不能混合使用。同一个 workerman worker 进程中,fiber、swoole、swow 三种协程驱动互斥,只能选其一;强行混用会导致事件循环冲突、协程挂起不执行、甚至进程崩溃。

不能混合使用。同一个 Workerman Worker 进程中,Fiber、Swoole、Swow 三种协程驱动互斥,只能选其一;强行混用会导致事件循环冲突、协程挂起不执行、甚至进程崩溃。
为什么 Worker 内部无法共存 Swoole 协程和 Fiber?
Workerman 5.0 的协程支持是通过替换底层事件循环(eventLoop)实现的:
-
Swoole驱动依赖Swoole\Event::wait()和Swoole\Coroutine原生调度器,需运行在 Swoole 扩展启用且未被其他协程库接管的环境中 -
Fiber驱动(如Revolt)完全绕开 Swoole,基于 PHP 8.1+ 的Fiber+EventLoop实现,此时Swoole\Coroutine::create()会直接报错或静默失效 - 两者对 I/O 挂起点(如
co::sleep、co::read或Revolt\sleep)的拦截机制不同,无法协同调度
Workerman 启动时指定 Swoole 协程的正确姿势
必须显式设置 eventLoop 并确保 Swoole 扩展已加载、无其他协程库干扰:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 确认
extension=swoole.so已启用,且php -m | grep swoole可见输出 - Worker 实例需设置
$worker->eventLoop = \Workerman\Events\Swoole::class; - 禁用所有依赖
Fiber或Swow的组件(如revolt/event-loop、swow/swow) - 所有协程调用必须使用
Swoole\Coroutine::系列函数,例如Swoole\Coroutine::sleep(0.1),而非co::sleep(旧版别名,已弃用)
示例片段:
<?php use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker = new Worker('http://0.0.0.0:8080');
$worker->eventLoop = \Workerman\Events\Swoole::class; // 关键:明确指定 Swoole 驱动
$worker->onMessage = function ($connection, $request) {
// ✅ 正确:Swoole 协程内可安全调用
\Swoole\Coroutine::sleep(0.05);
$connection->send('done');
};
Worker::runAll();
GatewayWorker 场景下 Swoole 协程为何“延迟执行”?
这不是配置错误,而是架构限制导致的必然现象:
- GatewayWorker 的
Worker进程由Gateway进程 fork 出,但不直连 Swoole 事件循环;它本质是普通 PHP 进程,仅通过 Unix Socket 与 Gateway 通信 - 你在 Worker 进程里写的
Swoole\Coroutine::create(),实际被丢进一个未启动的 Swoole 事件循环队列中,直到整个 GatewayWorker 进程退出时才批量执行 - 所以你会看到日志里协程逻辑全在
Worker::stop()之后打印,根本不是“异步”,而是“延迟同步” - 解决路径只有一条:把协程逻辑移出 GatewayWorker 的 Worker 进程,改用
async_task接口投递到独立的 Swoole 协程 Worker,或换用 Redis/Kafka 做中间解耦
真正容易被忽略的点是:协程能力不是“开了扩展就能用”,它绑定在进程启动时选定的 eventLoop 实现上。一旦选错驱动,Swoole\Coroutine 就只是个空壳——既不报错,也不执行,调试时极难定位。










