connection timed out 主因是网络链路问题而非代码错误,高并发下易因端口耗尽、云平台限速或监听配置不当导致tcp握手失败;需检查监听地址、启用reuseport、调优内核参数并添加双向心跳。

Workerman 出现 Connection timed out,绝大多数情况不是代码写错了,而是连接根本没发出去——卡在了网络链路中间。
为什么高并发下更容易触发 net::ERR_CONNECTION_TIMED_OUT?
这个错误本质是客户端(浏览器或其它 client)在 TCP 握手阶段等不到服务端 SYN-ACK 响应,超时放弃。高并发会放大三类底层问题:
- 服务器本地端口耗尽:Linux 默认
net.ipv4.ip_local_port_range是 32768–65535(约 3.2 万个临时端口),大量短连接 + TIME_WAIT 状态堆积后,新连接无法分配本地端口,表现为“连接超时”而非“拒绝连接” - 云平台安全组/防火墙限速:阿里云、华为云等对新建连接数(conn/s)有隐式限制,单 IP 每秒新建连接超过阈值会被丢包,现象就是间歇性超时
- 服务端监听能力不足:Workerman 进程未设置
reusePort,或监听地址写死为127.0.0.1,导致多核 CPU 无法并行处理 SYN 包,SYN 队列(net.core.somaxconn)溢出后直接丢弃新请求
Worker::$globalEvent = 'libevent' 能缓解吗?
能,但只解决一半。libevent 比默认的 stream_select 更高效地轮询 socket,提升单进程吞吐,但它不改变内核层面的连接建立瓶颈。重点要配齐以下三项:
- 确认 Workerman 启动时监听的是
0.0.0.0:xxxx,不是127.0.0.1:xxxx - 在
start.php中启用 SO_REUSEPORT:$worker = new Worker('websocket://0.0.0.0:2346'); $worker->reusePort = true; - 调大系统参数(需 root):
sysctl -w net.core.somaxconn=65535 sysctl -w net.ipv4.ip_local_port_range="1024 65535" sysctl -w net.ipv4.tcp_tw_reuse=1
怎么快速判断是客户端问题还是服务端链路问题?
别猜,用最原始但最准的方式验证:
- 在服务端机器上执行:
telnet 127.0.0.1 2346—— 如果通,说明 Workerman 进程本身正常;如果不通,检查Worker::status()输出和netstat -tlnp | grep :2346 - 在客户端机器上执行:
telnet your-server-ip 2346—— 如果不通,立刻排查:① 云平台安全组是否放行该端口(不是宝塔防火墙!);② 本地网络是否拦截(如公司代理、校园网 NAT);③ 是否 DNS 解析到了错误 IP(用nslookup或dig确认) - 用
tcpdump -i any port 2346在服务端抓包:如果看到客户端 SYN 包进来但无 SYN-ACK 回复,基本锁定是内核队列溢出或防火墙 DROP
高并发长连接场景下,Connection timed out 的真正对手是 NAT 和中间设备
很多线上环境用的是云服务器+公网 IP+SLB/NAT 网关组合。这些中间设备普遍有 30–60 秒的空闲连接超时。Workerman 本身不发心跳,TCP 连接在应用层“活着”,但在中间设备眼里早已被回收。结果就是:前一秒还正常收发消息,下一秒发包就卡住,重试几次后报 Connection timed out。
必须在业务层加心跳,且注意两点:
- 心跳间隔必须小于中间设备超时时间(建议 ≤ 25 秒)
- 心跳包不能只发不收:客户端发
{"type":"ping"},服务端收到后必须立即回{"type":"pong"},否则单向心跳对 NAT 无效 - 服务端要主动清理超时连接:
Worker::onWorkerStart = function() { Timer::add(25, function() { foreach($worker->connections as $connection) { if (time() - $connection->lastMessageTime > 30) { $connection->close(); } } }); };
真正的难点不在代码怎么写,而在于你得同时盯着四层(TCP)、五层(NAT 设备)、七层(Workerman 应用逻辑)和云平台控制台这四个地方。漏掉任意一环,Connection timed out 就会反复出现。











