workerman 5.2.3 搭配 swow 需满足 php ≥ 8.0、swow 扩展已启用、版本确认为 5.2.3、前台启动,并在 worker::runall() 前设置 worker::$eventloopclass = \swow\eventloop::class 和 worker::$timerinterval = 0。

Workerman 5.2.3 搭配 Swow 扩展不是“一键启用”,而是要满足一整套运行时约束,并手动接管事件循环。Swow 不是 Workerman 的插件,它替代的是底层 I/O 调度器——相当于把 Workerman 原来的“心脏”换掉。配置对了才能真正跑协程,否则会静默降级回 stream_select,性能毫无提升。
前置条件必须全部满足
缺一不可,否则启动即失败或无效:
- PHP 版本 ≥ 8.0(Swow 仅支持 PHP 8.0+,5.2.3 本身兼容,但低版本 PHP 直接无法加载 Swow)
- Swow 扩展已正确安装并启用:运行 php -m | grep swow 有输出,且 php --ri swow 显示正常信息
- Workerman 版本确认为 5.2.3(该版本完全支持
Worker::$eventLoopClass,低于 4.1.0 不可用) - 启动方式必须为前台模式:php start.php start(禁止
-d或--daemon)——Swow 不支持 fork 后的协程上下文继承
关键代码注入位置
在 Workerman 启动文件(如 start.php)中,Worker::runAll() 之前、Worker 实例创建之后 插入两行核心配置:
- Worker::$eventLoopClass = \Swow\EventLoop::class; —— 替换默认事件循环
- Worker::$timerInterval = 0; —— 关闭 Workerman 自带定时器(Swow 内置 Timer 更高效,冲突会导致异常)
注意:这两行不能写在 onWorkerStart 回调里,必须在全局作用域、Worker::runAll() 调用前完成赋值。
监听与 socket 注意事项
Swow 不接受阻塞式 socket 创建。虽然 Workerman 5.2.3 已自动适配非阻塞标志(如 SOCK_NONBLOCK),但以下情况仍需检查:
- 所有
new Worker('text://...')或'websocket://...'协议监听,无需额外改动 - 若项目中有自定义
stream_socket_server()或原生 socket 操作,必须显式传入STREAM_SERVER_BIND | STREAM_SERVER_LISTEN并确保STREAM_CONTEXT中设置['socket' => ['non_blocking' => true]] - 禁用
Worker::$reloadable = false外的热更新机制(Swow 当前不支持运行时 reload 协程环境)
验证是否真正生效
不要只看进程起来——要确认 Swow 在驱动:
- 启动后访问任意 Worker 的
onWorkerStart回调,在其中加一行:var_dump(\Swow\EventLoop::isRunning());,应输出 bool(true) - 用
strace -p [pid] -e trace=epoll_wait,io_uring_enter观察系统调用(Linux),Swow 会使用io_uring或epoll,而非select/poll - 故意写一个死循环协程(如
\Swow\Coroutine::create(fn() => { while(1) usleep(1000); });),观察 CPU 是否可控——这是纯协程调度的典型表现











