php中怎么使用fsockopen實現異步請求,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
php執行一段程序,有可能幾毫秒就執行完畢,也有可能耗時較長。
例如,用戶下單這個事件,如果調用了些第三方服務進行發郵件、短信、推送等通知,可能導致前端一直在等待。
而有的時候,我們并不關心這些耗時腳本的返回結果,只要執行就行了。這時候就需要采用異步的方式執行。
眾所周知,PHP沒有直接支持多線程這種東西。我們可以采用折衷的方式實現。這里主要說的就是fsockopen。
通過fsockopen發送請求并忽略返回結果,程序可以馬上返回。
示例代碼:
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET /backend.php HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
/*忽略執行結果
while (!feof($fp)) {
echo fgets($fp, 128);
}*/
fclose($fp);
}需要注意的是我們需要手動拼出header頭信息。通過打開注釋部分,可以查看請求返回結果,但這時候又變成同步的了,因為程序會等待返回結果才結束。
實際測試的時候發現,不忽略執行結果,調試的時候每次都會成功發送sock請求;但忽略執行結果,經??吹經]有成功發送sock請求。查看nginx日志,發現很多狀態碼為499的請求。
后來找到了原因:
fwrite之后馬上執行fclose,nginx會直接返回499,不會把請求轉發給php處理。
客戶端主動端口請求連接時,NGINX 不會將該請求代理給上游服務(FastCGI PHP 進程),這個時候 access log 中會以 499 記錄這個請求。
解決方案:
1)nginx.conf增加配置
# 忽略客戶端中斷 fastcgi_ignore_client_abort on;
2)fwrite之后使用usleep函數休眠20毫秒:
usleep(20000);
后來測試就沒有發現失敗的情況了。
附上完整代碼:
<?php
/**
* 工具類
* */
class FsockService {
public static function post($url, $param){
$host = parse_url($url, PHP_URL_HOST);
$port = 80;
$errno = '';
$errstr = '';
$timeout = 30;
$data = http_build_query($param);
// create connect
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
// send request
$out = "POST ${url} HTTP/1.1\r\n";
$out .= "Host:${host}\r\n";
$out .= "Content-type:application/x-www-form-urlencoded\r\n";
$out .= "Content-length:".strlen($data)."\r\n";
$out .= "Connection:close\r\n\r\n";
$out .= "${data}";
fwrite($fp, $out);
//忽略執行結果;否則等待返回結果
// if(APP_DEBUG === true){
if(false){
$ret = '';
while (!feof($fp)) {
$ret .= fgets($fp, 128);
}
}
usleep(20000); //fwrite之后馬上執行fclose,nginx會直接返回499
fclose($fp);
}
public static function get($url, $param){
$host = parse_url($url, PHP_URL_HOST);
$port = 80;
$errno = '';
$errstr = '';
$timeout = 30;
$url = $url.'?'.http_build_query($param);
// create connect
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
// send request
$out = "GET ${url} HTTP/1.1\r\n";
$out .= "Host:${host}\r\n";
$out .= "Connection:close\r\n\r\n";
fwrite($fp, $out);
//忽略執行結果;否則等待返回結果
// if(APP_DEBUG === true){
if(false){
$ret = '';
while (!feof($fp)) {
$ret .= fgets($fp, 128);
}
}
usleep(20000); //fwrite之后馬上執行fclose,nginx會直接返回499
fclose($fp);
}
}
?>看完上述內容,你們掌握php中怎么使用fsockopen實現異步請求的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。