如果有仔細(xì)看過 swoole task 的文檔的話,應(yīng)該都會(huì)注意到這句話
task操作的次數(shù)必須小于onTask處理速度,如果投遞容量超過處理能力,task會(huì)塞滿緩存區(qū),導(dǎo)致worker進(jìn)程發(fā)生阻塞。
worker進(jìn)程將無法接收新的請(qǐng)求 (推薦學(xué)習(xí): swoole視頻教程)
task 如果阻塞會(huì)引發(fā) woker 進(jìn)程阻塞,造成服務(wù)無法工作,引發(fā)問題。
我曾經(jīng)使用 task 發(fā)送服務(wù)的鏈路日志,接收日志的服務(wù)出現(xiàn)bug,造成發(fā)送日志的 task 阻塞,然后服務(wù) gg 的情況,之后我就對(duì) task 做了一波優(yōu)化。
思路就是使用 swoole channel 和 swoole user process 實(shí)現(xiàn)一套 task 。
使用 channel 接收數(shù)據(jù),然后在 user process 消費(fèi)數(shù)據(jù),假如 channel 滿了僅僅會(huì)造成 push 數(shù)據(jù)失敗,并不會(huì)引發(fā)阻塞,因?yàn)槭擎溌啡罩?,是允許丟失的,所以這個(gè)方案完全沒問題。
在swoole user process 消費(fèi) channel 的策略的偽代碼如下
$sleepTime = 5; $maxSleepTime = 100; while (true) { $task = $chan->pop(); if ($task === false) { $sleepTime = $sleepTime + 5; if ($sleepTime > $maxSleepTime) { $sleepTime = $maxSleepTime; } usleep($sleepTime * 1000); continue; } $sleepTime = 0; // 處理數(shù)據(jù) }
如果消費(fèi)到channel的數(shù)據(jù),就使用死循環(huán)處理數(shù)據(jù),因?yàn)樘幚頂?shù)據(jù)過程中是有其他操作的,所以并不會(huì)占用大量 cpu。
如果消費(fèi)不到數(shù)據(jù),就 sleep 5ms,sleep的時(shí)間依次累加,直到達(dá)到最大值 100ms,達(dá)到 cpu 使用率和處理數(shù)據(jù)實(shí)時(shí)性的一個(gè)平衡,具體平衡點(diǎn)可以根據(jù)自己的業(yè)務(wù)按需調(diào)整。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com