3、消息协议入门:HTTP轮询与长轮询、WebSocket协议基础、AMQP协议概览、MQTT协议简介

聊消息系统,绕不开协议。我见过不少团队,上来就选 RabbitMQ 或 Kafka,结果发现业务场景根本不匹配。说白了,协议选型错了,后面怎么优化都别扭。

这一章,我带大家走一遍四种最常见的消息协议。不搞理论堆砌,重点讲清楚它们各自解决什么问题、适合什么场景。

3.1 HTTP轮询与长轮询

先说说最朴素的方案——HTTP 轮询。客户端每隔几秒发一次请求,问服务器「有消息吗?」。服务器要么返回数据,要么说「没有」。

我早期做的一个电商后台,订单状态更新就是靠轮询。前端每 3 秒调一次接口。听起来很傻对吧?但当时业务量小,开发快,确实够用。

注意: 轮询的弊端很明显。如果间隔太短,服务器压力大;间隔太长,消息延迟高。说白了,这是用带宽换实时性。

后来有了长轮询。客户端发请求后,服务器不急着回复。它把请求「挂」在那里,等有新消息了再响应。如果超时了,客户端再重新发起。

举个例子:

// 客户端长轮询示例(伪代码)
function longPoll() {
  fetch('/poll')
    .then(response => response.json())
    .then(data => {
      // 处理消息
      console.log('收到消息:', data);
      // 立即发起下一次长轮询
      longPoll();
    })
    .catch(err => {
      // 出错或超时,重新连接
      setTimeout(longPoll, 1000);
    });
}
longPoll();

长轮询比普通轮询好一些,但本质上还是 HTTP 请求。每次都要建立连接、发送头部、解析响应。连接数一多,服务器扛不住。

我曾经维护过一个长轮询系统,高峰期 10 万连接。服务器 CPU 全耗在上下文切换上。嗯,那时候我就知道,该换协议了。

3.2 WebSocket协议基础

WebSocket 的出现,算是解决了「服务器主动推」的问题。它建立一次 TCP 连接,之后全双工通信。客户端和服务器随时可以发数据。

握手过程很简单:

// 客户端请求
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

// 服务器响应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

握手成功后,数据帧格式很轻量。头部最小只有 2 字节。对比 HTTP 请求动不动几百字节的头部,差距一目了然。

核心优势: WebSocket 没有 HTTP 请求的「一问一答」限制。服务器可以主动推送,延迟低到毫秒级。

我做过一个实时协作编辑工具,用的就是 WebSocket。用户打字的同时,光标位置、文本变化实时同步。如果用轮询,体验会差很多。

但 WebSocket 也不是万能的。它需要自己处理心跳、重连、消息确认。说白了,它只提供了通道,业务逻辑得自己写。

3.3 AMQP协议概览

AMQP 全称是 Advanced Message Queuing Protocol。它和前面两种协议完全不同。AMQP 是一个线级协议,定义了消息的格式、交换方式、队列模型。

你想想看,HTTP 和 WebSocket 只是传输通道。而 AMQP 连「消息怎么路由」「怎么确认」「怎么持久化」都规定好了。

AMQP 的核心模型包含三个角色:

  • Exchange(交换器):接收生产者发来的消息,根据路由键分发到队列
  • Queue(队列):存储消息,等待消费者消费
  • Binding(绑定):定义交换器和队列之间的路由规则

交换器有四种类型:

类型 路由规则 典型场景
Direct 路由键精确匹配 点对点消息
Topic 路由键模式匹配(支持通配符) 发布订阅
Fanout 广播到所有绑定队列 日志广播
Headers 根据消息头部属性匹配 复杂路由

我习惯用 RabbitMQ 作为 AMQP 的实现。它稳定、功能全。曾经有个金融项目,要求消息不能丢、不能重复消费。AMQP 的确认机制和事务支持,正好满足需求。

避坑指南: 我曾经踩过一个坑——AMQP 的确认模式。如果消费者处理完消息后忘记发送 ack,消息会一直留在队列里,导致内存暴涨。记得一定要在 finally 块里确认或拒绝。

3.4 MQTT协议简介

MQTT 全称是 Message Queuing Telemetry Transport。看名字就知道,它专为物联网和低带宽场景设计。

MQTT 的报文头部最小只有 2 字节。对比 HTTP 动不动几百字节,MQTT 简直是「省流量冠军」。

它的核心概念是:

  • Broker(代理):消息中转服务器
  • Topic(主题):消息的分类标签,支持层级结构(如 sensor/temperature/room1)
  • QoS(服务质量):消息送达保证级别

QoS 有三个级别:

级别 含义 适用场景
QoS 0 最多一次(可能丢失) 传感器数据,丢了无所谓
QoS 1 至少一次(可能重复) 控制指令,允许重复
QoS 2 恰好一次(不丢不重) 计费、关键事件

我做过一个智能家居项目,设备端用 MQTT 上报温度、湿度。设备是电池供电,网络不稳定。MQTT 的断线重连和遗嘱消息(Last Will)机制,帮了大忙。

遗嘱消息是什么?设备上线时可以注册一个遗嘱。如果设备异常断开,Broker 会自动发布这条遗嘱消息,通知其他设备「某某掉线了」。这个设计很巧妙。

总结一下: MQTT 适合资源受限、网络不稳定的场景。它轻量、省电、支持离线消息。但如果你需要复杂路由和事务支持,还是得看 AMQP。

下面这张图,展示了四种协议在实时性和资源消耗上的对比:

消息协议对比:实时性 vs 资源消耗 高 低 资源消耗 低 高 实时性 轮询 低实时 高消耗 长轮询 中实时 中消耗 WebSocket 高实时 低消耗 MQTT 高实时 极低消耗 AMQP 中实时 中高消耗 HTTP轮询 HTTP长轮询 WebSocket MQTT AMQP

选协议没有银弹。我个人的经验是:先搞清楚你的场景要什么。要实时推送?WebSocket 或 MQTT。要可靠路由?AMQP。设备资源受限?MQTT 是首选。

嗯,这一章就到这里。协议是消息系统的基石,理解透了,后面学消息中间件会轻松很多。

可可精品资料库