PHP 的协程库

Pader2020年12月25日 发表于 网页与编程 php coroutine

协程是当下火热的概念,尤其是 NodeJS 和 Go 语言的流行将协程彻彻底底的带入了大家的视野。然后大家这才意识到,在绝大多数面向服务端的程序中,阻塞式的 IO 才是并发最大的原罪。

异步

协程的基础是异步,异步在程序等待 IO 的空闲时不浪费 CPU 继续执行其它的工作,配合 epoll/kqueue/iocp 等多路复用的技术能够实现在单个线程上处理巨量的连接和并发。但异步的基础编程方式是回调,实际的实践中,面对大量的回调地狱开发过程痛苦至极。

协程

很早以前我就在想,回调的形式是否可以通过保存栈状态再恢复的形式转变为同步的编程形式呢?

现在的协程就是通过保存和恢复调用栈或其它形式做到将异步转变为同步的编程形式,让异步编程真真正正的实用起来。

PHP 的情况

在目前流行的这些语言中,我认为 PHP 是最需要协程功能的。PHP 默认的 fpm 模式下,多进程单线程阻塞式运行,且相关资源在访问时反复的创建和销毁,都是 PHP 面对高并发和自足性时最大的弱点。虽然近些年 PHP 7 和刚发布的 PHP 8 对本身的执行性能有了非常大的提升,但是也仅仅是执行的速度快了,对于这种高并发 IO 的场景从本质上来讲几乎没有帮助。而其它的语言,如 JS 的天生异步,或者 Java 通过相对较少的资源创建多线程来处理请求,他们在这种情况下都可以通过长驻来创建连接池的等各种形式大大减少每一次请求过程中的一些不必要的性能浪费。

对比之下 PHP 由于其简单,开发快速的特性成为很多公司创业初期的选择,但在业务成熟,复杂度、性能压力上升之后,很多公司都会转向其它语言。这也是 PHP 非常尴尬的一点,官方在这一块好像也不希望 PHP 过于复杂或是其它考虑而无动于忠,反倒执着于 PHP 语言本身的执行性能不能自拨。

PHP 的协程

不过现在情况已经有了改观,协程的趋势势不可挡,PHP 界的各路神通纷纷通过各种形式为 PHP 提供了协程的支持。在有了协程后 PHP 拥有了更多的可能,不仅仅是并发性能达到甚至远超其它语言,还能在业务上摆脱对 Crontab, Nginx 等等各种工具的强依赖实现功能上的自足。

PHP 的协程基础上有两种实现方案,一种是通过 C/C++ 的扩展来实现,另一种是通过 PHP 的生成器和 yield 来做到让出和恢复执行来做到,具体要参考这篇文章

PHP 的协程列表

  1. Swoole - 国内大名鼎鼎的 Socket 编程和协程库,是一个基于 C/C++ 编写的扩展,提供异步的 Socket 客户/服务端,提供隐式协程的支持,并且能够一键协程化 PHP 内置的数据库,CURL,Redis 等客户端,最大化的复用 PHP 现有生态。

  2. Swow - Swoole 的简化版本,最小纯 C 核心 Socket 编程及协程库扩展,如果作为语言的特性,本身的简洁很重要。

  3. Parallel - C 扩展并发库,提供了 Future 等概念的实现,此扩展提供的功能更像是一个线程池。

  4. Fiber - 一个轻量级的类似绿色线程/纤程的实现,能够实现对任何 IO 协程化,该扩展在未来有望进入 PHP 主干,目前该扩展由 Amphp 维护,Amphp v3 将基于该扩展(进入主干的话)。

  5. Amphp - 纯 PHP 实现的协程库,Amphp 不仅提供了协程的实现,还提供了大量协程相关的组件生态,如纯 PHP 实现的协程数据库客户端,Http 客户端,连接池等等等等,是最具实用价值的纯 PHP 协程库。

  6. sabre/event - 一个简单的纯 PHP 协程库,类似于 JS 的相关实现,如 Promise, setTimeout, setInterval 等等。

  7. Recoil - 纯 PHP 协程库,适用于 ReactPHP。

  8. mkjpryor/async - 同样用于 ReactPHP 的纯 PHP 协程库。

  9. hprose-php - Hprose 是一个提供跨语言提供远程对象调用的组件,其较早前为 JS 和各种语言提供 Promise/A+ 实现的方案,它同时也为 PHP 提供了相应的实现(扩展形式),同时还提供了基于生成器和 yield 的协程实现。

拥有了协程的 PHP 不仅可以做到很高的并发,在长驻模式下的相关框架还可以做到不依赖外部工具的连接池、定时任务、高性能的消息队列、WebSocket、高性能微服务等等,彻底解放 PHP 的潜力。

协程实际上并不是很新的概念,在很早的计算机进程模型中就有过协程的形式

转载本文请标明原文链接

评论 共有 4 条评论

  • 韩天峰 2020-12-25

    放屁,老子已经换java了