open_tcp_nodelay是swoole中禁用nagle算法的tcp选项,设为true可使小数据包“写完即发”,消除20–200ms人为延迟,专治websocket、http/2、sse等长连接下高频小响应的实时性卡顿。

open_tcp_nodelay 是什么,为什么需要设为 true
在 Swoole 中,open_tcp_nodelay 控制是否对 TCP 连接启用 TCP_NODELAY 选项。默认是 false,即启用 Nagle 算法:它会把小数据包缓存起来,等凑够 MSS 或收到前序包的 ACK 后再发,目的是提升吞吐、减少小包开销。但对 HTTP、WebSocket、实时推送这类低延迟敏感场景,这会造成明显卡顿——比如一个响应头 + 小 body 分两次发,中间可能等几十毫秒。
设为 true 后,内核跳过 Nagle 合并逻辑,应用层调用 send() 或 write() 后立即发出,不等待 ACK 或凑包。这不是“加速发送”,而是“取消人为延迟”。真实效果取决于你的协议特征和网络 RTT。
swoole_http_server 和 swoole_server 的配置差异
两者都支持 open_tcp_nodelay,但生效范围不同:
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
-
swoole_http_server:只对 HTTP 协议连接生效(即通过on("request")处理的连接),不影响底层 TCP 连接池或 WebSocket upgrade 后的裸 TCP 流 -
swoole_server(TCP 模式):对所有 accept 进来的 TCP 连接全局生效,包括自定义协议、长连接心跳、二进制通信等 - 注意:
swoole_websocket_server继承自swoole_http_server,所以它的open_tcp_nodelay默认只影响 HTTP 握手阶段;upgrade 成 WebSocket 后,需在on("open")回调里手动调用$fd->set(['tcp_nodelay' => true])才能对后续帧生效
容易被忽略的坑:UDP 和 KCP 场景下别乱配
open_tcp_nodelay 是纯 TCP 选项,对 UDP 完全无效。如果你看到配置里同时写了 open_kcp_protocol => true 和 open_tcp_nodelay => true,后者会被忽略——KCP 自带自己的 kcp_nodelay 参数,必须单独设:
- 错误写法:
['open_kcp_protocol' => true, 'open_tcp_nodelay' => true]→open_tcp_nodelay不起作用 - 正确写法:
['open_kcp_protocol' => true, 'kcp_nodelay' => true] - KCP 的
kcp_nodelay是模拟 TCP_NODELAY 的行为,但底层机制完全不同:它控制是否启用快速重传 + 取消发送间隔限制,不是系统级 socket 选项
验证是否生效的最简方式
不要只看配置有没有写对,要确认 OS 层面 socket 确实设置了该选项:
- 启动服务后,用
lsof -i :端口 -n | grep TCP找到主进程 PID - 执行
ss -ti -p "pid=PID"(Linux ≥ 4.1),观察输出中是否有ts sack字样且无nagle提示;更直接的是查ss -i输出里的wscale和rtt行为变化 - 代码中可在
onConnect回调里加日志:var_dump($server->connection_info($fd)['tcp_nodelay'] ?? 'unknown');—— 注意这个字段只在连接建立后才可读,且依赖 Swoole ≥ 4.8.13
真正关键的不是“开了没”,而是“开了之后你的业务请求是否还出现首字节延迟”;如果用了 nginx 做反代,记得检查 tcp_nodelay on; 是否也配在 upstream 里,否则 Swoole 开了也没用。









