HTTP Server 的 request_timeout 是响应总耗时限制,非连接超时;它从接收完整请求头起计时至 response->end(),超时强制关闭连接并返回502;需在start()前set()配置,默认60秒,生产建议5~10秒。

HTTP Server 的 request_timeout 不是连接超时,而是响应总耗时限制
很多人把 request_timeout 当成“客户端连不上就断”的连接超时,其实它只管从收到完整请求头开始,到调用 $response->end() 结束的整个周期。如果业务逻辑卡在中间(比如协程里 sleep 了 15 秒),且 request_timeout 设为 10,那第 10 秒一到,连接就被强制关闭,返回 502 —— 但此时 TCP 连接早已建立成功。
这个值必须在 $server->start() 前通过 $server->set() 设置,启动后再改无效。默认是 60 秒,生产环境建议压到 5~10 秒,避免慢请求拖垮 worker。
-
request_timeout不影响 DNS 解析、TCP 握手、TLS 协商这些前置阶段 - 它和
heartbeat_idle_time是两回事:后者只对 HTTP keep-alive 长连接生效,控制空闲多久断开,不干预业务处理 - 若你用了
Co\Http\Client去调下游,它的超时跟这个完全无关,得单独配
协程客户端(Co\Http\Client)必须显式设 connect/read/write_timeout
协程客户端默认所有超时都是 0(即永不超时),一旦下游服务卡住或网络抖动,当前协程就会无限挂起,进而阻塞整个 worker。这不是 bug,是设计使然 —— Swoole 把控制权交还给开发者。
三个超时参数互不覆盖,漏掉任何一个都可能出问题:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
connect_timeout:DNS 查询 + TCP 握手 + TLS 握手总耗时,单位秒,建议设 3~5 -
read_timeout:从发完请求头/体后,等待第一个字节响应的时间(含 header),不是整个响应体接收时间,建议设 5~10 -
write_timeout:发送请求体(如 POST 大文件)的超时,小请求可设 3,大包需放宽
示例:
$client = new Co\Http\Client('api.example.com', 443, true);
$client->set([
'connect_timeout' => 3,
'read_timeout' => 5,
'write_timeout' => 3,
]);
WebSocket 和 TCP Server 要靠 tcp_keepalive + heartbeat 防空闲断连
公网或 NAT 环境下,中间设备(如路由器、云厂商 SLB)常在 60~300 秒无数据时主动踢掉连接,表现为 Connection reset by peer 或客户端收不到 ping 回复。光靠应用层心跳不够,底层 TCP 保活也得开。
- 加
'tcp_keepalive' => 1启用内核级 keepalive,避免被中间设备静默回收 - 配
'heartbeat_check_interval'(如 60)和'heartbeat_idle_time'(如 180),表示每 60 秒扫一次连接,连续 180 秒没收到 ping 就主动 close - 注意:WebSocket 的
onMessage里不能有同步阻塞操作(如sleep、curl_exec),否则会卡住 ping/pong 响应,触发 heartbeat 踢人
MySQLi 连接池的 get_connection_timeout 容易被忽略
当并发请求超过连接池 max_conn,新协程会排队等空闲连接。这个等待过程本身也有超时,由 get_connection_timeout 控制,默认仅 3 秒 —— 很多人只调 timeout(SQL 执行超时),却忘了等连接这一步也会超时。
- 若
get_connection_timeout太小(如 1 秒),高并发时大量请求还没拿到连接就直接抛Swoole\Coroutine\MySQL\Exception - 建议设为 5~10 秒,并配合监控:当该异常突增,优先查是否
max_conn不足或下游 DB 响应变慢 - 连接池空闲连接要设
idle_check_time和max_idle_time,否则 MySQL 的wait_timeout会悄悄干掉“僵尸连接”
真正难调的不是单个 timeout 数值,而是各层超时之间的咬合关系:HTTP 请求超时、下游 HTTP 客户端超时、数据库查询超时、连接池获取超时 —— 它们得形成梯度,上层比下层略长,否则会出现“上游已放弃,下游还在忙”的资源浪费。

















