实时通信协议对比速查:WebSocket、MQTT、SSE等十大方案选型指南
刚接手一个项目时,团队为“实时消息到底用哪个协议”吵了整整一周:做前端的说上 WebSocket,做物联网的同事坚持 MQTT,领导又提了一句“那 SSE 是不是更简单”。这种争论我很熟悉,因为实时通信协议这个领域看起来选择很多,实际上能放到同一维度比较的协议只有那么几个,而市面上十个里至少有三个是不同层级的产物,强行对比只会越比越乱。这篇文章就把我平时排查问题、做技术选型时反复用过的一份“实时通信协议对比速查”整理出来,涵盖 WebSocket、SSE、WebRTC、MQTT、CoAP、STOMP、AMQP、XMPP、Socket.IO、QUIC 这 10 个常见协议/方案,讲清楚每个协议解决什么问题、底层怎么工作、适合什么场景以及有哪些坑。无论你是架构师、后端开发、前端,还是做 IoT 或音视频的工程师,这份速查都可以直接拿去用。
1. 先理清一件容易搞混的事:这些协议根本不在一个层级
1.1 传输层、应用层、封装库的区别,别拿苹果比橘子
做实时通信选型,第一个陷阱就是“把不同层级的协议放在一起比”。网络通信有明显的分层,TCP 和 UDP 是传输层,HTTP、WebSocket、MQTT、CoAP、AMQP、STOMP 这些是应用层,而 Socket.IO 严格来说是“基于 WebSocket 的封装库和协议扩展”,XMPP 也常以库的形式出现。但实际工作中很多人把 Socket.IO 和 WebSocket 摆在一起二选一,就像拿“微信”和“手机网络”对比一样——前者是构建在后者之上的产物,关联但不属于同一层面。
如果非要画一张关系图:QUIC 是传输层的“TCP 替代者”,它让 HTTP/3 跑在 UDP 上;WebSocket 和 SSE 都寄生在 HTTP 三次握手之上,一个做全双工、一个做单向推送;MQTT 和 CoAP 是面向受限设备和弱网的专用应用层协议;STOMP、AMQP 需要消息代理(如 RabbitMQ、ActiveMQ)支撑,是消息中间件的“方言”;XMPP 则是有着二十年历史的即时通讯协议。Socket.IO 可以理解为 WebSocket 的“自动挡版本”,内部会自动降级到 HTTP 长轮询。
1.2 为什么层级混乱会导致选型错误
我见过最典型的错误:某团队要做“服务器向下发通知到浏览器”,技术负责人直接说“上 WebRTC”。其实需求只是单向推送,SSE 就够了,WebRTC 为了音视频传输做了一大堆 ICE、DTLS、SRTP 的复杂机制,对纯文本通知完全是杀鸡用牛刀。反过来的错误也有,IoT 设备端上报数据,有人选了 WebSocket,结果设备是 1MB RAM 的 MCU,WebSocket 的握手和帧解析对硬件来说既臃肿又耗电,MQTT 仅凭几个字节的小报文就能跑起来。
先搞清楚你在哪个层做选择,再看协议本身的机制是否匹配。否则你会在 SSM 框架还是 RocketMQ 这类毫无关联的东西之间左右摇摆,最后浪费好几天。
2. 十个协议逐个速查:定位、原理、优势与坑
这一节是核心。每个协议我会用一句话定位、一段原理讲清楚“为什么它长这样”,再列出优点和坑。如果你时间紧,可以先看第 3 节的速查表。
2.1 WebSocket:全双工长连接的行业标准
WebSocket 是目前浏览器实时通信的事实标准。它通过 HTTP Upgrade 头把连接升级为 TCP 长连接,之后客户端和服务端可以双向、实时地收发消息。它的帧格式相对简单,有文本帧和二进制帧,并且天然有消息边界,不像原始 TCP 数据流那样需要自己处理粘包问题。因为握手经由 HTTP,所以它可以复用已有的 80/443 端口和鉴权体系,天然穿过大多数企业防火墙。
优点是浏览器原生支持,全双工、低延迟,消息头很小,用起来直接。坑主要有三个:一是负载均衡场景下要配置 sticky session 或让网关感知长连接,否则请求被分发到不同后端节点就断了;二是公司内部如果有多层 HTTP 代理,部分代理会拦截或缓冲 WebSocket 帧,导致连接一直握手失败;三是很多新手忽略了浏览器对同一域名的连接数限制以及跨域 Origin 校验,埋下安全隐患。
2.2 SSE:够用就好的单向服务器推送
Server-Sent Events,对很多人来说是冷门选手。它建立在 HTTP 之上,允许服务器向浏览器持续推送数据,方向是单向的。浏览器端通过 EventSource API 使用,响应内容的 Content-Type 是 text/event-stream,不同事件用换行分隔。SSE 最反直觉的优点反而是它的“弱”:因为不搞双向,它实现起来极其简单,而且浏览器和服务器之间是普通 HTTP 连接,任何能跑 HTTP 的架构都能直接支持。
很多人不知道 SSE 自带断线重连机制——连接断了浏览器会自动重连,并且带上 Last-Event-ID 头告诉服务器“从哪儿接着发”。我私下叫它“性价比之王”:如果业务只需要服务端推送(比如订单状态变化、行情价格更新、日志下发),SSE 比 WebSocket 至少省一半的工作量。坑在于 IE 和部分老浏览器不支持,移动端原生 App 也没有标准化的 SSE 客户端,通常要自己封装轮询。
2.3 WebRTC:浏览器点对点音视频传输
WebRTC 并不是一个单一协议,而是一整套实时音视频通信方案,内部用到了 ICE 做网络穿透,DTLS 做传输加密,SRTP 承载音视频数据,信令则通常走 WebSocket 或普通 HTTP。它的核心亮点是端到端直连:两端通过 STUN 服务器发现公网地址,必要时通过 TURN 服务器中转。这种 P2P 设计让媒体数据尽量不经过中心服务器,显著降低带宽成本。
最容易被低估的是 NAT 穿透。你以为客户端之间能直连,实际在对称 NAT 环境下直连成功率并不高,很多请求还是要走 TURN 中转,而 TURN 流量是计费的,而且不便宜。做音视频选型时先想清楚:是少量 1 对 1 通话(P2P 足够),还是多人会议室。多人场景通常要用 SFU/MCU 架构和 MediaSoup、LiveKit 这类方案,纯 WebRTC 网格方案到四路以上就非常吃力。
2.4 Socket.IO:WebSocket 之上的“自动挡”
Socket.IO 常被误认为协议,它本质上是 Node.js 生态里的一个实时通信库,后来扩展到多语言实现。它在 WebSocket 之上增加了房间(room)、命名空间(namespace)、自动重连、心跳、广播等高层能力,并且自带降级机制:WebSocket 连不上会自动切到 HTTP 长轮询。对团队来说,最大的价值是 API 设计友好,业务代码非常简单。
但你要清醒地认识到,它的“自动挡”也意味着“黑盒”。一旦连接不稳定,客户端会悄悄从 WebSocket 降到轮询,延迟瞬间变高,而你的监控系统如果只盯着 WebSocket 维度,根本发现不了问题。另一个坑是 Socket.IO 协议有版本兼容问题,客户端和服务端版本不一致时会静默失败。用过一段时间,我的体会是:如果你已经决定全部走 WebSocket,且团队有能力处理连接管理,原生 WebSocket 反而更可控;如果要想快速交付,Socket.IO 确实香。
2.5 MQTT:物联网消息轻量之王
MQTT 因为物联网而流行,本质是发布/订阅模型,跑在 TCP 上,默认端口 1883,TLS 版是 8883。它最醒目的特征是三个 QoS 等级:QoS 0 最多发一次,QoS 1 至少发一次,QoS 2 恰好一次。加上遗嘱消息(Last Will)、保留消息(Retained)、会话状态续传等机制,专门应对设备断网、弱网、掉线重连的恶劣环境。
一条普通消息的固定头只有 2 个字节,带宽开销极低,所以车载T-Box、水表电表、农场传感器这类只有几 KB 内存的设备都能跑。我做过的 MQTT 选型里,Broker 通常选 EMQX 或 Mosquitto,前者在百万连接场景表现不错,后者适合小规模部署。坑在于是主流的 Broker 默认 QoS 1 下可能发生消息重复,消费端必须做幂等;另一个是订阅主题的通配符(+ 和 #)设计不当,容易把权限控制绕过去,一定要按租户隔离主题前缀。
2.6 CoAP:受限设备上的“HTTP 简化版”
CoAP 是为物联网设计的另一个应用层协议,和 MQTT 最大的差异在于它跑在 UDP 上,风格却模仿 HTTP,有 GET/POST/PUT/DELETE 方法,用 URI 表示资源。它通过 CON(需要确认)和 NON(不需要确认)两种消息类型实现不同可靠等级,配合 Blockwise 分块传输来解决 UDP 报文大小限制。很多智能路灯、传感网络用的就是 CoAP,因为 UDP 没有握手成本,通信时延更低、资源占用更小。
和 MQTT 的选择逻辑非常关键:如果业务是“设备上传数据、服务端集中处理”,MQTT 更合适,因为发布/订阅模型天然支持一对多分发;如果业务是“服务端查询设备上的某个资源、设备主动暴露接口”,CoAP 更顺手,因为它就是请求/响应模型。我曾经在构建网关时用了 MQTT,结果做设备远程配置时需要模拟一对一的资源访问,绕了一圈才用 CoAP 的观察模式解决。多问一句“这一步是推送数据还是操作资源”,答案就清晰了。
2.7 STOMP:消息队列与 Web 之间的温和连接
STOMP(Simple Text Oriented Messaging Protocol)是一个基于文本的消息协议,设计目标很明确——让不同语言写的客户端都能和消息代理对话。它定义了一组 Frame(命令帧),例如 CONNECT、SEND、SUBSCRIBE、ACK,通过这个统一格式把消息标题、目标和内容都塞进文本帧里。它不负责底层传输,所以你在 Web 场景看到的通常是“STOMP over WebSocket”:浏览器连 WebSocket,上面再跑 STOMP 语义。
这套组合在 Spring Boot + RabbitMQ/ActiveMQ 的实时推送方案里很常见,因为 Spring 框架自带 STOMP 支持,后端可以轻松把业务消息路由到 Web 客户端。好处是模式简单、协议直观,而且和消息队列的消费组、队列路由深度集成。坑在于文本协议对二进制传输不友好,视频、文件直接传会有额外开销;另外它强制依赖消息代理,如果你本身没有 RabbitMQ 这种中间件,就别为了一个推送功能引入一整套路由体系。
2.8 AMQP:企业级消息路由大师
AMQP 是一种面向消息中间件的有线协议,规格丰富,包含 Exchange、Queue、Binding、Virtual Host、消息确认、事务等一堆概念。RabbitMQ 是 AMQP 最著名的实现,通过 Exchange 做灵活路由,配合不同的路由键可以把一条消息送到多个队列,是微服务架构中异步解耦的常客。它的可靠性机制非常完整,生产端和消费端的确认机制,加上持久化队列,能保证消息在进程崩溃后不丢失。
但它不是“实时通信”的通用方案——AMQP 的实时性取决于消费者处理速度,而且它是一个重协议,握手交互多、报文结构复杂。如果团队已经有 RabbitMQ 基础设施,做 OTA 指令下发、订单状态同步这类异步任务非常稳。但如果只做页面聊天,拿 AMQP 去推消息会显得笨重,就像扛着服务器的 UPS 去给手机充电,能充,但不该这么干。
2.9 XMPP:即时通讯领域的“老前辈”
XMPP(Extensible Messaging and Presence Protocol)诞生于 1999 年,基于 XML 流,核心概念是 JID(类似邮箱地址的用户标识)、Presence(在线状态)、Message、IQ(信息查询)。它支持联邦式部署——不同服务商之间的用户也能互相通信,这也是早期 Google Talk 选择它的原因。XMPP 有大量 XEP 扩展协议,消息回执、离线消息、文件传输、群聊都有对应规范。
它的历史包袱也很明显:XML 报文冗长,解析成本高,弱网下效率差;现代移动端消息服务更多采用“自研 TCP 长连接 + Protobuf”或 MQTT。我一般不推荐新项目从零用 XMPP,除非你要做企业即时通讯并且需要联邦通信。在选型评审时,它最大的价值反而是“反面教材”意义——告诉你一个协议如果没有足够克制,会在二十年里膨胀到什么程度。
2.10 QUIC:UDP 上的传输层革新,实时通信的新底座
QUIC(Quick UDP Internet Connections)是近年最值得关注的实时通信底层技术。它把传输层建立在 UDP 之上,却实现了 TCP 才有的可靠传输、流量控制和拥塞控制,最重要的是解决了 HTTP/2 的队头阻塞问题:一条连接里多个流独立传输,某个流的丢包不会阻塞其他流。它还支持 0-RTT 或 1-RTT 握手,连接迁移也做得非常优雅,切换 Wi-Fi 和蜂窝网络时连接不会中断。
HTTP/3 就是基于 QUIC 的实现。为什么它和实时通信有关?WebRTC 已经开始了 WebRTC over QUIC 的探索;Google 系服务大量用 QUIC 承载实时数据;未来 WebSocket 也可能真正搬到 QUIC 上。但目前它的坑是部署复杂,很多中间件和代理并不支持,需要 CDN 或网关层面做兼容。如果你做的是音视频、游戏同步这类对弱网和抖动极其敏感的业务,盯紧 QUIC 的进展比盯任何应用层协议都值。
3. 横向对比:一张速查表看懂核心差异
3.1 协议主速查表
下面这张表是我做方案评审时必摆出来的。你可以直接截图贴在 wiki 上。
| 协议/方案 | 传输层 | 通信方向 | 实时性量级 | 可靠机制 | 消息模型 | 典型场景 | 学习成本 |
|---|---|---|---|---|---|---|---|
| WebSocket | TCP | 全双工 | 毫秒级 | 应用层自行保证,依赖 TCP | 双向消息流 | 网页聊天、实时协作、行情推送 | 低 |
| SSE | HTTP/TCP | 单向(服务器→客户端) | 毫秒级 | 自动重连 + Last-Event-ID | 服务器推送流 | 通知、股票行情、日志流 | 很低 |
| WebRTC | UDP为主 + TCP | 全双工(P2P) | 毫秒级 | DTLS/SRTP 加密,靠 NACK/重传保证 | 音视频数据流 | 视频会议、直播连麦、远程桌面 | 高 |
| Socket.IO | 基于 WebSocket/HTTP | 全双工 | 毫秒~秒级(降级为轮询时变高) | 自动重连、心跳、ACK | 事件广播/房间 | 快速原型、中小型 Web 实时应用 | 低 |
| MQTT | TCP | 全双工(发布/订阅) | 毫秒级 | QoS 0/1/2,遗嘱/保留/会话续传 | 主题发布订阅 | 物联网、车联网、移动推送 | 中 |
| CoAP | UDP | 请求/响应,可观察 | 毫秒级 | CON 确认重传,Blockwise | 资源操作/观察 | 受限设备传感网、智能硬件 | 中 |
| STOMP | 运行于 WebSocket/TCP | 全双工 | 毫秒级 | ACK 确认、事务 | Frame 式消息 | Spring 实时推送、消息队列适配 | 低 |
| AMQP | TCP | 全双工(异步消息) | 取决于消费能力 | 生产/消费确认、持久化队列 | Exchange 路由队列 | 微服务异步、事务消息、任务队列 | 高 |
| XMPP | TCP | 全双工 | 秒级 | 离线消息、消息回执 | 地址寻址 + 在线状态 | 即时通讯、联邦聊天 | 高 |
| QUIC | UDP | 全双工 | 毫秒级 | 自有可靠传输、多路复用 | 流式传输 | HTTP/3、音视频加载、WebRTC over QUIC | 高 |
3.2 延迟、带宽和弱网表现,这些指标怎么选
很多人只看“毫秒级”就觉得够用,但实时通信的体验是由多个指标叠加决定的。延迟衡量的是从一端发出到另一端收到的时间,WebSocket、MQTT、CoAP 在正常网络下都能做到几十毫秒,差距不大。带宽开销则差异显著:MQTT 最小,几个字节就能发一条消息;AMQP 和 XMPP 因为协议结构复杂,每一条消息可能附带几百字节的协议头;WebRTC 是媒体流,带宽占用最大,但也因为它传输的是音视频而非纯文本。
弱网表现里,CoAP 和 QUIC 因为基于 UDP,天然能更快应对丢包和抖动,但需要应用层或协议内的确认机制兜底;MQTT 在蜂窝网和低带宽场景表现优秀。如果只是局域网内部聊天,WebSocket 完全够看;如果是公网海量移动设备,MQTT 的会话续传比 WebSocket 的裸连接更适合;如果是音视频,WebRTC 对弱网的抗性比任何纯 TCP 长连接都强,因为它的拥塞控制和码率自适应是专为此设计的。
3.3 生态成熟度与跨语言支持
生态决定了这个协议能不能快速落地。WebSocket 和 SSE 是标准协议,几乎所有语言都有实现,浏览器原生支持:WebSocket 有 ws、socket.io-client 等库,SSE 直接用 fetch 或 EventSource 也行。MQTT 的客户端覆盖 C、Java、Python、Go、JavaScript,Broker 选 Mosquitto、EMQX、HiveMQ 都相当成熟。WebRTC 虽然复杂,但前端有原生的 RTCPeerConnection,服务端有 mediasoup、Janus、LiveKit,跑起来很快。
XMPP 的现代实现相对少了,但基于它的 Openfire、Ejabberd 仍然活跃。AMQP 生态相当完善,RabbitMQ 社区资源丰富。选型时除了看协议本身,也要看团队的熟悉度:再好的协议,如果团队要花三周去填坑,那就不是“快”,而是“慢”。这也是我常跟团队说的“协议成本不仅仅是性能成本,更是认知成本”。
4. 选型决策路径:从业务场景倒推协议
4.1 五个决定性问题,问完就有答案
在实际选型中,我习惯用五个问题把场景套出来,而不是直接“推荐一个协议”:
- 通信是单向的还是双向的?服务端只推数据,还是客户端也要随时发消息?单向优先考虑 SSE(浏览器端)或 MQTT(设备端);双向优先 WebSocket 或 MQTT。
- 客户端是谁?浏览器、原生 App、还是单片机?浏览器选 WebSocket/SSE/WebRTC 都方便;单片机优先 MQTT/CoAP;原生 App 如果要稳定长连接,考虑自带推送通道或 MQTT。
- 传输的数据是文本还是音视频?文本、指令、消息用 WebSocket/MQTT;音视频用 WebRTC。
- 网络环境如何?弱网、丢包严重、带宽受限?侧重 UDP 系(CoAP、QUIC)或 MQTT。
- 已有基础设施里有没有消息队列?有 RabbitMQ/Kafka,考虑 STOMP/AMQP 打通;没有就别硬造。
这套问法不一定是最严谨的,但在评审会上特别管用——它能把“我觉得这个协议好”这种主观争论,拉到需求维度。
4.2 同场景 PK:WebSocket 和 SSE 到底怎么选
WebSocket 和 SSE 是最容易纠结的两个。两者都走 HTTP 体系,都支持浏览器直接连。有一个很容易忽视的差异:WebSocket 是全双工的,服务端和客户端都能主动发;SSE 是单向的,只有服务端能推。如果你的场景是“后端状态变更推给前端”,SSE 省掉一半的前后端协议代码,还自动带重连;如果你的场景是“聊天、白板协作、多人在线编辑”,必须要双向,那 SSE 只能当作辅助,主通道还是 WebSocket。
另一个很多人不知道的点:HTTP/2 下 SSE 可以多路复用,多个 SSE 流共享一条 HTTP/2 连接;而 WebSocket 在 HTTP/2 下的标准化一直比较尴尬,实际部署中通常还是走独立的 TCP 连接。所以高并发推送场景,SSE 的连接资源占用可能比 WebSocket 更可控。我自己做过一个灰度系统:服务端定时推送任务进度,早期用了 WebSocket,后来改成 SSE,连接数量从几百个降到了几十个,因为多个事件流可以复用连接,代码量也少了一截。
4.3 IoT 场景 PK:MQTT、CoAP 和 WebSocket 的差异化分工
IoT 场景里,三者的关系不是谁取代谁,而是分地段负责。设备上报传感器数据,MQTT 是优选,它基于主题的发布/订阅让多级网关、云平台之间天然解耦;设备是资源受限传感器且服务端要查询配置,CoAP 更省,因为 UDP 无连接开销;设备本身能力强、又要和 Web 后台对接,部分团队直接用 WebSocket 把设备端和云端拉一条双向长连接,写起来直观,但设备数量一上来,WebSocket 长连接的内存和连接维护成本会明显高于 MQTT。
我做过一个充电桩项目:最初让充电桩用 WebSocket 连服务端,桩端偶尔断网重连时,状态同步逻辑写了一堆;后来切到 MQTT,利用遗嘱消息让服务端秒级感知设备掉线,用保留消息让设备上线即拿到最近状态,代码量反而下降了。很多时候不是协议本身性能多好,而是它的生命周期模型正好贴合业务。
4.4 组合拳:真实项目里协议往往不是单打独斗
纯聊天和音视频之外,大多数项目的实时架构都是协议组合。比如我做智能硬件 App 时,设备数据走 MQTT Broker,Broker 通过规则引擎把数据转发给后端业务系统;后端要往浏览器推状态,走 WebSocket/SSE;设备远程视频监控则单独走 WebRTC,用 TURN 服务器中转。这样一个项目里同时跑了 MQTT、WebSocket、SSE、WebRTC,各管一段,互不干扰。
组合使用时要特别注意协议之间的“翻译成本”。MQTT 主题里的设备 ID 如何对应到 WebSocket 连接的用户 ID?WebRTC 的会话描述如何通过信令通道交换?这些胶水代码往往比协议本身更复杂。在设计时就给消息加上统一的消息头和路由字段,能省掉很多以后踩的坑。
5. 踩坑记录与实操经验:你大概率也会遇到的几个问题
5.1 外网能连 WebSocket,内网一接就失败的代理问题
这是我在一个企业后台系统里遇到的真事:本地开发环境 WebSocket 连得好好的,部署到客户内网后,前端一直报 Error during WebSocket handshake。折腾了一天发现客户网络里有一层 HTTP 代理,代理没有配置 Upgrade 支持,把 WebSocket 的握手请求当普通 HTTP 请求处理了。排查方法是让浏览器直接访问 ws:// 地址看握手响应,再看代理日志。解决方式要么在网络策略里放行 WebSocket、要么用带 TLS 的 wss:// 走 443 端口,很多代理对 TLS 加密流量会直接透传。
5.2 移动运营商封锁 MQTT 端口的坑
用 MQTT 做互联网场景时,1883 和 8883 端口在部分移动网络或海外网络里会被封锁或限速,尤其是 1883 这种非标准端口。踩过一次之后,我强烈建议:面向公网的 MQTT 直接上 TLS,用 443 端口,或者在 Broker 前面加一层支持 MQTT over WebSocket 的网关。这样既绕开了端口封锁,又把加密和传输问题一起解决了。代价是加了一层协议转换,但这在稳定性面前非常值得。
5.3 Nginx 反向代理 WebSocket 少写了三行配置
WebSocket 的负载均衡方案里,Nginx 是最常用的,但默认配置会把长连接打回原形。你要在 location 里显式声明:
proxy_http_version 1.1 和 Upgrade/Connection 这三行是缺一不可的。proxy_read_timeout 也要合理设置,否则 Nginx 默认 60 秒就断开空闲连接,很多客户端还来不及发心跳就被服务端踢了,接着就是一轮重连风暴。这类问题表面看像“代码 bug”,实际是网关层配置问题,排错时先检查网关,再查代码。
5.4 断线重连写不好,比断线本身更可怕
很多实时通信系统崩溃不是断线导致的,而是断线后的瞬间重连风暴。每个客户端同时重连,服务端和网关瞬间被打爆。后来我形成了一套固定写法:指数退避 + 抖动。客户端第一次断线后等 1 秒重试,第二次等 2 秒,第三次等 4 秒,并加上随机 0 到 500 毫秒的抖动,上限封顶 30 秒。MQTT 客户端一般自带退避,但 WebSocket 裸写时很容易忽略。另一个注意点是客户端不仅要自动重连,还要在重连后主动做一次“增量同步”,把断线期间漏掉的消息拉回来,否则你会看到连接恢复了但数据一直缺了几条。
5.5 前端安全别忽略:WebSocket 跨站劫持
WebSocket 和普通 HTTP 一样有跨域安全问题,常被叫“跨站 WebSocket 劫持”。因为浏览器发起 WebSocket 握手时会自动带上 Cookie,如果服务端不校验 Origin 头,恶意网页就能以用户的身份建立连接、读取消息。在服务端收到 Upgrade 请求时,一定要校验 Origin 和 Host;如果涉及敏感操作,还要在握手后发一条临时 token 验证消息,确保发起方是“真用户”而非自动脚本。这块容易被当成后端细节忽略,一旦出事影响面很大。
5.6 不在乎序列化的人,迟早要吃性能的亏
协议选好了,数据格式选错一样会拖垮系统。最早我用 JSON 跑 WebSocket 消息,单个消息动辄几 KB,高并发下序列化和带宽开销明显;后来切到 MessagePack 或 Protobuf,消息体积能减小 60% 以上。规则也很简单:偏向可读性和调试就用 JSON,偏向性能和高吞吐就用 Protobuf/MessagePack。如果跨语言对接,Protobuf 需要先维护 .proto 文件的兼容性,这个成本要算进开发量里;如果只是前后端都是 JavaScript,JSON 其实够用,别为了优化而优化。
6. 最后给一份 30 秒速查卡
如果你现在手头有个项目,没时间看前面的长篇,直接按这个表对号入座:
| 你的需求 | 推荐方案 | 不推荐 |
|---|---|---|
| 浏览器页面聊天/双向协作 | WebSocket | SSE(单向不够用) |
| 浏览器页面只收通知/行情 | SSE | WebSocket(过度设计) |
| 物联网设备数据上报/命令下发 | MQTT | WebSocket(资源开销大) |
| 受限 MCU、低功耗传感网络 | CoAP | WebSocket/AMQP(太重) |
| 音视频会议、直播连麦 | WebRTC | WebSocket(传不了音视频) |
| 已有 RabbitMQ 的实时推送 | STOMP over WebSocket | 自研长连接 |
| 移动端大量在线状态同步 | MQTT 或自研长连接 | XMPP(XML 冗长) |
| 需要传输层新特性、高速弱网 | QUIC/HTTP3 | 传统 TCP 长连接 |
个人体会是,实时通信选型没有一劳永逸的“最好协议”,只有“当前需求最合适的组合”。我给新项目做技术方案时,从不先提协议名,而是先逼着业务方回答三个问题:数据是推还是拉?客户端是浏览器还是硬件?弱网下能容忍丢消息还是必须不丢?这三个问题问完,方案基本就浮出水面了。协议只是手段,能稳定扛住业务压力的架构才是目的。