php 後端socket服務長連結,多併發開發備忘
阿新 • • 發佈:2019-02-06
//保證子程序上限 if($this->_maxFork >0 && $this->_children > $this->_maxFork) { Yii::log("_children > ".$this->_maxFork,CLogger::LEVEL_WARNING,__METHOD__); $this->handler(SIGCHLD); // usleep(200); continue; } /** * 監控訊號 * @param object socket $clientt * @return boolean */ public function handler($signo) { Yii::log("handler {$signo} ",CLogger::LEVEL_INFO, __METHOD__); switch(intval($signo)) { case SIGCLD: case SIGCHLD: Yii::log("SIGCHLD sub proccess ",CLogger::LEVEL_TRACE, __METHOD__); //正常退出 //declare = 1, that means one signal may be correspond multi-process die while( ($pid = pcntl_wait($status, WNOHANG|WUNTRACED)) > 0 ) { if (FALSE === pcntl_wifexited($status)) { Yii::log("sub proccess {$pid} exited unormally with code {$status}",CLogger::LEVEL_WARNING, __METHOD__); } else { Yii::log("sub proccess {$pid} exited normally",CLogger::LEVEL_INFO, __METHOD__); } $this->_children--; } break; case SIGINT: case SIGQUIT: case SIGHUP: //異常退出 $this->_cleanup(); exit(0); break; default: break; } }
【多程序方式注意點】 變數共享問題
因為是程序,可以理解成主程序的一個拷貝,執行是從呼叫 pcntl_fork() 後各主、子程序後自往後執行,避免子程序層層巢狀,一般子程序執行完後是用exit(0)來退出。 子程序如果執行過程中崩潰不會影響到主程序,也不能和主程序共享變數。訊號和select 衝突問題
pcntl_signal 註冊訊號後會和 stream_select 有衝突 PHP Error[2]: stream_select(): unable to select [4]: 被中斷的系統呼叫 (max_fd=10) 目前沒找到解決方法,未採用 pcntl_signal 進行監控。
子程序通過exit退出後,會變成殭屍程序,需要通過 pcntl_wait 來進行回收。 centos 測試中發現最大的程序上限是3.2萬,通過設定子程序總數,大於設定值再呼叫 pcntl_wait 來進行回收socket讀寫注意
多程序情況下,會出現對同個socket控制代碼,有多個程序同時在讀的問題。 解決方法是讀操作在主程序裡,讀出所有資料後,拋給子程序進行執行。檔案操作注意
filesize 函式在多程序情況下會出現取不到或取到的檔案大小一直不變問題 這裡採用直接呼叫 linux下的系統函式解決。$file_size = @filesize($logFile);
//解決併發情況下取不到檔案大小問題
if(0 == $file_size ||$this->_prevFileSize == $file_size )
{
$file_size = @exec('/usr/bin/stat -c %s '. escapeshellarg($logFile));
clearstatcache();
}
壓力測試後1000的併發可達到350每秒的請求。應該還可優化。