一次生产环境 WebSocket 连接断开的排查与解决

发布于 2025-11-08  |  分类:Bug复盘

上周五临下班前,测试反馈了一个诡异的问题:测试平台的实时日志功能,大概每过 1 分钟就会自动断开连接,前端报错 `Connection Closed`。

1. 问题复现与初步定位

我在本地开发环境(Localhost)测试了一下,挂机 10 分钟都没有断开。这说明代码本身逻辑没有大问题,大概率是环境差异导致的。

打开浏览器的 Network 面板,观察 WebSocket 连接。发现每次断开的时间点都极其规律:正好是 60 秒

2. 排查链路

我们的部署架构是:浏览器 -> Nginx (反向代理) -> Django (daphne)

既然是 60 秒断开,我首先怀疑是 Nginx 的超时配置。查看服务器上的 nginx.conf


location /ws/ {
    proxy_pass http://backend_ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # ❌ 问题就在这里,默认是 60s
    # proxy_read_timeout 60s; 
}
        

3. 解决方案

原因找到了:Nginx 默认的 proxy_read_timeout 是 60 秒。如果后端在 60 秒内没有向前端发送任何数据(心跳包),Nginx 就会认为连接超时,主动断开。

修改配置,增加超时时间:


location /ws/ {
    # ... 其他配置 ...
    proxy_read_timeout 3600s;  # 改为 1 小时
    proxy_send_timeout 3600s;
}
        

重启 Nginx 后,问题解决。

4. 反思

这次事故提醒我:在做长连接业务时,心跳机制(Ping/Pong)非常重要。除了依赖 Nginx 的超时配置,应用层也应该每隔 30 秒发送一次心跳包保活。