1. 程式人生 > >php 後端socket服務長連結,多併發開發備忘

php 後端socket服務長連結,多併發開發備忘


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