co\http\client 的 connect 和 recv 超时必须分开设定,需通过构造函数传入数组指定 connect_timeout 和 recv_timeout,set() 方法对这两项无效;超时单位为秒(支持浮点),触发时 errcode=110 但需结合调用阶段判断具体超时类型;协程客户端无内置心跳,需手动实现;settimeout() 不适用于 http 客户端。

Co\Http\Client 的 connect 和 recv 超时必须分开设
协程 HTTP 客户端的超时不是单个参数能控制的,connect_timeout 和 recv_timeout 必须显式传入构造函数,否则走默认值(connect 是 0.5 秒,recv 是 5 秒),极易在弱网或服务响应慢时意外中断。
常见错误是只设了 connect_timeout,结果请求卡在 recv 阶段长达 5 秒才失败;或者反过来,只调 set 方法传数组,但该方法对 Co\Http\Client 实例无效——它只在 Server/Client 创建时生效。
-
new Co\Http\Client($host, $port, $ssl)的第三个参数$ssl是 bool,不能塞超时;超时必须用后两个参数:new Co\Http\Client($host, $port, false, ['connect_timeout' => 3.0, 'recv_timeout' => 8.0]) - 如果用
set(),必须在connect()前调用,且仅支持部分选项(文档未列全),实测connect_timeout和recv_timeout在set()中无效 - 超时单位是秒,支持浮点数(如
0.8表示 800ms),别误写成毫秒整数
超时触发后 errCode = 110,但不能只靠这个判断失败原因
当 connect()、send() 或 recv() 超时时,$client->errCode 会被设为 110,对应 ETIMEDOUT。但注意:这个值和 Linux errno 一致,不是 Swoole 自定义码,所以 socket_strerror($client->errCode) 能正确输出 "Connection timed out"。
问题在于,errCode === 110 只说明“某环节超时”,不区分是连不上、发不出还是收不到。你得结合调用阶段判断:
- 调
connect()后errCode === 110→ 连接超时(DNS 解析 + TCP 握手) - 调
send()后errCode === 110→ 发送缓冲区满或对端窗口为 0 导致阻塞超时 - 调
recv()后errCode === 110→ 等待响应体超时(比如后端卡住没 flush)
建议每次操作后立刻检查 $client->errCode,而不是等整个请求结束再查。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
协程客户端不支持 heartbeat 配置,心跳得自己写
文档里写的 set(['heartbeat' => 30]) 对 Co\Http\Client 完全无效。协程客户端没有内置心跳机制,所谓“自动心跳”只存在于老式同步 swoole_client,而且发的是无意义 \x00 字节,兼容性差。
如果你要维持长连接并防服务端主动断连,必须手动实现:
- 用
Swoole\Coroutine\Timer::tick(45000, fn() => $client->send("ping"))每 45 秒发一次心跳(间隔建议 ≤ 服务端heartbeat_idle_time的 1/2) - 心跳包内容需和服务端协议对齐(比如 HTTP/1.1 用
OPTIONS /health,WebSocket 用{"type":"ping"}) - 别在
recv()后直接sleep()等待下一次心跳——这会阻塞协程;要用co::sleep()或定时器
setTimeout() 是 mysql_pool 专属,别套用到 HTTP 客户端
看到 coroutineSend()->setTimeout(100) 这种写法,容易误以为所有协程操作都支持链式 setTimeout()。实际上,这是 Swoole\Coroutine\MySQL\Pool 内部封装的特例,Co\Http\Client 根本没有这个方法。
试图调用 $client->get('/')->setTimeout(2000) 会报 Fatal error: Uncaught Error: Call to undefined method。HTTP 客户端的超时只能靠构造参数或连接后设置(如 $client->set(['timeout' => 3.0]),但注意这个 timeout 是 recv 超时,且必须在 connect() 后、send() 前调用)。
真正通用的协程超时控制方式是 Swoole\Coroutine::sleep() + go() 封装,或用 Channel 配合 select() 做竞态等待——但对 HTTP 场景太重,优先用构造参数。










