把 SSE 服务放到 Caddy 2.8 后面,本地直连首字 300ms,过 Caddy 后要 8 秒才出第一个字,客户端超时设的 10 秒,几乎每次都在边缘,Caddyfile 里只写了一行 reverse_proxy 127.0.0.1:8000。

一开始怀疑是「flush_interval 的默认值对长连接不友好」,查了一圈,方向不对。

原因不止一个,得分开看。上游没有声明 Content-Type 是 text/event-stream,Caddy 按普通响应缓冲。也可能是配置里开了 encode gzip,压缩器攒够一个块才输出。

不容易想到的是,前面还有一层 CDN 按整包缓存,把首字拖得更久。

第一件事是确认响应头是否声明了事件流

curl -sI http://127.0.0.1:8000/stream | grep -i content-type

再往下在 Caddyfile 里关压缩并显式 flush

reverse_proxy 127.0.0.1:8000 {
  flush_interval -1
}

接着重载配置后对比首字时间

curl -N -w '%{time_starttransfer}\n' -o /dev/null http://localhost/stream

等前面都确认过,再绕过 Caddy 直连做一次基线对照

curl -N -w '%{time_starttransfer}\n' -o /dev/null http://127.0.0.1:8000/stream

改完先别撤,确认这几项。经过 Caddy 的 time_starttransfer 与直连相差在 100ms 内,浏览器逐字输出,不再整段出现。

这里还有个坑。flush_interval 设 -1 表示每次写都刷出,长连接场景基本都要显式写这一行,靠默认值一定踩坑。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189