会话层设计

会话层处理 MQTT 协议发布订阅(Publish/Subscribe)业务交互流程:

  1. 缓存 MQTT 客户端的全部订阅(Subscription),并终结订阅 QoS
  2. 处理 Qos0/1/2 消息接收与下发,消息超时重传与离线消息保存
  3. 飞行窗口(Inflight Window),下发消息吞吐控制与顺序保证
  4. 保存服务器发送到客户端的,已发送未确认的 Qos1/2 消息
  5. 缓存客户端发送到服务端,未接收到 PUBREL 的 QoS2 消息
  6. 客户端离线时,保存持久会话的离线 Qos1/2 消息

消息队列与飞行窗口

会话层通过一个内存消息队列和飞行窗口处理下发消息:

image

飞行窗口(Inflight Window)保存当前正在发送未确认的 Qos1/2 消息。窗口值越大,吞吐越高;窗口值越小,消息顺序越严格。

当客户端离线或者飞行窗口(Inflight Window)满时,消息缓存到队列。如果消息队列满,先丢弃 Qos0 消息或最早进入队列的消息。

报文 Id 与消息 Id

MQTT 协议定义了一个 16bits 的报文 ID(PacketId),用于客户端到服务器的报文收发与确认。MQTT 发布报文(PUBLISH)进入消息服务器后,转换为一个消息对象并分配 128bits 消息 ID(MessageId)。

全局唯一时间序列消息 ID 结构:

image

  1. 64bits 时间戳: erlang:system_time if Erlang >= R18, otherwise os:timestamp
  2. Erlang 节点 ID: 编码为 2 字节
  3. Erlang 进程 PID: 编码为 4 字节
  4. 进程内部序列号: 2 字节的进程内部序列号

端到端消息发布订阅(Pub/Sub)过程中,发布报文 ID 与报文 QoS 终结在会话层,由唯一 ID 标识的 MQTT 消息对象在节点间路由:

image