国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

調(diào)試busy進(jìn)程

有時(shí)候我們通過php start.php status 命令能看到有busy狀態(tài)的進(jìn)程,說明對(duì)應(yīng)進(jìn)程正在處理業(yè)務(wù),正常情況下業(yè)務(wù)處理完畢對(duì)應(yīng)進(jìn)程會(huì)恢復(fù)為idle狀態(tài),這一般情況下不會(huì)有什么問題。但是如果一直是busy狀態(tài)沒有恢復(fù)過idle狀態(tài),則說明進(jìn)程內(nèi)的業(yè)務(wù)有阻塞或者無限循環(huán),可以通過以下方法定位。

利用strace+lsof命令定位

1、status里找到busy進(jìn)程的pid
運(yùn)行php start.php status 后顯示如下

圖中busy的進(jìn)程的pid1172511748

2、strace 跟蹤進(jìn)程
挑選一個(gè)進(jìn)程pid(這里選擇11725),運(yùn)行strace -ttp 11725 顯示如下

可以看到進(jìn)程在不斷的循環(huán)poll([{fd=16, events=....的系統(tǒng)調(diào)用,這是在等待fd為16的描述符可讀事件,也就是在等這個(gè)描述符返回?cái)?shù)據(jù)。

如果沒有顯示任何系統(tǒng)調(diào)用,保留當(dāng)前終端,重新再打開一個(gè)終端,運(yùn)行kill -SIGALRM 11725(給進(jìn)程發(fā)送一個(gè)鬧鐘信號(hào)),然后看strace的終端是否有響應(yīng),是否阻塞在某個(gè)系統(tǒng)調(diào)用上。如果仍然沒有顯示任何系統(tǒng)調(diào)用說明程序很可能處于業(yè)務(wù)死循環(huán)中,參考頁面下部引起進(jìn)程長時(shí)間busy的其它原因 第2項(xiàng) 解決。

如果系統(tǒng)阻塞在epoll_wait或者select系統(tǒng)調(diào)用是正常情況,這說明進(jìn)程已經(jīng)處于idle狀態(tài)。

3、lsof 查看進(jìn)程描述符
運(yùn)行lsof -nPp 11725 顯示如下

述符16對(duì)應(yīng)的是16u的記錄(最后一行),能看fd=16的描述符是一個(gè)tcp連接,遠(yuǎn)程地址是101.37.136.135:80,說明進(jìn)程應(yīng)該是在訪問一個(gè)http資源,循環(huán)poll([{fd=16, events=....是一直在等待http服務(wù)端返回?cái)?shù)據(jù),這解釋了為什么進(jìn)程處于busy狀態(tài)

解決:
知道了進(jìn)程阻塞在哪里,接下來就容易解決了,例如上面經(jīng)過定位應(yīng)該是業(yè)務(wù)在調(diào)用curl,而對(duì)應(yīng)的url長時(shí)間沒有返回?cái)?shù)據(jù),導(dǎo)致進(jìn)程一直等待。這時(shí)候可以找url提供者定位url返回慢的原因,同時(shí)應(yīng)該在curl調(diào)用的時(shí)候加上超時(shí)參數(shù),比如2秒沒返回就超時(shí),避免長時(shí)間阻塞卡死(這樣進(jìn)程可能會(huì)出現(xiàn)2秒左右的busy狀態(tài))。

引起進(jìn)程長時(shí)間 busy 的其它原因

除了進(jìn)程阻塞或?qū)е逻M(jìn)程busy,還有以下原因會(huì)引起進(jìn)程處于busy狀態(tài)。

1、業(yè)務(wù)有致命錯(cuò)誤導(dǎo)致進(jìn)程不斷退出
現(xiàn)象: 這種情況下能看到系統(tǒng)負(fù)載比較高,status中的load average為1或者更高。能看到進(jìn)程的exit_count數(shù)字很高,并且不斷增長
解決: debug方式運(yùn)行(php start.php start不加-d)workerman看下業(yè)務(wù)報(bào)錯(cuò),把報(bào)錯(cuò)解決即可

2、代碼里無限死循環(huán)
現(xiàn)象: top中能看到busy進(jìn)程占用cpu很高,strace -ttp pid命令沒有打印出任何系統(tǒng)調(diào)用信息
解決: 參考鳥哥的文章通過gdb和php源碼定位,步驟總結(jié)大概如下:
1、php -v查看版本
2、下載對(duì)應(yīng)php版本的源碼
3、gdb --pid=busy進(jìn)程的pid
4、source php源碼路徑/.gdbinit
5、zbacktrace 打印調(diào)用棧
最后一步可以看到php代碼當(dāng)前執(zhí)行的調(diào)用棧,也就是php代碼死循環(huán)的位置。
注意:如果zbacktrace 沒有打出調(diào)用棧,可能你的php編譯時(shí)沒有加入-g參數(shù),需要重新編譯php,然后重啟workerman定位。

3、無限添加定時(shí)器
業(yè)務(wù)代碼不停的添加定時(shí)器又不刪除,導(dǎo)致進(jìn)程內(nèi)定時(shí)器越來越多,最終造成進(jìn)程無限運(yùn)行定時(shí)器。例如以下代碼:

$worker = new Worker;
$worker->onConnect = function($con){
    Timer::add(10, function(){});
};
Worker::runAll();

以上代碼在有客戶端連接上來后會(huì)增加一個(gè)定時(shí)器,但是整個(gè)業(yè)務(wù)代碼里沒有刪除定時(shí)器的邏輯,這樣隨著時(shí)間推移,進(jìn)程內(nèi)會(huì)不斷增加定時(shí)器,最終導(dǎo)致進(jìn)程無限運(yùn)行定時(shí)器導(dǎo)致busy。
正確的代碼:

$worker = new Worker;
$worker->onConnect = function($con){
    $con->timer_id = Timer::add(10, function(){});
};
$worker->onClose = function($con){
    Timer::del($con->timer_id);
};
Worker::runAll();
編輯于2024-03-13 17:37:18 完善本頁 +發(fā)起討論
贊助商