美文网首页
听欢哥讲PHP之异步是怎么玩的

听欢哥讲PHP之异步是怎么玩的

作者: 司马东阳 | 来源:发表于2017-05-27 11:53 被阅读180次

PHP异步

PHP是世界上最好的语言,但是总被“同行们”吐槽不支持异步。其实我们要实现异步也非常简单,之前看到鸟哥的一篇写PHP异步执行的博文 PHP实现异步调用方法研究,这篇文章还是08年的,到今天PHP发展快10年了,对于异步调用也有了更多新的玩法。

一. 先说说鸟哥文章中的几种玩法:

一是通过渲染前端页面,使用js执行Ajax,这种方式现在还适用。只是受限于业务场景,因为只能在浏览器中调用,遇到接口请求就不行了。

二是通过popen()方法打开一个指向进程的管道,每个请求会多起一个进程。忽略进程来看最主要的原因是数据的传输特别不方便,使用场景有限。

三是使用CURL扩展,通过设置timeout超时参数,能实现离弦之箭的效果。不过这种方法会主动断开连接。被调用的服务如果有做连接检测,也会中断服务端脚本的执行。比如我们请求

微信的某个费时接口(20s),我们调用1s就断开连接,微信端是否会维持请求执行20S是不可控的。所以这种方法不推荐大家使用。

四方法与CURL类似,通过fsockopen创建socket连接访问远程服务,不循环获取请求结果。一样会有三中连接被断开的问题。

二. PHP发展了这么多年对异步支持方面都有哪些改进?

CURL扩展已支持毫秒配置,将 CURLOPT_TIMEOUT 改为 CURLOPT_TIMEOUT_MS 即可生效(cURL 版本 >= libcurl/7.21.0,老服务器要检查版本),但还是我前面说的需要服务端配合,不然接口的调用结果不可控。

CURL扩展已支持并发,我们能一次访问N个接口,执行时间取最长接口的时间。比如我们能一次访问 京东支付(1s),微信支付(1.2s),支付宝(0.8s)不同服务的三个接口,总耗时才1.2s。详细用法 curl_multi_init

类似Node.js的异步IO框架Swoole,能很好的实现异步调用;不过Swoole理论上不能算PHP框架,他算是PHP功能的扩展。所以除非项目都用Swoole写,不然也是享受不到异步IO的福利。

对yield的支持,能实现调度器的功能,写单进程的服务时能大展拳脚,特别是实现协程,异步更不在话下。不过在多进程的web服务上没有太大的使用场景,看未来会不会有新的玩法吧。

当然还有很多新的特性,这里不再细说,总之PHP越是被黑越是能快速发展。

三. 最好的异步实现方法

我们都知道PHP是支持多进程编程的,那完全可以新建一个进程去实现异步的调用。比如调用popen()方法,但是管道的方式传参异常麻烦,不过多进程这个方法是绝对可行的。如果要实现多进程的功能,毫无疑问我们会选择PHP官方提供的 pcntl 扩展,PHP默认会安装pcntl扩展,如果代码运行提示找不到pcntl扩展,可自行到php-src下载,选择好版本通过phpize安装即可。代码如下

0){            pcntl_wait($status);        }elseif($pid ==0){            $cid = pcntl_fork();if($cid >0){//这里放空            }elseif($cid ==0){                $rb();            }else{exit();            }        }else        {exit();        }    }}//离弦之箭---调用方法$time_out =30;Arrow::getInstance()->run(function()use($time_out){//这里写我们要执行的代码

sleep($time_out);

});

我给这个功能取了一个很生动的名字--离弦之箭。代表异步调用,我们的弓箭射出去后并不关心它的结果因为发送这个动作做了就行。比如打个10M的log,通知10个人(发10条短信)。

代码说明:首先Arrow类是个单例类,减少多次调用的开销。run()方法传递的是一个匿名函数,这样我们能非常方便的传递参数,并且保留上下文。

这个类最难的地方在于多进程的处理。因为我们要尽可能快的将数据返回给用户,所以主进程越快结束越好。但是我们又需要子进程来执行我们耗时的操作,执行完退出才行。如果不等子进程执行完就将父进程退出会出现什么结果呢?结果就是子进程会常驻内存变成僵死进程。那我们有什么办法让子进程执行完之后就自动结束呢?答案是很难……那么儿子进程这么不听话,孙子进程会不会听话一点呢??答案是孙子进程执行结束后会被系统进程回收并销毁(还是孙子听话)。所以我在代码中使用了如下方法:当前请求进程fork出子进程,子进程fork出孙子进程,主进程和子进程都先行退出,最后由孙子进程来执行耗时操作,最后完美的解决了僵死进程问题。

当然这个方法的缺点就是调用的时候会多产生一个php-fpm的进程。关于php-fpm进程的管理和规划又是另一个话题了。扩展阅读 PHP进程间通信

更多PHP相关技术请搜索千锋PHP,做真实的自己,用良心做教育

相关文章

  • 听欢哥讲PHP之异步是怎么玩的

    PHP异步 PHP是世界上最好的语言,但是总被“同行们”吐槽不支持异步。其实我们要实现异步也非常简单,之前看到鸟哥...

  • 听欢哥讲PHP之ajax

    XMLHttpRequest cannot load file:///D:/WWW/angularlx/ui-ro...

  • 听欢哥讲PHP之魔术方法

    魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,在此做了下总结,向大家分享下 ...

  • 听欢哥讲PHP之cookie问题

    PHP中的cookie必须刷新才能生效的问题,``` 这里输入代码 // php COOKIE设置函数立即生效,...

  • 听欢哥讲PHP之nginx配置

    假设我们用PHP实现了一个前端控制器,或者直白点说就是统一入口:把PHP请求都发送到同一个文件上,然后在此文件里通...

  • 听欢哥讲PHP之header头信息

    header函数在php中是发送一些头部信息的, 我们可以直接使用它来做301跳转等,下面我来总结关于header...

  • 听欢哥讲PHP之轻松搞定cURL

    cURL是一个利用URL语法规定来传输文件和数据的工具,支持很多协议和选项,如HTTP、FTP、TELNET等,能...

  • 听欢哥讲PHP之nginx配置直播服务

    近年互联网直播业务非常火热。我也研究了下,发现nginx上配置视频直播点播也很容易实现,特分享一下。 一、ubun...

  • 听欢哥讲PHP之轻松搞定依赖注入

    看到网络上很多“依赖注入”解释的话题,这篇博客呢也只是我自己的观点,如果你有不同的观点请拍砖,不用客气。 业务场景...

  • 听欢哥讲PHP页面静态化

    页面静态化 1、什么是PHP静态化 PHP静态化的简单理解就是使网站生成页面以静态HTML的形式展现在用户面前。 ...

网友评论

      本文标题:听欢哥讲PHP之异步是怎么玩的

      本文链接:https://www.haomeiwen.com/subject/zfqqfxtx.html