单机WebSocket并发卡在1k–5k主因是系统资源未放开、Nginx未透传Upgrade头、事件模型选型不当;需调ulimit-n至65535+、配全proxy_set_header Upgrade $http_upgrade等三行、启用Libevent等高效事件循环。

单机 WebSocket 并发量不是靠猜,而是靠三步定位:先看系统资源是否放开,再确认代理层有没有拦住 Upgrade 头,最后才轮到服务端代码和事件模型。卡在 1k–5k 基本不是代码问题,而是 ulimit -n 还是 1024、Nginx 没配 proxy_set_header Upgrade $http_upgrade、或者还在用 Select 事件循环。
Linux 文件描述符和内核参数必须改
每个 WebSocket 连接至少占 1 个文件描述符(fd),默认 ulimit -n 是 1024,新连接直接被拒绝,日志里常出现 Too many open files 或静默失败。
- 临时生效:在启动服务的同一 shell 中执行
ulimit -n 65535(注意:systemd 服务需单独配置LimitNOFILE) - 永久生效:往
/etc/security/limits.conf加两行:* soft nofile 1048576和* hard nofile 1048576,并确保 Nginx / Workerman / Go 等进程由该用户启动 - 同步调优内核:
/etc/sysctl.conf加入net.core.somaxconn = 65535、net.ipv4.tcp_tw_reuse = 1、net.ipv4.ip_local_port_range = 1024 65535,然后运行sysctl -p
Nginx 代理必须透传 Upgrade 和 Connection 头
90% 的“连不上”本质是 Nginx 把 WebSocket 握手当普通 HTTP 处理,过滤掉关键头,后端收不到升级请求,返回 200 而非 101,客户端报错 Unexpected response code: 200。
-
location块中必须写全这三行:proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade" -
proxy_read_timeout和proxy_send_timeout建议设为86400(24 小时),不能沿用默认 60 秒,否则空闲心跳期间连接会被主动切断 - 务必关闭缓冲:
proxy_buffering off;禁用缓存:proxy_cache off;否则消息可能延迟甚至丢失
浏览器端并发限制是硬门槛,服务端扩容解决不了
Chrome/Firefox/Safari 对单域名 WebSocket 并发连接数限制为 6~10 个,这是 TCP 层面的同源连接上限,跟协议无关,也跟服务端能力无关。你把服务器堆到百万并发,前端依然最多建 6 条连接。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 子域名分片可行但麻烦:如
wss://ws1.example.com、wss://ws2.example.com,需 DNS + TLS 证书支持 - 更推荐路径级多路复用:只建 1 个连接,所有业务消息带
type字段路由,例如{"type":"notify","data":{}}或{"type":"chat","data":{}} - 不要频繁重连试探——会触发浏览器连接队列阻塞,反而加剧
CLOSE_ABNORMAL和重试风暴
压测工具选型和关键参数要匹配真实场景
用 JMeter 压 WebSocket,必须装 WebSocket Samplers by Peter Doornbosch 插件;用 Go 客户端压,得关掉 gorilla/websocket 默认压缩(加 compression=None 可省 50KB/连接内存);用 websocat 测延迟,得加 --print-ping-rtts 才能拿到真实 PING/PONG 往返时间。
- JMeter 线程组 Ramp-Up 时间不能设为 0,建议按目标连接数的 1/10 设置秒数(如压 1w 连接,Ramp-Up 设 1000 秒),避免瞬间打满
accept()队列 - Go 客户端测试时,
-conn=10000后记得调大系统ulimit -n,否则本地 fd 不够,连不上服务端 - 监控必须包含连接建立耗时、
onopen成功率、onerror频次,光看吞吐量(msg/s)容易误判——连接都建不稳,吞吐再高也没意义
真正卡住并发上限的,往往不是代码逻辑,而是 /etc/security/limits.conf 没改、Nginx location 块漏了一行 header、或者压测客户端自己先耗尽了文件描述符。这些点不检查一遍,调再多服务端参数都是白搭。










