我現(xiàn)在采用的做法是在workerman中啟動(dòng)一個(gè)Timer來檢測queue進(jìn)程數(shù),如果進(jìn)程不足則重啟。但是這種輪詢很不優(yōu)雅。畢竟要等一輪interval才能進(jìn)行檢測。尤其是當(dāng)queue設(shè)置了--stop-when-empty選項(xiàng)時(shí),每次執(zhí)行完隊(duì)列會(huì)自動(dòng)退出進(jìn)程,那么下次有任務(wù)推入隊(duì)列時(shí),要保證隊(duì)列實(shí)時(shí)性就比較困難(假設(shè)interval設(shè)置得較大)。
我有個(gè)方案,workerman監(jiān)聽一個(gè)端口,并設(shè)置onClose回調(diào)。
laravel queue 進(jìn)程啟動(dòng)后發(fā)起一個(gè)連接連workerman這個(gè)端口。
如果laravel queue 進(jìn)程掛掉,那么連接也會(huì)close,workerman的onClose就會(huì)觸發(fā)。
onClose觸發(fā)時(shí)去檢查laravel queue 是否掛掉。這樣監(jiān)控是最實(shí)時(shí)的,但是挺麻煩的。
我現(xiàn)在還采用了另一個(gè)方案,啟動(dòng)queue進(jìn)程是永不退出的,workerman的工作進(jìn)程作為守護(hù)進(jìn)程來檢測queue進(jìn)程數(shù)量,這樣有queue進(jìn)程異常退出導(dǎo)致進(jìn)程數(shù)不足時(shí),workerman的工作進(jìn)程可以補(bǔ)足數(shù)量。這樣做可以把timer間隔設(shè)得比較大,事件推入隊(duì)列也是實(shí)時(shí)的,因?yàn)殡S時(shí)有隊(duì)列進(jìn)程在等著接收事件。唯一的缺陷是,我在worker stop --d的時(shí)候,如果想同步停止隊(duì)列,需要在onWorkerStop去調(diào)用一個(gè)shell腳本來kill隊(duì)列進(jìn)程,laravel queue本身也并沒有提供一個(gè)優(yōu)雅的stop方法,導(dǎo)致這個(gè)kill腳本很可能會(huì)執(zhí)行失敗,這個(gè)情況下,workerman會(huì)出現(xiàn)一個(gè)死循環(huán)的exit with status 9異常,不停寫日志,我前面好像發(fā)過issue?;蛘哒fkill時(shí)隊(duì)列里還有未完成的任務(wù),會(huì)積累到下次重啟隊(duì)列才能糾錯(cuò)。無論哪一種,都談不上優(yōu)雅。
是否可以在onWorkerStop 里面像隊(duì)列進(jìn)程發(fā)送一個(gè)停止的信號(hào),甚至可以是一個(gè)停止的隊(duì)列任務(wù)(這個(gè)隊(duì)列任務(wù)優(yōu)先級最高),從而讓隊(duì)列自己退出自己
用laravel Horizon 不是更好么,動(dòng)態(tài)進(jìn)程數(shù),而且進(jìn)程數(shù)我覺得開你能接受的最大就行,反正沒任務(wù)的時(shí)候進(jìn)程在阻塞掛起,幾乎不耗CPU
如果要將 Horizon 部署到一個(gè)正在運(yùn)行的服務(wù)器上,應(yīng)該配置一個(gè)進(jìn)程監(jiān)視器來監(jiān)視 php artisan horizon 命令,并在它意外退出時(shí)重新啟動(dòng)它。
結(jié)果Horizon自身進(jìn)程也需要被守護(hù),還是沒有解決問題。
當(dāng)然要用supervisor守護(hù)了,它干的就是這事,我司領(lǐng)導(dǎo)不想用supervisor我才用的workerman當(dāng)?shù)倪M(jìn)程守護(hù)工具