php 後端socket服務長連結,多並發開發備忘_PHP教程

來源:互聯網
上載者:User
[php]
//保證子進程上限
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;
}
}

//保證子進程上限
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每秒的請求。應該還可最佳化。

http://www.bkjia.com/PHPjc/477526.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/477526.htmlTechArticle[php] //保證子進程上限 if($this-_maxFork 0 $this-_children $this-_maxFork) { Yii::log(_children .$this-_maxFork,CLogger::LEVEL_WARNING,__METHOD__); $this-handler(SIGCHLD); u...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.