php中使用fsockopen实现异步请求(代码示例)
发布:smiling 来源: PHP粉丝网 添加日期:2022-05-26 10:41:55 浏览: 评论:0
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);
- }
- }
- ?>
Tags: fsockopen php异步请求
- 上一篇:php监听redis key失效触发回调事件
- 下一篇:最后一页
相关文章
- ·php fsockopen邮箱发送实例代码(2014-01-22)
- ·php中fsockopen模仿post与get详解(2014-08-27)
- ·php中fsockopen采集网页内容实例(2014-08-28)
- ·PHP利用socket模拟post之fsockopen发送数据(2014-09-05)
- ·php中fsockopen详细实例代码(2014-09-09)
- ·php fsockopen 伪造 post和get方法(2014-09-09)
- ·php fsockopen解决办法 php实现多线程(2020-08-28)
- ·php定时计划任务与fsockopen持续进程实例(2021-01-10)

推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)