Skip to content

WebSocket 实时通信

握手升级 101、全双工帧通信、应用层心跳保活、与 SSE 及长轮询选型对比。

Updated View as Markdown
For humans

WebSocket 实时通信

校招考察频度:☆ 中频(实时通信与长连接·应用拓展) 生产导向主线:HTTP 传统的“一问一答”模式无法实现低延迟的服务端主动推送。WebSocket 通过一次标准的 HTTP 请求升级(101 Switching Protocols)将 TCP 连接转变为全双工双向长连接。面试重点:握手升级流程与 Sec-WebSocket-Key 校验、NAT 超时与应用层 Ping/Pong 心跳保活机制、以及 WebSocket vs SSE(Server-Sent Events)在生产中的选型。


一、握手升级机制(HTTP 101)

WebSocket 握手: 标准 HTTP 协议升级为全双工双向通信

  • 握手核心请求头:
    • Connection: Upgrade
    • Upgrade: websocket
    • Sec-WebSocket-Key:客户端随机生成的 Base64 字符串。
  • 服务端响应:
    • 服务端将该 Key 与固定的 GUID 字符串拼接后计算 SHA-1 哈希,返回 Sec-WebSocket-Accept。
    • 状态码返回 101 Switching Protocols。
    • 防误升级:该握手机制用于确认服务端确实理解 WebSocket 协议,防止老旧的透明 HTTP 缓存代理服务器误将长连接当成普通请求缓存。

二、生产痛点:为什么必须有应用层心跳?

在生产环境下,如果长时间没有消息交互,连接很可能会被防火墙、云厂商负载均衡器(ALB)或家用 NAT 路由器静默关闭(Dead Connection)。

  • 静默断开的危害:TCP 连接在中间设备已经被抹掉了路由表项,但客户端和服务端都不知道。当有新消息发送时,数据包被路由静默丢弃,最终触发长达数分钟的 TCP 超时重传,用户体验极其恶劣。
  • 生产心跳黄金法则:
    1. Ping/Pong 控制帧:WebSocket 协议原生支持 0x9(Ping)和 0xA(Pong)控制帧。
    2. 心跳间隔小于中间件空闲超时:例如云厂商 Nginx / ALB 默认空闲超时为 60 秒,生产心跳间隔通常配置为 25~30 秒。
    3. 双向保活与超时主动剔除:若连续 3 次未收到心跳回包,客户端主动重连,服务端主动断开释放文件描述符(fd)。

三、生产选型:WebSocket vs SSE vs 长轮询

在大模型(LLM)打字机流式输出、股票行情推送等场景中,面试官最爱问:“你们的 AI 对话为什么选 SSE 而不是 WebSocket?”

技术方案通信方向协议基础优势痛点与选型定位
HTTP 长轮询客户端向服务端伪推送HTTP 短请求挂起兼容性最好,无防火墙阻碍频繁建连开销大,延迟高,已被淘汰
SSE (Server-Sent Events)仅服务端向客户端单向推送标准 HTTP/1.1 或 HTTP/2 文本流 (text/event-stream)极度轻量,天然支持断线重连与事件 ID,完美穿越企业防火墙,原生支持 HTTP/2 多路复用只支持单向推送。大模型流式输出(ChatGPT/DeepSeek)的最优解!
WebSocket真正的全双工双向通信独立于 HTTP 的独立长连接协议双向极低延迟,支持自定义二进制与文本帧状态有状态、跨域与 LB 配置繁琐,连接维护成本高。多人在线游戏、IM 即时通讯的最优解!

面试高频追问

  1. WebSocket 握手成功后,底层还在用 TCP 吗? 还在用。WebSocket 是应用层协议,复用握手时建立的那条底层 TCP 连接,只是后续的数据收发不再遵守 HTTP 报文格式,而是使用轻量级的二进制数据帧(Frame)。
  2. 大模型流式输出(Chat)为什么优先选 SSE 而不是 WebSocket?
    • 场景本质是“用户发送一个 Query(客户端到服务端),大模型持续吐出几百个 Token(服务端到客户端单向流式推送)”,并不需要双向全双工。
    • SSE 基于标准 HTTP,零学习成本,自带断线重连,完美兼容已有的 API 网关鉴权、限流、日志监控和 HTTP/2 多路复用,架构复杂度远低于 WebSocket。
  3. 线上大量 WebSocket 连接如何做集群扩展与负载均衡?
    • 单台服务器支持万级长连接,集群部署时需借助 Redis Pub/Sub 或消息队列(Kafka/RocketMQ)作为分布式会话广播总线。
    • 用户 A 连在 Server-1,用户 B 连在 Server-2;Server-1 将 A 发送的消息发布到 Redis 频道,Server-2 订阅后下发给用户 B。
Navigation

Type to search…

↑↓ navigate↵ selectEsc close