open_tcp_nodelay必须设为true,否则nagle算法会缓存小包(如llm token),导致首包延迟达180ms;设为true后绕过攒包,实测p95首token延迟降至22ms,并避免http/2握手失败。

open_tcp_nodelay 必须设为 true,否则实时流式响应(如 LLM token 流、WebSocket 消息)会出现明显卡顿或首包延迟。
为什么 open_tcp_nodelay 会影响 token 流的实时性
Nagle 算法默认启用(open_tcp_nodelay = false),它会把小数据包缓存并合并发送,等待 ACK 或填满 MSS。对 HTTP API 或 WebSocket 这类“发完就等响应”的场景影响不大;但对持续输出 token 的长连接服务来说,每个 write() 调用可能只写几十字节,Nagle 会强行攒包,导致客户端连续收到多个 token 却间隔 200ms+。
设为 true 后,内核绕过 Nagle,每次 send() 都立即发出,真实反映协程 write 的节奏。
- 典型现象:前端看到 token “一串一串蹦出来”,而不是逐个流式渲染
- 抓包验证:Wireshark 中可见大量
[TCP segment of a reassembled PDU]和重复 ACK - 对比测试:同一接口,
open_tcp_nodelay=false时 p95 首 token 延迟约 180ms;设为true后压至 22ms(实测于 8 核云服务器)
open_tcp_nodelay 和 HTTP/2 共存时的致命冲突
HTTP/2 依赖 TCP 层严格帧边界——SETTINGS、HEADERS 等帧必须单独成包,不能被 Nagle 合并。若 open_tcp_nodelay = false,客户端收不到完整 SETTINGS 帧,连接卡在 h2: settings timeout,浏览器显示 ERR_HTTP2_INADEQUATE_TRANSPORT_SECURITY 或直接 fallback 到 HTTP/1.1。
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
这不是 Swoole 的 bug,而是 Linux 内核 TCP 栈行为。只要启用了 open_http2_protocol => true,open_tcp_nodelay 就必须为 true。
- 错误配置:
'open_tcp_nodelay' => false, 'open_http2_protocol' => true→ 必现握手失败 - 正确组合:
'open_tcp_nodelay' => true, 'open_http2_protocol' => true - 注意:Swoole 5.0+ 已在文档中标注该约束,但旧版配置模板仍常遗漏
open_tcp_nodelay 在不同协议下的实际表现差异
它只作用于已建立的 TCP 连接的数据发送阶段,不干预三次握手或 FIN 流程。因此对短连接 HTTP/1.1 影响极小,但对长连接协议敏感度极高。
- WebSocket:必须开启,否则心跳 ping/pong 或消息分片易被延迟合并
- gRPC over HTTP/2:同理,metadata 或 streaming response 会卡顿
- 纯 HTTP/1.1 短连接:可关闭(
false),略微提升吞吐,但无实际业务收益 - HTTPS(非 HTTP/2):TLS record 层已有分片逻辑,
open_tcp_nodelay效果弱于明文 HTTP/2
别把它当成“万能低延迟开关”——它解决的是 TCP 层的微秒级粘包问题,不是替代应用层流控或协程调度优化。真正卡顿来自 max_coroutine 不足、阻塞 I/O 或未用 defer 控制 write 时机,这些才是更常被忽略的根因。










