会话层设计
会话层处理 MQTT 协议发布订阅(Publish/Subscribe)业务交互流程:
- 缓存 MQTT 客户端的全部订阅(Subscription),并终结订阅 QoS
- 处理 Qos0/1/2 消息接收与下发,消息超时重传与离线消息保存
- 飞行窗口(Inflight Window),下发消息吞吐控制与顺序保证
- 保存服务器发送到客户端的,已发送未确认的 Qos1/2 消息
- 缓存客户端发送到服务端,未接收到 PUBREL 的 QoS2 消息
- 客户端离线时,保存持久会话的离线 Qos1/2 消息
消息队列与飞行窗口
会话层通过一个内存消息队列和飞行窗口处理下发消息:
飞行窗口(Inflight Window)保存当前正在发送未确认的 Qos1/2 消息。窗口值越大,吞吐越高;窗口值越小,消息顺序越严格。
当客户端离线或者飞行窗口(Inflight Window)满时,消息缓存到队列。如果消息队列满,先丢弃 Qos0 消息或最早进入队列的消息。
报文 Id 与消息 Id
MQTT 协议定义了一个 16bits 的报文 ID(PacketId),用于客户端到服务器的报文收发与确认。MQTT 发布报文(PUBLISH)进入消息服务器后,转换为一个消息对象并分配 128bits 消息 ID(MessageId)。
全局唯一时间序列消息 ID 结构:
- 64bits 时间戳: erlang:system_time if Erlang >= R18, otherwise os:timestamp
- Erlang 节点 ID: 编码为 2 字节
- Erlang 进程 PID: 编码为 4 字节
- 进程内部序列号: 2 字节的进程内部序列号
端到端消息发布订阅(Pub/Sub)过程中,发布报文 ID 与报文 QoS 终结在会话层,由唯一 ID 标识的 MQTT 消息对象在节点间路由: