AsyncTcpConnection onConnect不触发主因是网络策略未打通:TCP握手前连接已卡住,需优先验证目标IP可达性、云安全组出向规则、宿主机防火墙及容器网络,并确保连接对象正确挂载eventloop。

AsyncTcpConnection 连外网 IP 超时,90% 不是代码问题,而是网络策略没打通。
为什么 onConnect 死活不触发?
AsyncTcpConnection 的 new 构造函数只创建连接对象,不发起真实连接;真正触发连接的是事件循环对 socket 可写状态的监听。如果 onConnect 一直不执行,说明连接卡在 TCP 握手前——大概率根本没发出去。
- 检查目标 IP 是否真实可达:
telnet 118.24.128.100 8080或nc -zv 118.24.128.100 8080,不是超时就是拒绝,那 PHP 层再怎么写也白搭 - 确认 Workerman 进程运行在能访问外网的机器上:云服务器默认只能出、不能入,但 AsyncTcpConnection 是「出向连接」,所以重点看它能不能「出」——比如某些企业内网或容器环境会限制 outbound 流量
- 别用域名测试:如果传的是
tcp://api.example.com:80,DNS 解析失败时onError才会触发,而很多人没设onError,结果静默失败
防火墙和安全组才是第一道关卡
本地开发机连外网服务超时,通常跟本机防火墙无关;但如果你是在 ECS、华为云、腾讯云等环境跑 Workerman 客户端,必须确认两点:
- 云平台「安全组」是否放行了**出方向**(Outbound)对应端口——很多控制台默认只管入方向,出方向规则被忽略
- 宿主机系统级防火墙是否拦截 outbound:
sudo firewall-cmd --list-all查看outgoing规则,CentOS 7+ 默认允许,但有些定制镜像会改 - 如果是 Docker 容器,检查
--network模式:用host最省事;用bridge时得确认容器内路由是否通外网
超时时间根本不由 PHP 控制
AsyncTcpConnection 底层调用 stream_socket_client 带 STREAM_CLIENT_ASYNC_CONNECT 标志,此时连接超时由操作系统内核决定,PHP 层无法直接设置秒级 timeout 参数。Linux 默认 SYN 重试 3 次,间隔约 1s/3s/7s,总耗时接近 20 秒才彻底失败。
- 想缩短感知延迟?只能提前 resolve 域名 + 手动计时:用
gethostbyname或dns_get_record拿到 IP 后,传tcp://118.24.128.100:8080,再起一个Timer::add在 5 秒后强制$connection->close() - 别依赖
onError的 $errstr 判断类型:Connection timed out和Connection refused都可能归为同一个错误码,得结合$errno(如 110=ETIMEDOUT,111=ECONNREFUSED)区分 - SSL 连接更慢:除了 TCP 握手,还有 TLS 握手,同样受系统超时影响,且证书验证失败时可能卡在握手阶段,
onError才报错
最容易被忽略的点:连接未 attach 到 eventloop
AsyncTcpConnection 实例创建后,必须被 Worker 的 eventloop 管理才能工作。常见漏掉场景:
- 在
onWorkerStart外创建连接(比如放在全局作用域),eventloop 尚未启动,连接永远不触发 - 连接对象被 GC 回收:没保存引用,比如
new AsyncTcpConnection(...)->onConnect(...)写成一行,PHP 可能立刻释放对象 - Worker 进程数为 0 或未 start:检查
php start.php start是否真运行成功,ps aux | grep workerman看进程是否存在
超时问题本质是「连接请求发不出去」或「对方根本不应答」,所有日志和回调都只是表象。先从网络层验证通路,再看 PHP 层是否正确挂载和保活连接。

















