您好,登錄后才能下訂單哦!
小編給大家分享一下Swoole自定義項目初始化事件處理的實現(xiàn)方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
最近使用基于 Swoole 開發(fā)的 imi 框架開發(fā)項目,碰到一個需求,就是想要做項目初始化處理。當初始化處理完成前,不想讓 Swoole 處理請求。因為可能有一些值沒有加載進來,處理請求極有可能出現(xiàn)問題。
下面給出了思考過程及解決問題的demo代碼。
首先分析了一下,Swoole 是多進程模式運行的,分為 Master
、Manager
、Worker
進程。
Master 進程就是我們啟動服務的 cli 命令文件所在進程,在這里面初始化有一個問題,這里所有加載的類、全局變量,其它 Worker 進程里都可以使用,無法熱重啟生效。
Manager 進程的情況基本和上面差不多。
那么只有在 Worker 進程做處理了,但如果寫在 WorkerStart 事件里,每個 Worker 進程都會去執(zhí)行。
WorkerStart
事件定義:
function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id是一個從0-$worker_num之間的數(shù)字,表示這個Worker進程的ID
那這個就好辦了,直接判斷workerid為0的去觸發(fā)項目初始化事件。剩下還有一個問題就是,如何在初始化執(zhí)行完成前,讓所有 Worker 進程暫時都不處理請求。
思考并嘗試了一下,這個問題可以通過協(xié)程掛起來解決,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(); // 寫入文件,保證不再重復觸發(fā)項目初始化事件 file_put_contents($initFlagFile, $server->manager_pid); // 當前worker進程恢復協(xié)程 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進程恢復協(xié)程 resumeCos(); } }); $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { // 判斷未初始化完畢,則掛起協(xié)程 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 開發(fā)的協(xié)程 PHP 開發(fā)框架,擁有常駐內存、協(xié)程異步非阻塞IO等優(yōu)點。官方網站:<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); } } /** * 恢復協(xié)程 * * @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 事件中判斷是否初始化完畢,如果沒有初始化完成,則掛起當前協(xié)程,將協(xié)程ID加入全局變量。
當?shù)?個 worker 進程執(zhí)行完初始化后,通過向其他 worker 進程發(fā)送消息,喚醒曾經掛起的協(xié)程們,在初始化期間進來的請求,這時候會被執(zhí)行。
以上是Swoole自定義項目初始化事件處理的實現(xiàn)方法的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。