前言
項目是基于swoole開發(fā),框架也是公司內(nèi)自己開發(fā)的框架,并沒有用外界熱門的swoole框架,swoole是4.0.0版本。項目需要執(zhí)行大量的自動任務(wù),框架是通過swoole的sendMessage方法將需要執(zhí)行的任務(wù)給到worker執(zhí)行。然而最近卻發(fā)現(xiàn)一些自動任務(wù)會莫名丟失,并沒有執(zhí)行的情況。
排查歷程
在發(fā)現(xiàn)自動任務(wù)丟失的時候,我也是第一時間認為,可能需要執(zhí)行的任務(wù)代碼出現(xiàn)BUG,導(dǎo)致執(zhí)行失敗。但是經(jīng)過排查,任務(wù)代碼是沒毛病的,那究竟是哪里出現(xiàn)了問題,導(dǎo)致任務(wù)丟了呢?百思不得其解~
經(jīng)過不斷的溯源,終于查到了swoole的sendMessage方法處。先來看看swoole文檔的sendMessage介紹:

sendMessage方法是會返回一個布爾值,通過檢查發(fā)現(xiàn)丟失的任務(wù),都是因為sendMessage失敗了,根本就沒有觸發(fā)對應(yīng)worker的onPipeMessage事件。但是,知道的同時也開始納悶了,怎么就發(fā)送消息失敗了呢?返回值只有一個布爾值,去哪里獲取報錯信息?
swoole還提供了另外一個獲取報錯信息的方法,那就是getLastError。

getLastError能獲取最后一次操作的錯誤碼。但是經(jīng)過調(diào)試,發(fā)現(xiàn)一個很無奈的問題,getLastError獲取不到任何錯誤碼,也不清楚是什么問題導(dǎo)致獲取不到,這讓我甚是頭疼。
后來只能去查一下swoole的日志,看是否能看出點端倪,結(jié)果還真有所發(fā)現(xiàn)。

“output buffer overflow”,意思大概是輸出緩存區(qū)溢出。再對比getLastError有可能的報錯,有兩種可能:

然后查閱了一下文檔關(guān)于buffer_output_size:

意思是每次發(fā)送數(shù)據(jù)的上限值,出BUG有可能是因為這個問題,立馬去添加了項目的buffer_output_size配置,改為128M。但是任務(wù)仍舊會出現(xiàn)丟失的情況。
那么就可能是另外一個問題,那就是發(fā)送緩存區(qū)已滿。再次查閱swoole文檔,找到了一項配置socket_buffer_size:

就是說發(fā)送到worker時是先放入緩存區(qū),那么就有可能緩存區(qū)滿了,塞不進去的情況。死馬當(dāng)活馬醫(yī),立馬修改配置!
經(jīng)過長時間的觀察,任務(wù)不再出現(xiàn)丟失的情況。終于解決了這個頭疼的問題,Nice!!