SSE、长轮询与 WebSocket 连接资源对比及 Spring Boot 配置指南

一、背景

在构建实时消息推送系统时,开发者常面临三种主流技术选型:

  • 长轮询(Long Polling)
  • SSE(Server-Sent Events)
  • WebSocket

三者在连接模型、资源消耗、扩展性等方面差异显著。本文旨在对比其连接资源占用特性,并提供 Spring Boot 项目中的最佳实践与配置建议


二、连接模型与资源消耗对比

特性 长轮询 SSE WebSocket
通信方向 客户端拉(伪推) 服务器 → 客户端(单向) 双向
连接类型 短连接(但 hold 住) 持久 HTTP 连接 TCP 升级后独立连接
是否长期占用 HTTP 连接 ✅ 是(每次请求 hold 30~60s) ✅ 是(连接持续打开) ❌ 否(脱离 HTTP 协议栈)
线程模型 每请求占 1 线程(阻塞) 异步非阻塞(不占处理线程) 异步非阻塞(NIO)
并发连接压力 ⚠️ 极高(易线程爆炸) ⚠️ 高(受 socket 数限制) ✅ 低(单线程可处理数千连接)
适用场景 兼容老旧系统(最后选择) 通知、日志、行情等单向推送 聊天、游戏、协作编辑等双向交互

核心结论

  • 长轮询资源消耗最大,应避免用于高并发场景
  • SSE 比长轮询高效,适合中等规模单向推送
  • WebSocket 是高并发、低延迟、双向通信的首选

三、Spring Boot 中的连接数配置

3.1 Web 容器选择建议

容器 适用场景 优势
Tomcat 默认,通用场景 稳定、生态完善
Undertow 推荐用于 SSE / 长轮询 内存占用低,支持高并发连接
Netty(WebFlux) 超高并发或 Reactive 架构 完全非阻塞,单机支持 10w+ 连接

🔧 切换为 Undertow(Maven)

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

3.2 Tomcat 配置(application.yml)

yaml 复制代码
server:
  tomcat:
    max-connections: 20000      # 最大 socket 连接数(默认 8192)
    accept-count: 200           # 请求等待队列大小
    threads:
      max: 500                  # 处理线程数(SSE 建立后不占此线程)
      min-spare: 50
    connection-timeout: 60000   # 连接超时(毫秒)

⚠️ 注意 :SSE 连接建立后不占用 threads.max,但受 max-connections 限制。


3.3 Undertow 配置(推荐)

yaml 复制代码
server:
  undertow:
    io-threads: 8               # IO 线程数 ≈ CPU 核数
    worker-threads: 200         # 阻塞任务线程
    buffer-size: 1024
    queues:
      task: 1024                # 任务队列大小

✅ Undertow 默认支持数万并发连接,内存效率优于 Tomcat。


3.4 系统级限制(Linux)

每个 TCP 连接 ≈ 1 个文件描述符(fd),需调整系统限制:

bash 复制代码
# 查看当前限制
ulimit -n

# 临时提升(需 root)
ulimit -n 65536

# 永久生效:编辑 /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

💡 建议:ulimit -n ≥ 预期最大连接数 × 1.2


四、容量估算与选型建议

用户规模 推荐方案 关键配置
< 1,000 SSE + Tomcat 默认配置即可
1,000 ~ 50,000 SSE + Undertow + Redis Pub/Sub max-connections=50000 + ulimit -n 65536
> 50,000 或需双向通信 WebSocket + NettyWebFlux Reactive SSE 集群部署 + 连接分片

五、SSE 项目优化 Checklist

  • 使用 Undertow 替代 Tomcat(降低内存)
  • 配置 server.undertow.max-connections 足够大
  • 系统 ulimit -n 调高(> 连接数 × 1.2)
  • 使用 Spring 的 SseEmitter(已支持异步)
  • 及时清理失效连接 (注册 onTimeout / onError 回调)
  • 集群环境使用 Redis Pub/Sub 广播消息
  • 通过 /actuator/metrics 监控在线连接数

六、附:Reactive SSE(WebFlux)示例(超高并发)

java 复制代码
@GetMapping(value = "/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> events() {
    return Flux.interval(Duration.ofSeconds(1))
               .map(seq -> ServerSentEvent.builder("tick-" + seq).build());
}

✅ 基于 Reactor 模型,单机可支持 10万+ 并发连接,适合大型实时系统。


七、总结

问题 回答
SSE 会占用很多 HTTP 连接吗? ✅ 会,每个用户占 1 个持久 HTTP 连接,但比长轮询高效得多
WebSocket 会占用很多连接吗? ❌ 不会,基于 NIO,连接成本极低
Spring Boot 需要配置连接数吗? 必须配置! 尤其是 max-connections 和系统 ulimit

🎯 选型口诀
单向推送用 SSE,双向交互选 WebSocket,长轮询仅作兜底。


📌 文档结束

如需完整可运行的 Spring Boot + SSE + Redis 集群示例工程,请联系作者获取。


相关推荐
像少年啦飞驰点、1 小时前
零基础入门 Spring Boot:从“Hello World”到可上线的 Web 应用全闭环指南
java·spring boot·web开发·编程入门·后端开发
有来技术1 小时前
Spring Boot 4 + Vue3 企业级多租户 SaaS:从共享 Schema 架构到商业化套餐设计
java·vue.js·spring boot·后端
皇帝要考研1 小时前
【ISO 13400-2:2019】核心配置项
网络·网络协议
东东5161 小时前
xxx医患档案管理系统
java·spring boot·vue·毕业设计·智慧城市
东东5162 小时前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
JoySSLLian2 小时前
IP SSL证书:一键解锁IP通信安全,高效抵御网络威胁!
网络·人工智能·网络协议·tcp/ip·ssl
云小逸4 小时前
【网络通信】DNS、SNMP、DHCP 等 UDP 服务解析
网络·网络协议·udp
qq_12498707534 小时前
基于Srpingboot心晴疗愈社平台的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·spring·microsoft·毕业设计·计算机毕业设计
大爱编程♡4 小时前
SpringBoot统一功能处理
java·spring boot·后端
半壶清水5 小时前
[软考网规考点笔记]-操作系统核心知识及历年真题解析
网络·网络协议·算法