Workerman 5.0 的 Fiber 协程需显式启用且不自动加速旧代码,仅在 async/await 风格下生效;HTTP 请求必须通过 Request 对象获取参数,$_GET 等全局变量已失效;http-client 默认协程化但连接池按协程隔离,需配置 max_connections_per_host 等参数防瓶颈。

Fiber协程不是“开了就变快”,而是必须显式选择并隔离使用
Workerman 5.0 支持 Fiber、Swoole、Swow 三种协程驱动,但三者互斥——$worker->eventLoop 只能设为其中一种类名,混用会导致启动失败或行为不可预测。PHP 官方 Fiber 是纯语言层实现,不依赖扩展;而 Swoole 和 Swow 是扩展级协程,性能更激进但绑定特定环境。
- 选
Revolt::class:需composer require revolt/event-loop:^1.0.0,兼容 PHP 8.1+,无扩展依赖,适合轻量服务或 CI 环境 - 选
Swoole::class:要求已安装swoole扩展(v5.0+),支持更多底层能力(如协程 DNS、毫秒定时器),但 Windows 下需 WSL - 选
Swow::class:要求swow扩展(v1.4+),内存占用更低,但生态工具链尚不如 Swoole 成熟
如果你只是想尝鲜 Fiber 或跑在没装扩展的服务器上,Revolt 是最稳妥的起点;别指望它自动加速旧代码——Fiber 不是透明优化,它只在你用 async/await 风格写法(比如配合 workerman/http-client)时才真正生效。
HTTP 请求参数获取方式已统一,$_GET 和 $_SERVER 不再可用
Workerman 5.0 彻底移除了对 CGI 兼容模式的模拟,所有请求上下文必须通过 Request 对象获取。这不是 bug,是 RFC3875 合规性升级的结果——$_GET、$_POST、$_SERVER['QUERY_STRING'] 等全局变量在 onMessage 或 onWebSocketConnect 回调里一律为空或未定义。
- 正确写法:
$request->get('token')、$request->post('name')、$request->header('user-agent') - 注意:
$request->cookie()返回关联数组,不是字符串;$request->rawBody()替代file_get_contents('php://input') - 如果项目大量依赖
$_GET,建议封装一个兼容层函数,而不是全局搜索替换——因为部分中间件或框架桥接逻辑可能仍走旧路径
这个改动也意味着你不能再靠 $_SERVER['REQUEST_URI'] 做路由分发,必须改用 $request->uri() 或 $request->path()。
workerman/http-client 的异步请求现在默认走协程,但连接池行为变了
新版 workerman/http-client 默认启用协程驱动,所有 get()、post() 调用都非阻塞,但连接复用策略从“进程级单例”变成了“协程级隔离”。简单说:每个 Fiber/Swoole 协程拥有独立连接池实例,不再跨协程共享 TCP 连接。
- 好处:避免协程间连接状态污染,提升稳定性
- 代价:高并发下连接数可能翻倍,尤其当短连接频繁创建时;若服务端有连接数限制,容易触发
Connection refused - 可调参数:
max_connections_per_host(默认 6)、timeout(默认 5.0 秒)、connect_timeout(默认 3.0 秒)——这些需在创建HttpClient实例时传入配置数组
示例:
$client = new HttpClient(['max_connections_per_host' => 10, 'timeout' => 10.0]);
别漏掉这个配置,否则默认值在压测中很容易暴露瓶颈。
另外,HttpClient 返回的 Response 对象实现了 PSR-7,但它的 getBody()->getContents() 是同步读取——如果你在协程里调用了它,会阻塞当前协程。要用 getBody()->__toString() 或 json_decode($response->getBody()->__toString(), true) 来安全取值。
协程不是银弹,Fiber 尤其需要你主动管理生命周期和资源边界。比如 onMessage 里启了一个协程去发 HTTP 请求,但没做超时控制或异常捕获,一旦远端卡住,整个 Worker 进程的该协程就会挂死——这种问题不会报错,只会表现为连接缓慢堆积。别跳过 try/catch 和 withTimeout 封装。











