Laravel 使用 swoole 协程遇到的坑
最近在用laravel-s改造手头上的一个laravel项目,作为这块目前最火的轮子,确实好用,赞一下作者。由于目前所处理的项目需要调用大量api,使用同步串行调用效率低下,因此开始尝试使用swoole的协程客户端来调用api。
这里我本地的环境如下:
Component | Version |
---|---|
PHP | 7.1.17 |
Swoole | 2.1.2 |
Laravel Framework | 5.5.40 |
先来个demo体验一下:
<?php
namespace App\Http\Controllers;
class TestController extends Controller
{
public function index()
{
$cli = new \Swoole\Coroutine\Http\Client('127.0.0.1', 80);
$cli->setHeaders([
'Host' => 'test.me',
]);
$cli->get('/');
$result = $cli->body;
$cli->close();
return response()->json($result);
}
}
启动请求之后发现卡死,这下懵逼了,以前在其他地方都是可以用的协程客户端,这里不能用了,WTF。在群里求助,群主提及到不能在魔术方法和call_user_func之类的方法里使用(官方链接)。一语惊醒梦中人,laravel这个框架可是这类方法横行,于是研究了下Controller类的执行方式。框架在执行Controller时,会通过Illuminate\Routing\Controller
类的callAction
方法执行具体的Controller类的方法,而这个方法如下:
/**
* Execute an action on the controller.
*
* @param string $method
* @param array $parameters
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function callAction($method, $parameters)
{
return call_user_func_array([$this, $method], $parameters);
}
总算找到问题所在了,接下来便是解决问题。其实解决问题的方式swoole的文档里也写了,使用\Swoole\Coroutine::call_user_func
和\Swoole\Coroutine::call_user_func_array
代替即可。那么我们只需要在App\Http\Controllers\Controller
中重写一下callAction
方法,代码如下:
public function callAction($method, $parameters)
{
return \Swoole\Coroutine::call_user_func_array([$this, $method], $parameters);
}
注意如果在__call()
这样的魔术方法里面需要使用$obj->$method(...$arguments)
这种方式去处理用\Swoole\Coroutine::call_user_func_array
还是会出现问题。
Done!
目前只是遇到这个坑,以后遇到再更新。
本作品采用《CC 协议》,转载必须注明作者和本文链接
切到swoole 4吧, 这个问题就解决了
@JaguarJack 嗯
不错
@JaguarJack 试了swoole 4如果不修改call_user_func为swoole协程版,将触发报错
我是尝试在swoole 4中使用协程mysql查询
经过测试成功了。。。
这里只能写原生的嘛?