PHP非同步請求之fsockopen()方法詳解
阿新 • • 發佈:2019-01-03
正常情況下,PHP執行的都是同步請求,程式碼自上而下依次執行,但有些場景如傳送郵件、執行耗時任務等操作時就不適用於同步請求,只能使用非同步處理請求。
場景要求:
客戶端呼叫伺服器a.php介面,需要執行一個長達10s-20s不等的耗資源操作,假如客戶端響應請求時間為5秒(請求響應超時時間),5s以上無回覆即斷開連線。
解決設想:
客戶端呼叫a.php之後,a.php執行非同步多執行緒操作呼叫b.php,a.php呼叫成功後即刻反饋給客戶端回執,b.php自動執行耗資源操作。
方案:
利用fsockopen()方法解決PHP非同步請求
1.封裝非同步請求函式asyncRequest(),程式碼如下:
/** * php非同步請求 * @param $host string 主機地址 * @param $path string 路徑 * @param $param array 請求引數 * @return string */ private static function asyncRequest($host, $path, $param = array()){ $query = isset($param) ? http_build_query($param) : ''; Bd_Log::debug($query); $port = 80; $errno = 0; $errstr = ''; $timeout = 30; //連線超時時間(S) $fp = @fsockopen($host, $port, $errno, $errstr, $timeout); //$fp = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr, $timeout); if (!$fp) { Bd_Log::debug('連線失敗'); return '連線失敗'; } if ($errno || !$fp) { Bd_Log::debug($errstr); return $errstr; } stream_set_blocking($fp,0); //非阻塞 stream_set_timeout($fp, 1);//響應超時時間(S) $out = "POST " . $path . " HTTP/1.1\r\n"; $out .= "host:" . $host . "\r\n"; $out .= "content-length:" . strlen($query) . "\r\n"; $out .= "content-type:application/x-www-form-urlencoded\r\n"; $out .= "connection:close\r\n\r\n"; $out .= $query; $result = @fputs($fp, $out); @fclose($fp); return $result; }
例項:
正常介面a.php,如下
/** * 正常介面a.php * @param $host string 主機地址 * @param $path string 路徑 * @param $param array 請求引數 */ public function a(){ $param = array( 'XXX' => $XXX, ); $asyncData = $this->asyncRequest( $host, $path ,$param); echo'a.php success' }
耗時介面b.php,如下
/** * 耗時介面b.php,依次輸出三種結果 */ public function b(){ set_time_limit(0); ignore_user_abort(true);//設定與客戶機斷開是否會終止執行 fastcgi_finish_request();//提高請求的處理速度 sleep('30'); echo "耗時30秒"; sleep('20'); echo "耗時20秒"; sleep('10'); echo "耗時10秒"; }
上述例項即為簡單的測試介面部分程式碼,根據自己需求做修改即可;