我正在为Laravel 5构建一个WebSocket Server包(包装在Ratchet周围,对于我的侦听命令,我想提供将其作为后台守护进程运行的选项,这样Ratchet循环就可以继续运行,而用户仍然可以输入新命令(就像L5为队列提供这个选项一样:工作命令),然而,我不知道如何做到这一点,谷歌搜索对我没有任何帮助。
非常感谢任何建议!
简单的答案是:不要让脚本终止。
这比听起来更难,有几种方法可以做到这一点。一些脚本会立即分叉到多个进程中,其中"主"进程充当从子进程(实际完成工作)到终端(用于输出)的信息运送器。这种方法的缺点是进程间通信(设置信号处理程序等)所需的复杂性增加。
我所知道的所有解决方案或多或少都可以归结为一个连续的循环结构:
while(true)
{
doWork();
sleep(1);
}
这是一个守护进程。一旦开始,它就永远活着。每隔一秒钟,它就会醒来并doWork
。缺点是,一旦启动,停止它的唯一方法就是中断它(Ctrl-C),或者,如果启动并从终端释放($ php myscript.php &
),则使用真正丑陋的锤子和进程id的kill
,并将为您提供一种"干净"的方式来关闭流程。
另一个潜在的问题是,如果doWork
方法的运行时间超过一秒钟,那么循环将不再每秒执行一次(或多或少)。如果需要任何形式的同步性,这可能是一个问题。
在Laravel的上下文中,在命令的fire
方法内部,您只需要其中的一些内容(例如无限的while
循环)来阻止命令返回。
不过,我给你的建议是,不要重新发明轮子。PHP的WebSockets已经解决。
更新
如果您正在围绕Ratchet构建一个包装器,那么Ratchet已经解决了守护进程问题。您只需要设置服务器对象并将其告知run()
,这就是导致阻塞执行的原因。以类似的手工命令为例:
use Ratchet'Http'HttpServer;
use Ratchet'Server'IoServer;
use Ratchet'WebSocket'WsServer;
// Setup the Ratchet Server.
$server = IoServer::factory(
new HttpServer(
new WsServer(
$messenger
)
),
$port
);
$server->run();
// You won't reach this line unless the server crashes
第一个比特构造了我保存在服务提供商中的服务器,第二个比特实际上在手工命令中。$messenger
变量是我对Ratchet'MessageComponentInterface
的实现。
我的观点是,您不需要守护进程来为Ratchet编写包装器。棘轮已经给你一个了。