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. ...
随机推荐
- 关于GMT UTC CST和Linux时区设置
GMT即格林威治时间:UTC即全球统一时间:GMT和UTC的时间是一样的 北京时间是东八区,即GMT+8或者UTC+8 CST:Central Standard Time (CST) is 6 hou ...
- MySQL存储引擎简介-MyISAM和InnoDB的区别
上篇文章<MySql逻辑结构简介>我们聊到了存储引擎,可以说MySQL可插拔的多元化存储引擎给我们的使用者带来了很灵活的选择. 这篇文章我们来聊一下目前主流的两种存储引擎MyISAM和In ...
- 使用asp.net core 3.0 搭建智能小车1
跟随.net core 3.0 一起发布的System.Device.Gpio 1.0已经可以让我们用熟悉的C#原汁原味的开发莓派上面的GPIO了.并且在 Iot.Device.Bindings这个包 ...
- SpringBoot 整合 Elasticsearch深度分页查询
es 查询共有4种查询类型 QUERY_AND_FETCH: 主节点将查询请求分发到所有的分片中,各个分片按照自己的查询规则即词频文档频率进行打分排序,然后将结果返回给主节点,主节点对所有数据进行汇总 ...
- RabbitMQ-交换机模式
在说正题之前先解释一下交换机模式是个笼统的称呼,它不是一个单独的模式(包括了订阅模式,路由模式和主题模式),交换机模式是一个比较常用的模式,主要是为了实现数据的同步. 首先,说一下订阅模式,就和字面上 ...
- [考试反思]0801NOIP模拟测试11
8月开门红. 放假回来果然像是神志不清一样. 但还是要接受这个事实. 嗯,说好听点,并列rank#7. 说难听点,垃圾rank#18. 都不用粘人名就知道我是哪一个吧... 因为图片不能太长,所以就不 ...
- 如何在 Spring/Spring Boot 中做参数校验?你需要了解的都在这里!
本文为作者原创,如需转载请在文首著名地址,公众号转载请申请开白. springboot-guide : 适合新手入门以及有经验的开发人员查阅的 Spring Boot 教程(业余时间维护中,欢迎一起维 ...
- JavaScript权威指南----一个JavaScript贷款计算器
废话不多说上例子代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- 测试工程师,选择python还是java?
问:“你平时工作中,用java多还是用python多”? 答:“都还可以,根据具体的场景选择不同的语言”. 问:“比如说呢”? 答:“开发自己的测试平台,肯定会选择java:在centos服务器跑一些 ...
- 1114作业 html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...