hyperf命令行与协程
背景
需要自定义命令行Command 启动附属的Server服务
记录一下引发的几个问题
无法启动
产生报错
Swoole\Server::start(): eventLoop has already been created, unable to start Swoole\Server
原因:Command中已经开启了协程无法再监听server
Co::create(function(){ $server = new Server('0.0.0.0', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP); $server->start(); });
处理方案,在Command类中定义属性,关闭协程
class StartCommand extends HyperfCommand { /** * Execution in a coroutine environment. */ protected $coroutine = false; // ..... }
关闭协程后的问题
查看hyperf-command组件代码 核心如下
if ($this->coroutine && ! Coroutine::inCoroutine()) { run($callback, $this->hookFlags); return $this->exitCode; } return $callback();
开启了协程之后会传递hookFlags参数
在关闭协程之后 一些心跳函数里我写了如下代码
Coroutine::create(function(){ while(true){ // foreach send \Hyperf\Utils\Coroutine::sleep(3); } });
但是由于默认没有hook了,而Hyperf utils中使用的不是Swoole提供的sleep函数,所以会造成进程堵塞。导致其他逻辑无法运行。
解决方案:在server set里设置hook
$server->set([ 'worker_num' => 2, 'daemonize' => $daemon, 'enable_coroutine' => true, 'hook_flags' => swoole_hook_flags(), ]);