Nginx生产级WebSocket实时长连接负载均衡,一文搞定

简介: 本文从基础配置、生产配置、Docker / K8s、安全、排障、性能调优,系统性讲清 WebSocket 在 Nginx 中的正确打开方式。

本文作者银河技术,有修订和改动。

1、引言

WebSocket 是基于 HTTP/1.1 Upgrade 机制实现的全双工长连接通信协议,广泛应用于 IM即时通讯、实时通知、协同编辑、行情推送、游戏服务等场景。

由于 WebSocket 是长连接 + 状态敏感的协议,在 Nginx 中做反向代理时,需要特别注意一些细节。

这些细节主要是:

  • 1)协议升级(Upgrade);
  • 2)连接保持;
  • 3)超时控制;
  • 4)负载均衡策略;
  • 5)云环境 / K8s 场景下的断连问题。

本文从基础配置、生产配置、Docker / K8s、安全、排障、性能调优,系统性讲清 WebSocket 在 Nginx 中的正确打开方式。

2、WebSocket如何建立长连接

WebSocket 通过 HTTP/1.1 完成握手:

GET /ws HTTP/1.1

Upgrade: websocket

Connection: Upgrade

一旦升级成功,连接将不再遵循 HTTP 请求-响应模型,而是长期保持的双向 TCP 通道。

PS:这也是为什么 WebSocket 对 Nginx 超时 / FD / 内核参数 / LB 极度敏感。

更多WebSocket基础资料可以继续阅读:

  1. WebSocket从入门到精通,半小时就够!
  2. 刨根问底HTTP与WebSocket的关系(上篇)
  3. 刨根问底WebSocket与Socket的关系
  4. 搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE
  5. Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?
  6. 理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

3、基础WebSocket反向代理配置

http {

   # 基础 WebSocket 代理配置

   upstream websocket_backend {

       server 192.168.1.100:8080;

       server 192.168.1.101:8080;

       # 支持长连接

       keepalive 10;

   }

 

   server {

       listen 80;

       server_name ws.example.com;

 

       location /ws/ {

           # 核心 WebSocket 配置

           proxy_pass http://websocket_backend;

           proxy_http_version 1.1;

           proxy_set_header Upgrade $http_upgrade;

           proxy_set_header Connection "upgrade";

 

           # 重要:传递原始主机头和客户端 IP

           proxy_set_header Host $host;

           proxy_set_header X-Real-IP $remote_addr;

           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

           proxy_set_header X-Forwarded-Proto $scheme;

 

           # 长连接超时设置

           proxy_read_timeout 3600s;

           proxy_send_timeout 3600s;

           proxy_connect_timeout 30s;

 

           # 禁用缓冲,确保实时性

           proxy_buffering off;

           proxy_cache off;

       }

   }

}

补充说明:

  • 1)proxy_http_version 1.1:WebSocket 必须;
  • 2)Upgrade / Connection:完成协议升级;
  • 3)proxy_buffering off:防止消息延迟;
  • 4)proxy_read_timeout:防止 Nginx 主动断连。

4、生产环境必须补充的 Upgrade 头处理(关键)

注意:这是原始配置中最容易踩坑、但极其重要的一点。

推荐写法:

map $http_upgrade $connection_upgrade {

   default upgrade;

   '' close;

}

然后在 location 中:

proxy_set_header Upgrade $http_upgrade;

proxy_set_header Connection $connection_upgrade;

为什么这样更安全?

  • 1)非 WebSocket 请求 → Connection: close;
  • 2)WebSocket 请求 → Connection: upgrade。

PS:避免普通 HTTP 请求被错误升级。

5、完整生产级WebSocket配置

http {

   upstream websocket_cluster {

       ip_hash;

 

       server 10.0.1.10:8080 weight=3;

       server 10.0.1.11:8080 weight=2;

       server 10.0.1.12:8080 backup;

 

       # 以下健康检查依赖 nginx_upstream_check_module(非官方)

       check interval=3000 rise=2 fall=3 timeout=1000 type=http;

       check_http_send "GET /health HTTP/1.0\r\n\r\n";

       check_http_expect_alive http_2xx http_3xx;

   }

 

   server {

       listen 443 ssl http2;

       server_name ws.example.com;

 

       ssl_certificate /etc/nginx/ssl/example.com.crt;

       ssl_certificate_key /etc/nginx/ssl/example.com.key;

       ssl_protocols TLSv1.2 TLSv1.3;

 

       location /chat/ {

           proxy_pass http://websocket_cluster;

 

           # WebSocket 升级

           proxy_http_version 1.1;

           proxy_set_header Upgrade $http_upgrade;

           proxy_set_header Connection $connection_upgrade;

 

           # 原始请求信息

           proxy_set_header Host $host;

           proxy_set_header X-Real-IP $remote_addr;

           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

           proxy_set_header X-Forwarded-Proto $scheme;

 

           # ⚠️ 长连接超时

           proxy_read_timeout 86400s;

           proxy_send_timeout 86400s;

 

           # 实时性

           proxy_buffering off;

 

           # 连接限制

           limit_conn ws_conn 1000;

       }

   }

}

limit_conn_zone $binary_remote_addr zone=ws_conn:10m;

6、HTTP/2 与 WebSocket 的现实情况

基本配置:

listen 443 ssl http2;

重要认知:

  • 1)浏览器 WebSocket 仍使用 HTTP/1.1;
  • 2)HTTP/2 WebSocket(RFC 8441):浏览器支持有限、Nginx 支持不完整。

PS:这是正常现象,不是配置错误。

WebSocket location 必须显式:

proxy_http_version 1.1;

7、Docker / K8s 场景

map $http_upgrade $connection_upgrade {

   default upgrade;

   '' close;

}

 

