1. 系统概述
coordinate-connector 是 Coordinate 消息系统中的 MQTT 客户端 SDK,基于 rumqttc 进行二次开发,采用 Rust 异步运行时(tokio)实现。它为应用程序提供简洁的 API 用于连接 MQTT Broker、发布消息和订阅主题。作为 coordinate-broadcast 的配套客户端库,coordinate-connector 主要用于 coordinate-server 与广播组件之间的通信,同时也支持外部应用接入。
从功能定位角度来看,coordinate-connector 主要承担三类职责:第一是作为 MQTT 客户端,封装底层协议细节,提供简洁的异步 API;第二是作为状态管理器,维护连接状态、QoS 流程控制和 packet id 分配;第三是作为传输层抽象,支持 TCP、TLS、WebSocket 等多种传输方式。系统设计遵循高性能、低延迟的原则,使用预分配数据结构和事件驱动模式,整体能够支撑高并发的消息处理。
2. 系统架构
2.1 整体架构图
flowchart TB
subgraph App["应用程序"]
direction LR
ClientAPI["Client API"]
end
subgraph coordinate-connector["coordinate-connector"]
subgraph client["Client - 高层抽象"]
direction TB
Client["Client"]
MqttOptions["MqttOptions"]
end
subgraph eventloop["EventLoop - 事件循环"]
direction TB
EventLoop["EventLoop"]
State["MqttState"]
end
subgraph protocol["Protocol - 协议层"]
direction LR
V0["v5 Extended"]
V5["v5 Lite"]
end
subgraph protocol["Protocol - 协议层"]
direction LR
V0["v5 Extended"]
V5["v5 Lite"]
end
subgraph transport["Transport - 传输层"]
direction LR
TCP["TCP"]
TLS["TLS"]
WS["WebSocket"]
WSS["WSS"]
end
end
subgraph coordinate-broadcast["coordinate-broadcast"]
BServer["Broadcast Server"]
end
App -->|publish/subscribe| Client
Client --> EventLoop
EventLoop --> State
EventLoop --> Protocol
Protocol -->|MQTT| Transport
Transport -->|TCP/TLS/WS| BServer
2.2 模块职责划分
coordinate-connector 采用模块化的架构设计,每个模块承担独立的职责,通过清晰定义的接口进行模块间交互。这种设计使得各模块可以独立演进,同时便于测试和维护。系统主要包含以下五个核心模块:
client 模块负责提供高层的异步客户端抽象,是应用程序使用的主要入口点。它封装了请求通道(Channel),提供了 publish、subscribe、ack、disconnect 等简洁的异步方法。client 模块的设计遵循简单易用原则,隐藏了底层的事件循环细节,应用程序只需关注业务逻辑。
eventloop 模块是系统的核心事件循环引擎,负责驱动整个客户端的运行。它管理网络连接、处理入站和出站数据包、维护 Keep-alive 机制。EventLoop 使用 tokio 的 select 模式实现异步事件处理,能够高效地处理并发请求和网络 I/O。
state 模块负责维护 MQTT 连接状态,包括飞行中消息(inflight)管理、packet id 分配、QoS 流程控制、会话恢复等。state 模块是 MQTT 协议实现的核心支持,确保消息传递的可靠性。
protocol 模块实现了 MQTT 协议的解析与序列化功能。该模块根据 Cargo feature 决定使用不同协议版本:
- v5 Extended(包含 v0 feature):用于 coordinate-server 连接 broadcast,在内网使用,是 MQTT v5 完整协议并扩展 AddSubscribe/RemoveSubscribe 消息类型,支持动态订阅管理
- v5 Lite(默认):用于外部客户端连接 broadcast 接收消息,是 MQTT v5 的裁剪集合,仅包含连接管理消息(Connect/ConnAck/Ping/Disconnect)
v5 Extended 扩展功能:
- AddSubscribe:服务端代客户端订阅主题
- RemoveSubscribe:服务端代客户端取消订阅
transport 模块负责底层网络传输,支持 TCP、TCP+TLS、WebSocket、WebSocket+TLS 四种传输方式。传输层抽象使得客户端可以灵活适应不同的网络环境。
3. 核心组件设计
3.1 MqttOptions 配置
MqttOptions 是客户端连接的核心配置类,提供了丰富的配置选项:
pub struct MqttOptions {
broker_addr: String, // Broker 地址
port: u16, // 端口
transport: Transport, // 传输层类型
keep_alive: Duration, // 保活间隔
clean_start: bool, // 清理会话标志
client_id: String, // 客户端标识
credentials: Option<Login>, // 认证凭据
last_will: Option<LastWill>, // 遗嘱消息
// ... 更多选项
}
配置示例:
let mut options = MqttOptions::new("client-id", "broker-host", 21884);
options
.set_keep_alive(Duration::from_secs(30))
.set_clean_start(true)
.set_credentials("user", "password")
.set_last_will(LastWill::new("will-topic", "msg", QoS::AtLeastOnce, false, None));
3.2 Client 客户端
Client 是面向应用程序的高层 API,提供了简洁的异步接口:
pub struct Client {
request_tx: Sender<Request>,
}
// 创建客户端和事件循环
let (client, mut eventloop) = Client::new(options, cap);
// 消息循环
loop {
match eventloop.poll().await {
Ok(Event::Incoming(Incoming::Publish(publish))) => {
// 处理接收到的消息
}
Ok(Event::Outgoing(_)) => { /* 发送确认 */ }
Err(e) => break,
}
}
3.3 EventLoop 事件循环
EventLoop 是系统的核心引擎,管理连接和事件处理:
pub struct EventLoop {
pub options: MqttOptions,
pub state: MqttState,
requests_rx: Receiver<Request>,
pending: VecDeque<Request>,
network: Option<Network>,
keepalive_timeout: Option<Pin<Box<Sleep>>>,
}
impl EventLoop {
pub async fn poll(&mut self) -> Result<Event, ConnectionError> {
// 连接建立、数据收发、Keep-alive 处理
}
}
3.4 MqttState 状态管理
MqttState 维护 MQTT 连接状态:
pub struct MqttState {
pub await_pingresp: bool,
pub last_pkid: u16,
pub inflight: u16,
pub outgoing_pub: Vec<Option<Publish>>,
pub incoming_pub: FixedBitSet,
pub events: VecDeque<Event>,
pub manual_acks: bool,
pub broker_topic_alias_max: u16,
pub max_outgoing_inflight: u16,
}
4. 关键技术实现
4.1 客户端创建与连接
// 创建客户端和事件循环
let (client, mut eventloop) = Client::new(options, 10000);
// 使用方式
loop {
match eventloop.poll().await {
Ok(Event::Incoming(Incoming::Publish(publish))) => {
println!("Received: {:?}", publish.topic);
}
Ok(Event::Outgoing(_)) => {}
Err(e) => break,
}
}
4.2 消息发布
// 异步发布
client.publish("topic/test", QoS::AtLeastOnce, false, "payload").await?;
// 非阻塞发布
client.try_publish("topic", QoS::AtMostOnce, true, "data")?;
4.3 消息订阅
// 订阅单个主题
client.subscribe("home/+/temperature", QoS::AtLeastOnce).await?;
// 批量订阅
client.subscribe_many(vec![
Filter::new("topic1", QoS::AtMostOnce),
Filter::new("topic2", QoS::AtLeastOnce),
]).await?;
// 非阻塞订阅
client.try_subscribe("topic", QoS::AtMostOnce)?;
4.4 传输层
系统支持四种传输层类型:
pub enum Transport {
Tcp, // 普通 TCP
Tls(TlsConfiguration), // TLS 加密
Ws, // WebSocket
Wss(TlsConfiguration), // WebSocket + TLS
}
4.5 TLS 配置
// 使用默认配置
Transport::tls_with_default_config()
// 自定义配置
Transport::tls(
ca: Vec<u8>,
client_auth: Option<(Vec<u8>, Vec<u8>)>,
alpn: Option<Vec<Vec<u8>>>,
)
5. 与 coordinate-broadcast 的交互
5.1 连接配置
coordinate-server 通过 coordinate-connector 连接 broadcast 服务:
[broadcast]
host = "192.168.31.195"
port = 21884
username = ""
password = ""
endpoint = "ws://192.168.31.195:8000"
5.2 连接流程
async fn connect(options: &mut MqttOptions) -> Result<(Network, ConnAck), ConnectionError> {
// 1. 建立网络连接
let (network, connack) = timeout(
Duration::from_secs(self.options.connection_timeout()),
connect(&mut self.options),
).await??;
// 2. MQTT 握手
network.write(Packet::Connect(...)).await?;
network.flush().await?;
match network.read().await? {
Incoming::ConnAck(connack) if connack.code == Success => Ok(connack),
_ => Err(ConnectionError::ConnectionRefused),
}
}
5.3 消息流
coordinate-server → Client.publish() → EventLoop → MqttState → Network.write() → coordinate-broadcast
coordinate-broadcast → Network.read() → EventLoop.poll() → Event::Incoming → 应用程序
6. 配置设计
6.1 Cargo.toml Features
[features]
default = []
use-rustls = ["use-rustls-no-provider", "tokio-rustls/default"]
use-rustls-no-provider = ["dep:tokio-rustls", "dep:rustls-webpki"]
use-native-tls = ["dep:tokio-native-tls", "dep:native-tls"]
websocket = ["dep:async-tungstenite", "dep:ws_stream_tungstenite"]
v0 = []
6.2 MqttOptions 配置项
| 配置项 | 说明 |
|---|---|
| broker_addr | Broker 地址 |
| port | 端口 |
| transport | 传输层类型 |
| keep_alive | 保活间隔 |
| clean_start | 清理会话 |
| client_id | 客户端标识 |
| credentials | 认证凭据 |
| last_will | 遗嘱消息 |
| manual_acks | 手动确认模式 |
6.3 NetworkOptions 配置项
pub struct NetworkOptions {
tcp_send_buffer_size: Option<u32>,
tcp_recv_buffer_size: Option<u32>,
tcp_nodelay: bool,
conn_timeout: u64,
}
7. 设计模式总结
7.1 架构模式
系统采用以下架构模式实现高性能和高可用性:
生产者-消费者模式:Client 作为生产者,将请求放入通道;EventLoop 作为消费者,从通道取出请求进行处理。通道提供了高效的异步通信机制。
事件驱动模式:EventLoop 基于 tokio 的 select 模式实现异步事件处理,能够高效地处理并发请求和网络 I/O。
状态机模式:MqttState 作为状态机,管理 MQTT 连接的各种状态,包括连接中、已连接、断开等。
7.2 扩展性设计
系统提供了良好的扩展性支持:通过 Cargo features 可以选择不同的协议版本和传输层;通过 TlsConfiguration 可以自定义 TLS 行为;通过 MqttOptions 可以灵活配置连接参数。
8. 技术规格
| 指标 | 规格 |
|---|---|
| 支持协议 | v5 Extended(含 v0 feature), v5 Lite(默认) |
| 传输层 | TCP, TLS, WebSocket, WSS |
| QoS 级别 | 0, 1 |
| 依赖 Runtime | tokio |
| 异步模型 | futures-channel |
9. 使用示例
9.1 基本使用
use coordinate_connector::{Client, Event, MqttOptions, QoS};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut options = MqttOptions::new("test-client", "localhost", 21884);
options.set_keep_alive(Duration::from_secs(30));
options.set_clean_start(true);
let (client, mut eventloop) = Client::new(options, 10000);
// 订阅主题
client.subscribe("home/temperature", QoS::AtLeastOnce).await?;
// 消息循环
loop {
tokio::select! {
event = eventloop.poll() => {
match event? {
Event::Incoming(coordinate_connector::Incoming::Publish(publish))) => {
println!("Received: {}", publish.topic);
}
_ => {}
}
}
}
}
}
9.2 发布消息
// 发布消息
client.publish("home/temperature", QoS::AtLeastOnce, false, "25.5").await?;
// 批量订阅
client.subscribe_many(vec![
coordinate_connector::Filter::new("home/temperature", QoS::AtLeastOnce),
coordinate_connector::Filter::new("home/humidity", QoS::AtLeastOnce),
]).await?;