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知识,请拜访php教程!
以上就是php中使用fsockopen实现异步恳求(代码示例)的具体内容,更多请关注百分百源码网其它相关文章!