php为什么需要异步编程?php异步编程的详解(附示例)
我对 php 异步的知识还比较混乱,写这篇是为了整理,可能有错。
传统的 php-fpm 一个进程执行一个请求,要达到多少并发,就要生成多少个进程。更糟糕的是每次请求都需要重新编译执行,导致并发一直上不来。因此出现了 Swoole 和 WorkerMan 两个国内流行的常驻内存框架[1]。这两个框架原理都是通过事件循环,让程序一直停留在内存,等待外部请求,达到高并发。
为什么需要异步
先来看一个例子
在工作目录下新建文件 slowServer.php
|
1 2 3 |
|
开启服务
|
1 |
|
开另一个终端,安装依赖
|
1 2 3 |
|
新建文件 worker.php
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
开启服务器
|
1 |
|
在浏览器开启两个标签,都打开网址 http://localhost:8082 。这时可以看到终端输出“1”,过了一会儿又输出“1”,原因是8081服务器在处理第一个请求的时候阻塞在了等待8081返回之中,等第一个请求结束后,才开始处理第二个请求。也就是说请求是一个一个执行的,要达到多少个并发,就要建立多少个进程,跟 php-fpm 一样。现在修改一下代码
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
现在打开服务,再在浏览器发起请求,发现第二个“1”在请求后就马上输出了,而这时第一个请求还没结束。这表明进程不再阻塞,并发量取决于 cpu 和 内存,而不是进程数。
为什么需要异步
通过上面的例子已经很明白了,reactphp 框架通过把 http 请求变成异步,让 onMessage 函数变成非阻塞,cpu 可以去处理下一个请求。即从 cpu 循环等待 8081 返回,变成了 epoll 等待。
异步的意义在于把 cpu 从 io 等待中解放出来,可以处理其他计算任务。 如果你想知道怎么用框架实现异步,看到这里就可以了。WorkerMan 配合 ReactPHP 或者自身的 AsyncTcpConnection 已经可以满足很多 io 请求异步化的需求。下面继续讨论这些框架是怎么做到异步的。
哪些地方应该被做成异步
通过上面的例子已经知道一旦执行到不需要 cpu,但是要等待 io 的时候,应该把 io 的过程做成异步。
实现事件循环
上面的例子是通过 reactphp 把 http 请求变成了异步,其实 WorkerMan 框架本身也是异步的,下面来看看 WorkerMan 是怎么使 onMessage 函数可以异步接受请求。先来新建下面这个文件 react.php
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
开始执行
|
1 |
|
在另一个终端执行
|
1 |
|
这时就会看到第一个终端输出'1'。
我之前写过一篇文章《php使用epoll》,是这篇文章的基础。那篇文章里事件回调是通过定时来实现,即
|
1 |
|
而这里,事件回调是通过检测 fd 是否有写入内容来实现,这个过程不需要 cpu 参与。当 fd 有内容写入时,会调函数 'react',这时开始使用 cpu。如果这时候进程执行另一个异步请求,比如用 reactphp 框架请求一个网页,那么程序会让出 cpu,此时如果有另一个请求进来,就可以回调执行另一个 'react' 函数。由此提高了并发量。
协程
生成器 Generater
这是生成器的 PHP 官方文档 http://php.net/manual/zh/lang...
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
生成器就是每次程序执行到 yield 的时候保存状态,然后返回 $i,是否继续执行 gen_one_to_three 里的循环,取决于主程序是否继续调用
什么是协程
上面的程序另一种写法是
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
由此可见,协程就是一种对函数的封装,使其变成一种可以被中断的函数,行为更像是子进程或子线程,而不是函数。协程的具体写法这里不细写,因为协程的写法十分复杂,可能需要再做一层封装才能好用。
协程与异步
既然协程可以被中断,那么只要在程序发起请求后发起事件循环,然后用 yield 返回,然后程序继续执行主程序部分,等事件返回后触发函数,执行 Generatot::next() 或 Generator::send() 来继续执行协程部分。封装好后就好像没有异步回调函数一样,和同步函数很像。
现在已经有 ampphp 和 swoole 两个框架封装了协程,有兴趣可以了解一下。

明确的学习思路能更高效的学习

