SSE 与 WebSocket 并发连接上限详解
一、核心结论先行
两者本质都是长连接TCP,单进程默认上限由三层限制决定:
- 操作系统文件句柄(ulimit)
- 服务端框架单进程事件循环承载能力
- 反向代理(Nginx)连接数限制
SSE / WebSocket 单进程理论上限几乎一致,差异不在协议,在业务开销;常规生产配置单进程可轻松万级连接,集群可达十万/百万。
二、三层限制拆解(决定最大并发)
1. 操作系统:文件描述符 fd(最常见瓶颈)
每个TCP长连接占用1个fd,Linux默认限制极低:
- 查看:
ulimit -n,默认通常1024
→ 单进程最多同时1000左右长连接,超出直接报错too many open files - 调优:
# 临时生效 ulimit -n 65535 # 永久 /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535
单机器全局总fd还要看 /proc/sys/fs/file-max,服务器一般调到百万级。
2. Nginx 反向代理层(前端瓶颈)
WebSocket/SSE都走Nginx转发,Nginx worker单进程也有连接上限:
# nginx.conf
worker_connections 65535; # 单worker最大连接
worker_processes auto;
公式:Nginx整机最大连接 = worker_processes × worker_connections
3. 服务端框架单进程承载能力
异步IO框架(Node.js/Go/Gin/Spring WebFlux/Tornado)基于epoll/kqueue,单进程万连接无压力;同步阻塞框架(Spring MVC 同步Servlet)性能极差,几千连接就卡顿。
三、SSE 和 WebSocket 并发能力对比
相同点
- 底层都是TCP长连接,占用fd规则完全一样,理论最大并发数值无区别;
- 受ulimit、Nginx、内核参数限制完全相同;
- 空闲连接内存开销接近(几百KB/连接)。
不同点(实际可承载连接数有细微差距)
- SSE 单向下行,开销略低,同硬件可多承载10%~30%连接
- SSE:HTTP长连接,仅服务端→客户端推送,客户端只发一次初始GET,无持续上行报文;
- WebSocket:双向全双工,心跳、客户端上行消息持续收发,CPU/内存开销更高。
- 浏览器单域名连接限制(客户端侧硬限制)
- SSE:浏览器对同一域名最多6个并发SSE通道;
- WebSocket:同一域名同样限制6条;
客户端侧限制和服务端支持多少连接无关,是浏览器标准。
- 断线重连差异影响有效并发
SSE内置自动重连,短断开会快速重建,瞬时连接数波动更大;WebSocket需手动实现重连。
四、各场景常规并发参考值
1. 开发机默认配置(ulimit=1024)
单进程最大同时长连接:800~1000,SSE略多一点。
2. 常规线上单进程调优(ulimit=65535,异步框架 Go/Node/SpringWebFlux)
- WebSocket 双向频繁收发:2万 ~ 4万 并发连接
- SSE 纯推送、极少上行:3万 ~ 5万 并发连接
3. 单机多进程集群(8核机器,多进程+Nginx调优)
整机合计:10万 ~ 30万 并发长连接
4. 分布式集群(多服务器+Redis/MQ做消息广播)
水平扩容无上限,百万并发成熟方案。
五、容易踩坑的误区
- ❌ WebSocket 比 SSE 支持更少连接?
✅ 协议本身无上限区别,只是双向通信增加CPU消耗,同等资源下SSE能承载更多。 - ❌ 短连接服务和长连接服务并发标准一样
✅ 短连接用完即释放fd;长连接永久占用fd,并发上限完全由文件句柄决定。 - ❌ 单台机器可以无限开百万连接
单台服务器内存/内核参数有上限,10万并发长连接会占用数十GB内存。
六、快速提升并发连接的关键调优清单
- 调高系统
ulimit -n、file-max; - Nginx 加大
worker_connections; - 使用异步非阻塞服务端(禁止同步Servlet做长连接);
- 业务空闲连接设置合理心跳,及时清理死连接;
- 高并发场景分布式集群,用消息中间件同步推送消息。

浙公网安备 33010602011771号