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。您无需管理这些细节。
以下是它的实际工作原理:
- 您创建一个
Context。 - 您将一个 stream 包装在
StreamPollHandle中。 - 您将其添加到 context 中,并指定您想要监听的事件。
- 您调用
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
