发布时间: 2026年10月21日更新时间: 2026年10月21日

Caddy 与 Nginx 的 WebSocket 代理配置有什么区别:升级头与超时

对比 Caddy 与 Nginx 的 WebSocket 反向代理配置,说明 HTTP/1.1 Upgrade、空闲超时和版本差异,并给出断连排查方法。

两者都能代理 WebSocket。本文示例采用传统 HTTP/1.1 Upgrade:Nginx 需要正确转发升级头;Caddy 的 reverse_proxy 会处理升级。连接建立后是否断开,还要看读空闲超时、连接总时长和中间层策略。下面给出配置示例与版本边界。

排查时先看握手是否成功,再看连接建立后的断开时间和各层日志。客户端出网代理的协议选择见HTTP、HTTPS、SOCKS5 代理怎么选。

Nginx 如何配置 WebSocket 升级头和读超时

```nginx
location /ws/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_buffering off;
}
```

Upgrade 与 Connection 用于传统 HTTP/1.1 握手;proxy_read_timeout 控制两次上游读取之间允许的空闲时间,长空闲连接应按应用心跳和实际链路设置。Nginx 官方文档对 HTTP/1.1 默认值有版本说明:1.29.7 之前需显式设置;示例保留显式配置以兼容较旧版本。升级后的连接按隧道工作,不能把普通 HTTP 响应缓冲直接当作握手条件。长连接保活见WebSocket 代理如何保持长连接。

Caddy 如何用 reverse_proxy 转发 WebSocket

```caddyfile
example.com {
reverse_proxy 127.0.0.1:8080
}
```

这就够了。Caddy 会在转发时处理升级,不需要手写 Upgrade 和 Connection。只有业务需要限制整条流连接的最长存活时间时才设置 stream_timeout;它不是空闲超时,达到上限时活动连接也会关闭。外层 example.com { } 与上面相同:

```caddyfile
reverse_proxy 127.0.0.1:8080 {
stream_timeout 24h
}
```

stream_timeout 限制流连接总时长,默认不设此上限;不要用它代替心跳或空闲检测。配置重载时的 stream_close_delay 是另一项行为。transport http 的读写超时也应按对应文档和应用行为核实。配置项见 Caddy reverse_proxy 文档。

代理本身的主机、端口和鉴权写法,见帮助中心的代理设置。

升级头、空闲超时和响应缓冲会怎样影响连接

对比项NginxCaddy实际影响
HTTP/1.1 Upgrade通常需显式转发升级头;HTTP/1.1 默认值受版本影响reverse_proxy 处理升级配置与版本不匹配可能导致握手失败
空闲读超时proxy_read_timeout 控制上游读取空闲间隔依据具体传输配置按心跳和链路实际空闲策略判断
流连接总时长由具体配置决定stream_timeout 可设总时长上限到时会关闭活动连接
响应缓冲Upgrade 后是双向隧道;按实际数据路径排查流式转发不作为握手成功的必备条件
证书需另配 certbot自动申请续期部署步骤数量不同
HTTP/2取决于客户端与服务器实现取决于实现RFC 8441 定义扩展 CONNECT,支持情况需逐端核实

若使用传统 Upgrade,按 HTTP/1.1 握手流程排查;HTTP/2 扩展 CONNECT 是否可用取决于客户端、代理和上游实现。若只有特定目标失败,比较该目标的响应和代理日志,不要直接归因于出口。

如何设置 WebSocket 保活间隔并定位断连

按链路最短空闲超时设置 ping 间隔

链路上任一层的空闲策略都可能关闭连接,实际时限需查对应 CDN、负载均衡和应用配置,并用边缘及后端日志测量。不要把未经核实的固定秒数当作通用默认值。应用层心跳间隔应依据实测到的最短空闲时限设置,并留出网络抖动余量。

握手失败或连接中断时按四步排查

排障按这个顺序走,不要跳步:

1. curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" http://你的域名/ws/,看是否返回 101 Switching Protocols
2. 没有 101 就查 Nginx 的头和 proxy_pass 路径
3. 有 101 但很快断,记录断开间隔并对照各层实际超时配置与日志
4. 断得没有规律,结合代理、CDN 和后端日志检查连接限制或异常关闭原因

根据 400、502、504 和固定时长断连定位故障层

出现下面这些现象时,先查对应的一层,不要先改代理:

现象先查哪一层判断动作
握手返回 400 或 426Nginx 升级头核对 Upgrade、Connection 和 HTTP/1.1
返回 502后端后端进程、端口、路径是否与 proxy_pass 一致
返回 504Nginx 读超时看后端处理耗时,再调 proxy_read_timeout
101 之后 60 秒整断Nginxproxy_read_timeout 仍是默认值
101 后固定时长断开CDN、负载均衡或应用对照该层配置及日志确认空闲策略
消息延迟或成批到达应用写入、代理或中间层检查数据流和缓冲行为,不据此判断握手失败

超时、连接被拒和 TLS 证书错误是三组不同原因:超时多半卡在链路或上游,连接被拒说明端口那头没在听,证书错误说明中间有人在拦截或替换证书。先按 curl 报出的类型分开,再决定动哪一端。

FAQ

Caddy 还要不要显式写 Upgrade 头

不用。v2 的 reverse_proxy 会自动处理升级,手写反而可能覆盖掉它自己的逻辑。只有当你需要改写头内容时才用 header_up。

Nginx 报 502 和 504 分别查什么

502 是后端拒绝或崩溃,查后端进程和端口;504 是后端在超时内没响应,查 proxy_read_timeout 和后端处理耗时。两者都不指向代理 IP 本身。

HTTP/2 下 WebSocket 还能用吗

RFC 8441 定义了 HTTP/2 的扩展 CONNECT;是否可用取决于客户端、代理及服务端实现。本文配置示例采用传统 HTTP/1.1 Upgrade,部署时应核实整条链路支持的方式。


如果长连接主要面向需要稳定出口的业务后台,用静态住宅代理 IP 比频繁更换出口更省事,出口固定之后,超时和缓冲问题也更容易复现。