正常情況下,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秒";
}
上述執行個體即為簡單的測試接口部分代碼,根據自己需求做修改即可;
作者:申文哲
出處:http://www.cnblogs.com/wenzheshen/
如果覺得這篇文章對你有小小的幫助的話,記得在右下角點個“推薦”哦,部落客在此感謝!❤
如果希望更容易地發現我的新部落格,記得在左下角點個“關注我”哦。❤(如有錯誤之處,還請指正!)