server {

   listen 80;

 

   location /ws/ {

       proxy_pass http://websocket-service:8080;

 

       proxy_http_version 1.1;

       proxy_set_header Upgrade $http_upgrade;

       proxy_set_header Connection $connection_upgrade;

 

       proxy_read_timeout 7d;

       proxy_send_timeout 7d;

 

       proxy_buffering off;

   }

}

K8s / 云环境的隐藏断连点:

PS:Nginx 再怎么配都没用,必须应用层心跳

8、WebSocket心跳保活(生产必做)

推荐 20~30 秒一次:

{ "type": "ping" }

否则云 LB、防火墙、NAT,都会主动断你连接。

9、负载均衡策略的选择

upstream websocket_backend {

   ip_hash;

   server 10.0.1.10:8080;

   server 10.0.1.11:8080;

}

实战建议:

PS:WebSocket 本质上 不适合强依赖 LB 算法做会话保持

10、优雅下线与灰度发布(生产增强)

K8s 必配:

terminationGracePeriodSeconds: 60

后端逻辑:

  • 1)收到 SIGTERM;
  • 2)停止新 WS;
  • 3)通知客户端重连;
  • 4)平滑下线。

11、Nginx及Linux内核参数(高并发必调)

Nginx配置如下:

worker_processes auto;

worker_rlimit_nofile 200000;

 

events {

   worker_connections 65535;

   use epoll;

}

Linux操作系统的配置:

net.core.somaxconn = 65535

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 15

12、写在最后

指令如下:

wscat -c ws://domain/ws

ss -an | grep ESTAB | wc -l

13、参考资料

[1] RFC6455 协议文档、WebSocket API文档、SSE API文档

[2] 新手入门贴:史上最全Web端即时通讯技术原理详解

[3] Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

[4] 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket

[5] 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

[6] 搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE

[7] WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

[8] WebSocket详解(六):刨根问底WebSocket与Socket的关系

[9] Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?

[10] WebSocket从入门到精通,半小时就够!

[11] 理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

[12] 浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)》

[13] 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗

[14] 零基础IM开发入门(一):什么是IM系统?

[15] 转转客服IM系统的WebSocket集群架构设计和部署方案

[16] 基于WebSocket的IM即时通信方案在H5游戏场景下的技术实践

[17] 详解AI大模型实时通信为什么选SSE,而不是WebSocket和WebRTC

[18] 都HTML5了,Web端即时通讯技术到底该用什么?一文即懂!

即时通讯技术学习:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK(备用地址点此)

(本文同步发布于: http://www.52im.net/thread-4921-1-1.html)

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
相关文章
|
1月前
|
弹性计算 Linux 网络安全
阿里云ECS使用教程:云服务器远程连接教程,使用阿里云自带Workbench登录超简单!
阿里云ECS创建后,推荐使用内置Workbench工具远程连接:免密、免安装、支持无公网IP实例,浏览器直接操作,简单高效完成Linux服务器管理。阿里云服务器ECS官网:https://t.aliyun.com/U/AZBUsA
|
应用服务中间件 nginx
Nginx日志格式不生效
Nginx日志格式不生效
|
3月前
|
弹性计算 负载均衡 网络协议
阿里云负载均衡SLB对接使用完全指南:从入门到生产级实战
本文系统讲解阿里云负载均衡SLB的完整对接使用流程。从ALB、NLB、CLB三大产品家族的选型策略切入,深入剖析四层与七层负载均衡的核心原理与差异。文章详细覆盖实例创建、服务器组配置、监听规则设置、健康检查参数调优、会话保持机制、安全组与访问控制配置、HTTPS证书部署、监控报警设置等全链路操作步骤,并提供阿里云CLI命令行工具及Python SDK的代码示例。同时结合高并发场景下的最佳实践,分享权重梯度调整、连接复用优化、跨可用区容灾部署等进阶技巧,帮助读者构建高可用、高性能的流量分发架构。
|
6月前
|
自然语言处理 前端开发 JavaScript
前端组件库——Bulma知识点大全(一)
教程来源 http://qcycj.cn/category/jiulishi.html Bulma是一款基于Flexbox的现代化纯CSS框架,零JavaScript依赖,类名语义直观、响应式开箱即用。支持Sass深度定制,模块化设计轻量灵活,广受后端与独立开发者青睐。
|
5月前
|
消息中间件 网络协议 测试技术
socket长连接在手游场景下的技术实践
本文介绍了37手游基于B站goim框架自研长连接系统的实践。系统采用分层设计,支持多协议和发布/订阅机制,用于直播弹幕、实时推送等场景,实现了高性能与业务适配。
333 4
socket长连接在手游场景下的技术实践
|
缓存 负载均衡 算法
slb支持多种负载均衡算法
slb支持多种负载均衡算法
661 6
|
11月前
|
人工智能 达摩院 Anolis
龙蜥操作系统装机量突破1000万,市占率近50%,首发支持RISC-V RVA23预览版!
报告调研显示,在国产操作系统迁移意愿方面,龙蜥操作系统的吸引力最高,用户意愿迁移至龙蜥生态社区版和商业版的比例为 54.25%,占比第一。
|
12月前
|
人工智能 JSON 前端开发
ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术
本文将带你快速认识SSE实时通信协议,包括它的技术原理、常见使用场景、与同类技术的对比以及简单的示例代码等。
479 0
ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术
|
存储 消息中间件 容灾
阿里IM技术分享(八):深度解密钉钉即时消息服务DTIM的技术设计
本文是国内企业IM的事实王者钉钉首次对外深度解密其即时消息服务(即DingTalk IM,简称DTIM)的技术设计实践。
2397 1
阿里IM技术分享(八):深度解密钉钉即时消息服务DTIM的技术设计

热门文章

最新文章