Swow:我是谁?我能做什么?
🚀 Swow 是一个专注于并发 I/O 的跨平台协程引擎,它致力于使用最小 C 核心及多数 PHP 代码以支持 PHP 高性能网络编程,具有极佳的扩展性与强大的调试能力,最大化开发者的编程效率。
项目初衷
尽管现在 PHP 协程生态已经有了非常多样的选择,但所有的协程框架、库都存在着一个非常致命的问题,即它们都是从异步框架演变而来,并非开始就自底向上为协程而设计,且出于一些兼容性方面的考量,往往会牺牲掉很多本应具备的能力,又或是囿于历史包袱而无法做出合理的设计改变。
因此,Swow 项目致力于打造一个自底向上专为协程设计的高性能、高可控、易兼容的引擎,依托架构设计优势,全面释放协程技术的真正实力。此为 Swow 及其团队成员的初衷,我们将持续投入并为此付出努力,也欢迎你加入我们参与开源建设。
设计理念
Swow 的最小 C 核心设计决定了它在保障关键性能之外,更多的是追求二次开发能力与可调试性。
Swow 内核与 PHP 代码的无缝融合运作使得开发者的编程效率与灵活性能得到极大的提升。
Swow 提供了丰富多样的调试机制与强大且低门槛的调试能力,最大程度地确保开发者免受BUG困扰,普通开发者也能通过工具的加持具备接近专家级别的DEBUG能力。
致谢
写在能力介绍之前:PHP 高性能协程网络通信引擎开发之路曲高和寡,这是一项高处不胜寒的开源工作,非常感谢以下小伙伴对于 Swow 项目的代码贡献,没有大家就没有现在的 Swow。其中重点感谢团队核心成员 @dixyes 的付出,将 Swow 各方面的能力与稳定性提升到了一个全新的高度。
支持的操作系统
操作系统 | Swow | 其它异步协程库 |
---|---|---|
Win32 | ✅ IOCP 原生支持 | ❌ 无原生支持 |
GNU/Linux (包括 musl) | ✅ Epoll 支持 + 计划中的 io_uring 支持 | ⚠️ 无 io_uring 计划支持 |
macOS | ✅ Kqueue 支持;支持 intel 和 m1 芯片 | ⚠️ 非一级支持 |
FreeBSD | ✅ Kqueue 支持 | ⚠️ 缺少官方支持声明 |
其它1 | ⚠️ 二等支持:AIX / IBM i / z/OS / Android / MinGW / SunOS | ⚠️ 不明确 |
协程
C栈协程实现
C栈协程实现 | Swow | 其它异步协程库 |
---|---|---|
boost-context | ✅ 一等支持2 | ✅ |
ucontext | ✅ 兼容性更佳 | ✅ |
thread-context | ✅ 可通过gdb观察所有C栈协程状态 | ⚠️ 仅Swoole支持 |
协程模型
协程模型 | Swow | 其它异步协程库 |
---|---|---|
主协程 | ✅ 所到之处,皆是协程 | ❌ 不支持,无法完美兼容传统PHP生态 |
跨协程调度 | ✅ 支持嵌套协程跨级调度 | ❌ 不支持,无法实现跨级中断 |
独立环境 | ✅ 单个协程崩溃不影响全局稳定 | ❌ 不支持,一崩全崩 |
对标进程模型 | ✅ 仿进程模型,设计有理可循 | ❌ 自造概念 |
单栈闪电切换 | ✅ 调度器或内部协程仅需单栈切换 | ❌ 不支持,总是双栈切换 |
协程操控能力
协程操控能力 | Swow | 其它异步协程库 |
---|---|---|
强制唤醒 | ✅ 等同于ECANCELED 或 ETIMEDOUT | ⚠️ 不完善 / 无全场景支持 |
异常中断 | ✅ 等同于SIGTERM | ⚠️ 不完全支持 |
杀死协程 | ✅ 等同于SIGKILL | ❌ 不支持 |
协程调试器
协程调试器 | Swow | 其它异步协程库 |
---|---|---|
SDB | ✅ 专为协程模型定制 | ❌ 缺少完全面向协程设计的 Debugger |
Xdebug | ✅ PHP-8.1起支持 | ✅ PHP-8.1起支持 |
协程调试器能力
协程调试器能力 | Swow | 其它异步协程库 |
---|---|---|
PHP编写&二次开发 | ✅ 可继承扩展 | ❌ 依赖其他扩展能力 |
生产环境支持 | ✅ 无性能影响 | ⚠️ 不建议在生产环境启用 |
协程列表 | ✅ 相当于查看进程的ps指令 | ⚠️ 不完全支持,依赖传统PHP调试器的库无协程粒度的支持 |
查看所有协程信息 | ✅ 可查看协程状态、全调用栈每一个栈帧的信息、执行的源代码内容、栈上变量等 | ⚠️ 不完全支持,依赖传统PHP调试器的库无协程粒度的支持 |
进入某个协程并跟踪调试 | ✅ 等同于 gdb attach | ❌ 不支持 |
断点、单步调试 | ✅ 只影响受调试的协程 | ⚠️ 依赖Xdebug等工具,且会阻塞整个进程 |
调试时动态插入PHP指令 | ✅ 使用调试器进行断点调试至BUG处时,可动态执行 PHP 指令对 BUG 进行调试3 | ❌ 不支持 |
扫描僵尸协程 | ✅ 找出长时间不活跃的协程 | ❌ 不支持 |
杀死协程 | ✅ 相当于 kill 命令 | ❌ 不支持 |
杀死所有协程并退出 | ✅ 相当于优雅关机 | ❌ 不支持 |
通道
核心有效代码不到300行,单元测试覆盖率100%。
通道能力 | Swow | 其它异步协程库 |
---|---|---|
零缓冲通道 | ✅ new Channel(0) | ❌ 不支持 |
带缓冲通道 | ✅ new Channel(n) | ✅ |
select | ✅ Selector |CallbackSelector | ❌ 不支持 |
循环引用GC | ✅ 可处理队列中的循环引用 | ❌ 不支持 |
关闭后读 | ✅ 通道关闭后仍可读取队列中的剩余数据 | ❌ 不支持 |
同步
其它能力 | Swow |
---|---|
WaitGroup | ✅ 内置高性能实现 |
WaitReference | ✅ 藉由引用计数机制实现,编码更轻松 |
事件
协程库 | 事件驱动 |
---|---|
Swow | ✅ 基于 libcat 自主维护4,libcat 是 libuv 的衍生项目5 |
Swoole | ✅ 自研,但无Windows原生支持 |
其它异步协程库 | ❌ 依赖第三方维护的事件驱动扩展,且部分扩展已无人维护 |
信号
信号能力 | Swow | 其它异步协程生态 |
---|---|---|
Windows 信号模拟 | ✅ Windows 下使用仿 Linux 信号机制 | ⚠️ 缺乏 Windows 原生支持 |
网络编程
网络编程能力 | Swow | 其它异步协程生态 |
---|---|---|
Buffer | ✅ 精准掌控每个字节的内存使用,实现高性能数据处理 | ❌ 粗粒度内存管理 |
Buffer (写时拷贝) | ✅ 写时拷贝机制 + 内存映射机制 | ❌ php_stream需创建内部内存副本 |
Socket | ✅ 可联动Buffer实现精准到每一字节的数据收发 | ❌ 粗粒度内存管理 |
Socket (writev 支持) | ✅ 单系统调用零拷贝发送多块内存数据 | ❌ 无法避免的内存拷贝或多次系统调用 |
IpAddress | ✅ 完善的高性能 IP 地址解析库,助力网络编程 | ⚠️ 缺乏相关内置支持 |
HttpParser | ✅ 可由 PHP 代码操控完成高性能HTTP协议解析 | ❌ 只能接收底层处理好的 HTTP 对象 |
WebSocket | ✅ 可由 PHP 代码操控完成高性能 WebSocket 协议解析 | ❌ 只能接收底层处理好的 WebSocket 对象 |
可借助 Swow 底层核心提供的最小化能力,通过编写 PHP 代码实现高性能 API 网关,具体的项目实践内容与生产环境验证分享敬请期待后续 Swow 官方团队的推文更新!
同步阻塞协程化
同步阻塞协程化 | Swow | Swoole | 其它异步协程生态 |
---|---|---|---|
PHP stream (阻塞模式) | ✅ | ✅ | ❌ |
PHP stream (非阻塞模式) | ✅ BIO模式 | ✅ SSL_read/write模式 | ❌ |
PHP stream (文件IO) | ✅ | ✅ | ❌ |
PHP stream (文件锁) | ✅ 全场景覆盖 | ✅ | ❌ |
pdo_mysql | ✅ | ✅ | ❌ |
pdo_pgsql | ✅ | ✅ | ❌ |
mysqli | ✅ | ✅ | ❌ |
phpredis | ✅ | ✅ | ❌ |
curl | ✅ | ✅ | ❌ |
proc_open | ✅ | ✅ | ❌ |
sockets扩展 | ⚠️ 暂不支持6 | ✅ | ❌ |
sleep, usleep, nanosleep … | ✅ | ✅ | ❌ |
shell_exec、exec、passthru … | ✅ | ✅ | ❌ |
gethostbyname 等DNS相关函数 | ✅ | ✅ | ❌ |
stream_select | ✅ | ✅ | ❌ |
stream_poll_one | ✅ Workerman 特供 | ✅ Swoole\Event | ❌ |
该技术带来的好处:
生态复用优势 | Swow | Swoole | 其它异步协程生态 |
---|---|---|---|
基于 file_get_contents()、cURL 的开源库 (如:Guzzle 等) | ✅ | ✅ | ❌ 生态割裂 |
云平台提供的基于 cURL 的 SDK (如:阿里云、腾讯云、AWS 等平台的SDK) | ✅ | ✅ | ❌ 生态割裂 |
基于 PDO、mysqli、phpredis 的开源库 | ✅ | ✅ | ❌ 生态割裂 |
基于 stream_select() 或其他事件驱动的异步开源库 (如:workerman、reactphp、amphp) | ✅ | ✅ | ❌ 无法同时运作 |
FileSystem 相关开源库 (如:symfony/filesystem) | ✅ | ✅ | ❌ 无法解决,直接阻塞 |
直接打印到标准输出或需要读写日志文件的 Log 库 (如:symfony/console、monolog) | ✅ | ✅ | ❌ 无法解决,直接阻塞 |
CPU调度
Watchdog 为 PHP 提供了 CPU 调度能力,其核心原理是 Watchdog 线程会定期检查其它线程中协程的活跃度情况,若发现工作线程中的协程不再活跃,则通过 ZendVM 的中断机制对其进行状态确认,若 VM 中断失败,则表明工作线程陷入了系统调用阻塞,触发告警;若 VM 中断成功,则表明工作线程陷入了 CPU 密集运算或死循环,则立即触发用户设定的调度规则进行调度。
CPU调度能力 | Swow | Swoole | 其它异步协程生态 |
---|---|---|---|
CPU阻塞告警 | ✅ 包含系统调用阻塞告警 | ⚠️ 静默调度,无告警 | ❌ 无法告警,直接宕机 |
CPU阻塞减缓 | ✅ 动态可调 | ✅ 固定调度时间 | ❌ 无法减缓,直接宕机 |
CPU阻塞扼制 | ✅ 支持杀死陷入死循环的协程 | ⚠️ 仅支持定时让出,降低负面影响 | ❌ 无法应对,直接宕机 |
动态开关调度器 | ✅ API开关调度器 | ⚠️ 仅支持通过 ini 设置 | ❌ 无 CPU 调度能力 |
动态规划调度行为 | ✅ 可编程,阻塞时动态决定调度方式 | ⚠️ 固定调度规则 | ❌ 无 CPU 调度能力 |
现代化
现代化能力 | Swow | 其它异步协程库 |
---|---|---|
面向对象 | ✅ 内核与PHP代码无缝融合,所有对象可通过继承方式扩展,轻松完成二次开发 | ⚠️ 不完全面向对象 |
异常机制 | ✅ 全面拥抱异常机制,链式调用轻松编码 | ⚠️ 不完全使用异常机制 |
Composer | ✅ 支持全流程通过 Composer 安装部署,支持 All in one 或分库两种拉取方式 | ⚠️ 需通过其它途径安装扩展 |
IDE 助手 | ✅ Composer 安装后包中内置 IDE 助手代码 | ⚠️ 需额外拉取 IDE 助手 |
其它调试能力
其它调试能力 | Swow | 其它异步协程库 |
---|---|---|
类 strace 日志 | ✅ Debug 模式下,支持将底层协程调度、网络收发、系统调用信息以strace的格式打印(支持多种格式时间、模块信息、PHP 源码位置显示),SSL 网络收发数据支持明文显示,免除抓包工具与证书配置烦恼。 | ❌ 无相关支持 |
debugInfo 支持 | ✅ 通过 var_dump() 打印内部对象,也可以看到丰富的调试信息 | ⚠️ 需要手动打印所需信息 |
构建系统
构建能力 | Swow | Swoole | 其它异步协程生态 |
---|---|---|---|
Builder | ✅ 可通过 Composer 拉取项目,并使用内置脚本一键安装扩展,支持每个项目独立扩展版本 | ⚠️ 仅支持手动编译或 PECL 安装 | ❌ 需要自行安装第三方事件驱动扩展 |
PECL | ❌ 无计划支持,PECL 年久失修,缺乏维护 | ✅ 一等支持 | ⚠️ 由第三方提供事件驱动扩展,无法独立自主保证可靠性 |
Windows DLL | ✅ 可在 release 页面直接下载 | ❌ 不支持 Windows | ❌ 没有Windows 原生支持 |
CLI发行 | ✅ 基于 lwmbs 能力,可直接下载 | ✅ swoole-cli | ❌ 需要自行编译或通过系统包管理器安装 |
micro 一键打包为二进制 | ✅ 基于 lwmbs 能力,可选配 Swow 进行 PHP 项目二进制打包发布,一次打包,多处运行7 | ⚠️ 暂不支持6 | ❌ 不支持,但可以借助 Swow 团队提供的 PHP 打包能力实现 |
更多
以上的能力枚举只是让 Swow 初露峥嵘,Swow 内核还包含了大量的细节设计以及部分未正式披露的实验性功能。
总的来说,Swow 的未来充满了想象空间,它为 PHP 提供了远超以往的可能性,我们可以藉由 Swow 的能力去想、去做更多未曾深思过的事情。
后续我们将通过「大量发布短篇文章」的方式与大家分享各个能力项的详细描述与最佳实践,并披露大量内部实现细节与生产应用情况,敬请期待!
注释
-
其它系统支持情况取决于libuv支持情况与社区需求 ↩
-
一等支持指 Swow 开发团队成员会通过向 boost-context 提交代码贡献的方式来使其更好地支持 Swow 所需的应用场景。 ↩
-
相当于 GDB 的 print 指令,动态执行调试者给出的 expression,并打印其返回值。 ↩
-
libcat 是协程版本的 libuv,由 Swow 团队独立自主维护,可供所有基于C的项目使用,如:你可以使用 libcat 写一个C++协程项目,或为 Python、Node.js 提供 C 栈协程能力等。 ↩
-
libuv 异步事件驱动提供主流全平台支持,经过 Node.js、Julia 等语言广泛且严苛的生产验证,达到了工业级水准。Swow 团队会通过向 libuv 提交代码贡献的方式来使其更好地支持 Swow 所需的应用场景。 ↩
-
Hyperf Box 提供了开箱即用的 Swow 项目一键打包二进制工具,也欢迎更多的开源社区小伙伴基于 micro 技术二次开发出更多开箱即用的打包工具造福社区。 ↩