最近使用基于Swoole开发的imi框架开发一个项目,遇到一个需求,就是想做项目初始化处理。在初始化处理完成之前,您不希望Swoole处理请求。因为可能有一些值没有加载,大概率会在处理请求时出现问题。下面给出了思考过程和解决问题的演示代码。首先经过分析,Swoole运行在多进程模式下,分为Master、Manager、Worker进程。Master进程就是我们启动服务的cli命令文件的进程。这里初始化有问题。这里加载的所有类和全局变量都可以在其他Worker进程中使用,热重启不能生效。Manager进程的情况和上面基本一样。那么只处理Worker进程,但是如果写在WorkerStart事件中,每个Worker进程都会去执行。WorkerStart事件定义:functiononWorkerStart(swoole_server$server,int$worker_id);$worker_id是0-$worker_num之间的一个数字,表示Worker进程的ID,那么这个好办,直接判断workerid为0触发项目初始化事件。剩下的问题就是如何在初始化执行完成之前,让所有的Worker进程暂时不处理请求。经过思考和尝试,这个问题可以通过挂起协程来解决。演示代码如下:on('WorkerStart',function(swoole_http_server$server,$workerId){$initFlagFile=__DIR__.'/init.flag';if(0===$server->worker_id&&(!is_file($initFlagFile)||file_get_contents($initFlagFile)!=$server->manager_pid)){//句柄项目初始化事件initApp();//写文件保证项目初始化事件不会重复触发file_put_contents($initFlagFile,$server->manager_pid);//当前worker进程恢复coroutineresumeCos();//通知其他工作进程for($i=1;$i<$server->setting['worker_num'];++$i){$server->sendMessage('init',$i);}}});$http->on('PipeMessage',function(swoole_http_server$server,$srcWorkerId,$data){if(0===$srcWorkerId&&'init'===$data&&!defined('APP_INITED')){//其他工作进程恢复协程resumeCos();}});$http->;on('request',function(swoole_http_request$request,swoole_http_response$response){//判断初始化未完成,暂停协程if(!defined('APP_INITED')){$GLOBALS['WORKER_START_END_RESUME_COIDS'][]=Coroutine::getuid();Coroutine::suspend();}$response->header('content-type','text/html;charset=utf-8');$response->end('IMIis一个基于Swoole的协程PHP开发框架,具有常驻内存、协程异步非阻塞IO等优点。官网:
