新聞中心
小編給大家分享一下Swoole自定義項目初始化事件處理的實現(xiàn)方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)的客戶來自各行各業(yè),為了共同目標(biāo),我們在工作上密切配合,從創(chuàng)業(yè)型小企業(yè)到企事業(yè)單位,感謝他們對我們的要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。專業(yè)領(lǐng)域包括網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、電商網(wǎng)站開發(fā)、微信營銷、系統(tǒng)平臺開發(fā)。
最近使用基于 Swoole 開發(fā)的 imi 框架開發(fā)項目,碰到一個需求,就是想要做項目初始化處理。當(dāng)初始化處理完成前,不想讓 Swoole 處理請求。因為可能有一些值沒有加載進(jìn)來,處理請求極有可能出現(xiàn)問題。
下面給出了思考過程及解決問題的demo代碼。
首先分析了一下,Swoole 是多進(jìn)程模式運行的,分為 Master
、Manager
、Worker
進(jìn)程。
Master 進(jìn)程就是我們啟動服務(wù)的 cli 命令文件所在進(jìn)程,在這里面初始化有一個問題,這里所有加載的類、全局變量,其它 Worker 進(jìn)程里都可以使用,無法熱重啟生效。
Manager 進(jìn)程的情況基本和上面差不多。
那么只有在 Worker 進(jìn)程做處理了,但如果寫在 WorkerStart 事件里,每個 Worker 進(jìn)程都會去執(zhí)行。
WorkerStart
事件定義:
function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id是一個從0-$worker_num之間的數(shù)字,表示這個Worker進(jìn)程的ID
那這個就好辦了,直接判斷workerid為0的去觸發(fā)項目初始化事件。剩下還有一個問題就是,如何在初始化執(zhí)行完成前,讓所有 Worker 進(jìn)程暫時都不處理請求。
思考并嘗試了一下,這個問題可以通過協(xié)程掛起來解決,demo 代碼如下:
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ù)觸發(fā)項目初始化事件 file_put_contents($initFlagFile, $server->manager_pid); // 當(dāng)前worker進(jìn)程恢復(fù)協(xié)程 resumeCos(); // 通知其它worker進(jìn)程 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進(jìn)程恢復(fù)協(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ā)框架,擁有常駐內(nèi)存、協(xié)程異步非阻塞IO等優(yōu)點。官方網(wǎng)站:https://imiphp.com'); }); $http->start(); /** * 處理項目初始化事件,比如這里延時5秒,模擬初始化處理 * * @return void */ function initApp() { $count = 5; for($i = 0; $i < $count; ++$i) { echo 'initing ', ($i + 1), '/', $count, PHP_EOL; sleep(1); } } /** * 恢復(fù)協(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 事件中判斷是否初始化完畢,如果沒有初始化完成,則掛起當(dāng)前協(xié)程,將協(xié)程ID加入全局變量。
當(dāng)?shù)?個 worker 進(jìn)程執(zhí)行完初始化后,通過向其他 worker 進(jìn)程發(fā)送消息,喚醒曾經(jīng)掛起的協(xié)程們,在初始化期間進(jìn)來的請求,這時候會被執(zhí)行。
以上是Swoole自定義項目初始化事件處理的實現(xiàn)方法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享文章:Swoole自定義項目初始化事件處理的實現(xiàn)方法
轉(zhuǎn)載注明:http://www.dlmjj.cn/article/pggsio.html