在 Cloudflare 背后保持 WebSocket 长连接不掉线,需要在 Cloudflare 控制台开启 WebSocket 支持,确保使用受支持的端口(如 443),并在服务端与客户端之间实现应用层心跳机制,同时调整反向代理超时时间大于心跳间隔。
先说结论:Cloudflare 默认支持 WebSocket,但空闲超时限制和端口策略是断连主因,必须配合应用层心跳和代理配置协同保活。
- 适合场景:使用 Cloudflare DNS 代理(小黄云)且业务依赖长连接推送的 Web 或移动端应用。
- 先准备:确认 Cloudflare 网络设置中 WebSocket 开关已开启,服务端 Nginx 或负载均衡器已配置 Upgrade 头透传。
- 验收:通过浏览器开发者工具 Network 面板观察 WebSocket 帧交互,确认 Ping/Pong 正常且连接未因空闲被重置。
命令速用版
若使用 Nginx 作为 Cloudflare 后的反向代理,需确保以下配置项生效,否则握手成功后仍会被中间层切断。
location /ws {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}注意:proxy_read_timeout 必须大于客户端心跳间隔,建议设置为心跳间隔的 2 倍以上。
为什么会这样
WebSocket 断连通常不是协议错误,而是网络中间设备(Cloudflare、Nginx、防火墙)清理了空闲连接。Cloudflare 作为反向代理,对空闲连接有默认超时策略,若长时间无数据交互,会主动发送 FIN 包断开连接。服务端若未配置透传 Upgrade 头,握手会降级为 HTTP 或直接失败。客户端若只发心跳不校验响应,无法感知连接已死,导致“假在线”。
分步处理
第一步:检查 Cloudflare 控制台设置
登录 Cloudflare dashboard,进入域名管理页,点击 Network 选项卡。确认 WebSockets 选项处于开启状态(默认通常开启)。若未开启,WebSocket 握手将无法完成升级。
第二步:确认端口在白名单内
Cloudflare 仅转发特定端口的 WebSocket 流量。优先使用 80 或 443 端口。若使用非标准端口,需确认其在 Cloudflare 支持的端口列表内(如 8443、2053、2083、2087、2096 等),否则流量会被丢弃。
第三步:配置服务端心跳与超时
在应用代码中实现双向心跳。客户端每 30 秒发送 Ping,服务端收到后立即回复 Pong。服务端需记录最后活跃时间,若超过阈值(如 60 秒)未收到心跳,主动关闭连接以释放资源。Nginx 的 proxy_read_timeout 建议设置为 86400 秒或至少大于心跳间隔的 2 倍。
第四步:处理移动端后台限制
移动端浏览器(iOS Safari/Android Chrome)在页面切后台后会暂停 JavaScript 定时器,导致心跳发送中断。需在应用层设计重连机制,当页面回到前台时检测连接状态并自动重连,或依赖服务端推送唤醒(需配合系统级推送服务)。
怎么验证是否生效
打开浏览器开发者工具,进入 Network 面板,筛选 WS 协议。观察连接建立后的帧交互:
- 确认 Status 为 101 Switching Protocols。
- 查看 Messages 标签,确认每隔固定时间有 Ping/Pong 文本或二进制帧交互。
- 观察 Time 列,连接持续时间应远超 60 秒,若固定在 60 秒或 100 秒断开,说明超时配置未生效。
服务端日志应显示心跳接收记录,若日志中断但客户端未报错,通常是中间层静默断开。
常见坑
1. 只发心跳不校验响应
客户端仅用 setInterval 发送消息,未监听 Pong 响应。若连接已断,send 操作可能静默失败或抛出异常,导致客户端以为在线。必须设置超时定时器,未收到 Pong 则主动重连。
2. Nginx 默认超时未调整
Nginx 默认 proxy_read_timeout 为 60 秒。若心跳间隔设为 60 秒,极易因网络抖动导致超时断连。必须显式调大该值,并确保 proxy_http_version 为 1.1。
3. 移动端后台保活误区
试图通过纯前端心跳保持移动端后台连接通常无效。操作系统会冻结后台页面进程。需接受后台断连事实,设计好消息队列补偿或重连逻辑,而非强行保活。
常见问题
Cloudflare 免费计划支持 WebSocket 吗?
支持。Cloudflare 免费计划默认支持 WebSocket 协议,但空闲超时时间较短,通常建议在 100 秒内完成一次数据交互。
为什么本地测试正常,上线就断?
本地测试通常直连服务端,绕过了 Cloudflare 和负载均衡器。上线后流量经过代理层,若未配置 Upgrade 头透传或超时时间不足,连接会被代理服务器清理。
心跳间隔设置多少秒合适?
建议设置为 25 至 30 秒。需小于 Cloudflare 及中间代理的空闲超时阈值,同时预留网络波动缓冲时间,避免频繁重连。
参考来源
- WebSocket 长连接如何保持不掉线 服务器与前端心跳检测代码【核心】
- Cloudflare 开启 DNS Proxy 后 Websocket 连不上的问题排查
- 怎么解决分布式长连接系统中 WebSocket 经过负载均衡频繁断线断开的难题
- WebSocket 心跳机制:如何实现长连接的稳定保活?