Swoole自定义项目初始化事件处置的实现
下面给出了思索历程及解决问题的demo代码。
第一剖析了一下,Swoole 是多进程模式运转的,分为 Master
、Manager
、Worker
进程。
Master 进程就是我们启动效劳的 cli 命令文件所在进程,在这里面初始化有一个问题,这里所有加载的类、全局变量,其它 Worker 进程里都可以使用,没法热重新启动生效。
Manager 进程的状况根本和上面差不多。
那么只要在 Worker 进程做处置了,但假如写在 WorkerStart 事件里,每个 Worker 进程都会去施行。
WorkerStart
事件定义:
function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id是一个从0-$worker_num之间的数字,表示这个Worker进程的ID
那这个就好办了,直接推断workerid为0的去触发项目初始化事件。剩下还有一个问题就是,怎样在初始化施行完成前,让所有 Worker 进程临时都不处置恳求。
思索并尝试了一下,这个问题可以通过协程挂起来解决,demo 代码如下:
<?php use Swoole\Coroutine; $http = new swoole_http_server('127.0.0.1', 8080); $http->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进程复原协程 resumeCos(); // 通知其它worker进程 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')) { // 其它worker进程复原协程 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('IMI 是一款基于 Swoole 开发的协程 PHP 开发框架,具有常驻内存、协程异步非堵塞IO等长处。官方网站:<a href="https://imiphp.com" target="_blank">https://imiphp.com</a>'); }); $http->start(); /** * 处置项目初始化事件,比方这里延时5秒,模拟初始化处置 * * @return void */ function initApp() { $count = 5; for($i = 0; $i < $count; ++$i) { echo 'initing ', ($i + 1), '/', $count, PHP_EOL; sleep(1); } } /** * 复原协程 * * @return void */ function resumeCos() { define('APP_INITED', true); $coids = $GLOBALS['WORKER_START_END_RESUME_COIDS'] ?? []; fwrite(STDOUT, 'suspend co count: ' . count($coids) . PHP_EOL); foreach($coids as $id) { Coroutine::resume($id); } }
通过在 request 事件中推断可否初始化完毕,假如没有初始化完成,则挂起当前协程,将协程ID参加全局变量。
当第0个 worker 进程施行完初始化后,通过向其他 worker 进程发送新闻,叫醒曾经挂起的协程们,在初始化期间进来的恳求,这时候会被施行。
以上就是Swoole自定义项目初始化事件处置的实现的具体内容,更多请关注百分百源码网其它相关文章!