php为什么需要异步编程?php异步编程的详解(附示例)的更多相关文章
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Python编程之列表操作实例详解【创建、使用、更新、删除】
Python编程之列表操作实例详解[创建.使用.更新.删除] 这篇文章主要介绍了Python编程之列表操作,结合实例形式分析了Python列表的创建.使用.更新.删除等实现方法与相关操作技巧,需要的朋 ...
- VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三
目录 目录 前文列表 VixDiskLib 虚拟磁盘库 VixDiskLib_GetMetadataKeys VixDiskLib_ReadMetadata 获取虚拟磁盘元数据 VixDiskLib_ ...
- VMware 虚拟化编程(6) — VixDiskLib 虚拟磁盘库详解之二
目录 目录 前文列表 VixDiskLib 虚拟磁盘库 VixDiskLib_Open 打开 VMDK File VixDiskLib_Read 读取 VMDK File 数据 VixDiskLib_ ...
- VMware 虚拟化编程(5) — VixDiskLib 虚拟磁盘库详解之一
目录 目录 前文列表 VixDiskLib 虚拟磁盘库 虚拟磁盘数据的传输方式 Transport Methods VixDiskLib_ListTransportModes 枚举支持的传输模式 Vi ...
- Java程序设计(2021春)——第一章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第一章课后题(选择题+编程题)答案与详解 第一章选择题 1.1 Java与面向对象程 ...
- Java程序设计(2021春)——第二章课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第二章课后题(选择题+编程题)答案与详解 第二章选择题 2.1 面向对象方法的特性 ...
- Java程序设计(2021春)——第四章接口与多态课后题(选择题+编程题)答案与详解
Java程序设计(2021春)--第四章接口与多态课后题(选择题+编程题)答案与详解 目录 Java程序设计(2021春)--第四章接口与多态课后题(选择题+编程题)答案与详解 第四章选择题 4.0 ...
- python异步并发模块concurrent.futures入门详解
concurrent.futures是一个非常简单易用的库,主要用来实现多线程和多进程的异步并发. 本文主要对concurrent.futures库相关模块进行详解,并分别提供了详细的示例demo. ...
随机推荐
- React + MobX 状态管理入门及实例
前言 现在最热门的前端框架,毫无疑问是React. React是一个状态机,由开始的初始状态,通过与用户的互动,导致状态变化,从而重新渲染UI. 对于小型应用,引入状态管理库是"奢侈的&qu ...
- Java基础(三十六)日期和时间
1.Date类 (1)无参数构造方法创建的对象可以获取本机当前时间 (2)有参数构造方法创建的对象表示举例计算机系统自身时间的距离为给定的参数 Date date = new Date(); // 当 ...
- UITabView
UITabView可是实现列表功能,此文转自https://www.cnblogs.com/longiang7510/p/5367080.html,讲述很详细,都有注视,但是注释解释不太确切,可以自行 ...
- 消息中间件-RabbitMQ环境搭建
一直在传统行业工作(早九晚五不加班),没有考虑消息中间件的性能,所以一直再用activeMQ也没有想过学习别的中间件,时间长也没什么技术上的进步,而且感觉到了 工作的麻木,所以决定学一些新的技术(其实 ...
- Linux常见命令之文件处理命令
ls命令 ls(选项)(参数) 选项 -a:显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为影藏,不会列出): -A:显示除影藏文件“.”和“..”以外的所有文件列表: -C:多列显示输出 ...
- 聊聊 Vue 中 provide/inject 的应用
众所周知,在组件式开发中,最大的痛点就在于组件之间的通信.在 Vue 中,Vue 提供了各种各样的组件通信方式,从基础的 props/$emit 到用于兄弟组件通信的 EventBus,再到用于全局数 ...
- USDT跑分系统开发
USDT跑分系统开发找[林生:178-7666-2415微/电],USDT跑分系统开发,USDT跑分系统解决方案,USDT跑分系统定制,小程序开发.APP.公众号等软件开发. 数字资产结算通道的特点: ...
- [考试反思]1015csp-s模拟测试75:混乱
赶上一套极其傻逼的题(是傻逼,不是简单) T1超级卡精 T2模拟(输出卡"0.0"与"-0.0"不开spj),而且数据诡异乱打就能A(貌似给这道题的时间越长分越 ...
- [考试反思]0902NOIP模拟测试35:摆动
skyh/Mr.zkt214 cbx204 6个200 4个180 172 162 我:rank16,160 呃,可以看到这个分差.... 对了教练说了两句话需要记录一下: 1.不要因为一时情绪而作出 ...
- Maven多模块项目介绍和搭建
http://www.open-open.com/lib/view/open1418263515855.html