英文版本为准
本页译自英文,由模型翻译。若与英文原文存在差异,以英文原文为准。
路径
一条 MQTT 消息在 RustStream 服务中的路径:事件循环、连接任务、投递、处理器、应答和确认。
以文字阅读本图
- MQTT 服务器 → EventLoop::poll 解码 PUBLISH
- EventLoop::poll 解码 PUBLISH → 连接任务 找到所属的订阅
- 连接任务 找到所属的订阅 → MqttMessage 共享载荷,不复制
- MqttMessage 共享载荷,不复制 → 分发 一个循环,或工作分区
- 分发 一个循环,或工作分区 → 解码 从载荷读取
- 解码 从载荷读取 → 订阅者的处理器 #[subscriber] 下的 async fn
- 订阅者的处理器 #[subscriber] 下的 async fn → 应答 编码进缓冲区
- 应答 编码进缓冲区 → MqttPublisher 交出缓冲区
- MqttPublisher 交出缓冲区 → AsyncClient 的 请求通道
- MqttPublisher 交出缓冲区 → 确认 PUBACK 或 PUBREC: 然后
- 确认 PUBACK 或 PUBREC → AsyncClient 的 请求通道
- AsyncClient 的 请求通道 → EventLoop 写出 PUBLISH,然后 PUBACK
- EventLoop 写出 PUBLISH,然后 PUBACK → MQTT 服务器
连接任务轮询 rumqttc 的事件循环,事件循环从套接字读取 PUBLISH 并解码。任务读取主题,找到该报文所属的订阅(见多路分解一页的图),并通过每个订阅自己的通道把投递发给它。不是 UTF-8 的主题会被丢弃,并记录一条警告。
MqttMessage 与报文共享载荷,因此消息体从不复制。它持有主题的一份副本,以及由报文属性构建的消息头。QoS 1 或 QoS 2 投递还保留报文的标识,确认时要用到它。处理器读取的上下文同样持有主题。
订阅的通道本身没有上限。对于 QoS 1 和 QoS 2,上限由服务器决定:它发出的未确认投递不超过 Receive Maximum。不匹配任何已打开订阅的报文会等待之后打开的订阅,最多 1024 个。
处理器的应答编码进一个缓冲区,发布者把这个缓冲区原样交给 rumqttc,不做复制。消息头成为报文的属性。请求进入客户端的请求通道后,发布就返回,而不是在服务器确认之后。
投递在应答之后结算。它的确认经过同一个请求通道,因此在应答之后发出,并且早于之后关闭时的 DISCONNECT。每种结果发送什么,见结算。
基准测试统计的正是这条路径:一次投递和一次应答的指令数和内存分配,包括客户端在服务线程上所做的工作。