この記事の内容は、Swooleカスタムプロジェクトの初期化イベント処理(コード)の実装方法に関するもので、ある程度の参考価値はありますので、困っている方は参考にしていただければ幸いです。
最近、Swooleをベースに開発したimiフレームワークを使ってプロジェクトを開発しているときに、プロジェクトの初期化処理をしたいという要件に遭遇しました。初期化プロセスが完了する前に Swoole にリクエストを処理させたくない場合があります。読み込まれていない値が存在する可能性があるため、リクエストの処理で問題が発生する可能性が高くなります。
問題を解決するための思考プロセスとデモ コードを以下に示します。
まず、分析後、Swoole はマルチプロセス モードで実行され、マスター プロセス、マネージャー プロセス、ワーカー プロセスに分割されます。
マスター プロセスは、サービスを開始する cli コマンド ファイルが配置されているプロセスです。ここでの初期化に問題があります。ロードされたすべてのクラスとグローバル変数は、他のワーカー プロセスで使用できますが、他のワーカー プロセスでは使用できません。ホットリスタートが有効になります。
Manager プロセスの状況は基本的に上記と同じです。
するとWorkerプロセスのみが処理を行うことになりますが、WorkerStartイベントに記述しておけば各Workerプロセスが実行することになります。
WorkerStart イベント定義:
function onWorkerStart(swoole_server $server, int $worker_id);
これは簡単に処理でき、workerid が 0 であることを直接判断します。プロジェクトの初期化イベント。残りの問題は、初期化の実行が完了するまですべてのワーカー プロセスがリクエストを処理しないようにする方法です。
考えて試してみた この問題はコルーチンをハングさせることで解決できます デモコードは以下の通りです:
<?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); } }
リクエストイベントで初期化が完了したかどうかを判定することで、初期化が完了していない場合はハングします 現在のコルーチンを開始し、コルーチン ID をグローバル変数に追加します。
0 番目のワーカー プロセスが初期化を完了すると、他のワーカー プロセスにメッセージを送信して、中断されていたコルーチンを起動します。初期化期間中に受信したリクエストはこの時点で実行されます。
関連する推奨事項:
カスタム イベントの JavaScript 実装の詳細な説明_JavaScript スキル
で Angularjs カスタム命令を使用する方法プロジェクトの使用
以上がSwoole カスタム プロジェクトの初期化イベント処理を実装する方法 (コード)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。