跳到主要内容
英文版本为准

本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。

路径

一条 MQTT 消息在 RustStream 服务中的路径:事件循环、连接任务、投递、处理器、应答和确认。

一条需要应答的消息的路径:沿左列从服务器下行到处理器,再沿右列上行,回到网络上EventLoop::poll解码 PUBLISH连接任务找到所属的订阅MqttMessage共享载荷,不复制分发一个循环,或工作分区解码从载荷读取订阅者的处理器#[subscriber] 下的 async fnMQTT 服务器EventLoop 写出PUBLISH,然后 PUBACKAsyncClient 的请求通道确认PUBACK 或 PUBRECMqttPublisher交出缓冲区应答编码进缓冲区
以文字阅读本图
  1. MQTT 服务器 → EventLoop::poll 解码 PUBLISH
  2. EventLoop::poll 解码 PUBLISH → 连接任务 找到所属的订阅
  3. 连接任务 找到所属的订阅 → MqttMessage 共享载荷,不复制
  4. MqttMessage 共享载荷,不复制 → 分发 一个循环,或工作分区
  5. 分发 一个循环,或工作分区 → 解码 从载荷读取
  6. 解码 从载荷读取 → 订阅者的处理器 #[subscriber] 下的 async fn
  7. 订阅者的处理器 #[subscriber] 下的 async fn → 应答 编码进缓冲区
  8. 应答 编码进缓冲区 → MqttPublisher 交出缓冲区
  9. MqttPublisher 交出缓冲区 → AsyncClient 的 请求通道
  10. MqttPublisher 交出缓冲区 → 确认 PUBACK 或 PUBREC: 然后
  11. 确认 PUBACK 或 PUBREC → AsyncClient 的 请求通道
  12. AsyncClient 的 请求通道 → EventLoop 写出 PUBLISH,然后 PUBACK
  13. EventLoop 写出 PUBLISH,然后 PUBACK → MQTT 服务器

连接任务轮询 rumqttc 的事件循环,事件循环从套接字读取 PUBLISH 并解码。任务读取主题,找到该报文所属的订阅(见多路分解一页的图),并通过每个订阅自己的通道把投递发给它。不是 UTF-8 的主题会被丢弃,并记录一条警告。

MqttMessage 与报文共享载荷,因此消息体从不复制。它持有主题的一份副本,以及由报文属性构建的消息头。QoS 1 或 QoS 2 投递还保留报文的标识,确认时要用到它。处理器读取的上下文同样持有主题。

订阅的通道本身没有上限。对于 QoS 1 和 QoS 2,上限由服务器决定:它发出的未确认投递不超过 Receive Maximum。不匹配任何已打开订阅的报文会等待之后打开的订阅,最多 1024 个。

处理器的应答编码进一个缓冲区,发布者把这个缓冲区原样交给 rumqttc,不做复制。消息头成为报文的属性。请求进入客户端的请求通道后,发布就返回,而不是在服务器确认之后。

投递在应答之后结算。它的确认经过同一个请求通道,因此在应答之后发出,并且早于之后关闭时的 DISCONNECT。每种结果发送什么,见结算。

基准测试统计的正是这条路径:一次投递和一次应答的指令数和内存分配,包括客户端在服务线程上所做的工作。