Polling API 是 PHP 最被低估的一次更新

PHP 8.6 包含了一项悄无声息的更新,它将彻底改变高并发网络编程的一切。

当许多开发者还在争论泛型(generics)时,Polling API 却在几乎没有争议的情况下通过了 RFC。它得到了 FrankenPHP 创建者和 Composer 作者等关键人物的支持。

多年来,PHP 一直依赖 stream_select()。这个工具使用的是 1983 年的系统调用。它存在三个主要缺陷:

  • 在大多数系统上,它会触及 1024 个文件描述符的限制。
  • 它使用 O(n) 复杂度,这意味着随着连接数的增加,性能会随之下降。
  • 它无法使用 Linux 上的 epoll 或 macOS 上的 kqueue 等现代工具。

这就是为什么像 AMPHP 或 ReactPHP 这样的异步库需要 ext-uv 等额外扩展才能表现良好的原因。PHP 缺乏大规模网络编程的原生基础。

Polling API 填补了这一空白。

它引入了 Io\Poll 命名空间。该 API 会自动为您的系统选择最佳后端。它在 Linux 上使用 epoll,在 macOS 上使用 kqueue,在 Solaris 上使用 event ports。您无需管理这些细节。

以下是它的实际工作原理:

  1. 您创建一个 Context
  2. 您将一个 stream 包装在 StreamPollHandle 中。
  3. 您将其添加到 context 中,并指定您想要监听的事件。
  4. 您调用 wait(),仅接收实际发生的触发事件。

这并不是一个完整的事件循环(event loop)。它是一个底层原语(primitive)。它提供了让事件循环运行得更快、更可靠的基础设施。

真正的魔力在于其内部机制。该 API 允许 PHP 核心和扩展共享统一的接口。它实现了:

  • 为 FrankenPHP 提供高效的信号处理。
  • 在 PHP-FPM worker 中实现更好的事件处理。
  • 为 sockets 和 curl 提供标准化的接口。
  • 高性能的边缘触发(edge-triggered)模式。

人们常说 PHP 无法扩展。在很长一段时间里,这种说法是有技术依据的。PHP 无法原生访问 Nginx 或 Go 所使用的轮询原语(polling primitives)。

随着 PHP 8.6 的发布,这个借口消失了。

最好的基础设施变革往往是无感的。你察觉不到 epoll 的存在,你只会注意到服务器在处理万级连接时依然游刃有余。

Polling API 这种不显眼的底层工作,提升了整个生态系统的上限。

Source: https://dev.to/juststevemcd/the-polling-api-is-the-most-underrated-rfc-php-has-shipped-in-years-2d32