十七、Rust集成MQTT Client

1、信息整理

目前了解到的Rust MQTT项目有:

  • bytebeamio/rumqtt

  • ntex-rs/ntex-mqtt、crates/ntex-mqtt

    • 258 star、504 commits、Contributors 15
    • ntex、MQTT Client/Server、v5 and v3.1.1 protocols
  • eclipse/paho.mqtt.rust

    • 463 star、368 commits、
    • 异步、SSL/TLS、cargo add paho-mqtt = "0.12"、
    • 但看自述文档所述,用于 musl linux 环境,有代码侵入。
    rust 复制代码
    fn is_musl() -> bool {
        std::env::var("CARGO_CFG_TARGET_ENV").unwrap() == "musl"
    }
  • rmqtt/rmqtt:355 star,871 commits

    • 基于 ( tokio、ntex、ntex-mqtt )
    • 一个纯服务端,遍观项目,貌似不能做 client 使用。自身的测试,使用 paho.mqtt.testing 项目完成。
    • 分布式集群(raft),TLS,WebSocket,WebSocket-TLS,x86/Arm
    • 单个服务节点上处理百万级别的并发客户端。集群提供相同的连接量、吞吐量,应该只是解决高可用问题。

2、开始集成

本次集成作为 Client 使用,选择了最前面的 bytebeamio/rumqtt 。

  • boot/mqtt.rs
rust 复制代码
use std::sync::Arc;
use std::time::Duration;

use once_cell::sync::OnceCell;
use rumqttc::{AsyncClient, MqttOptions};
use serde::{Deserialize, Serialize};

pub static MQTT_CLIENT: OnceCell<Arc<AsyncClient>> = OnceCell::new();

#[derive(Debug, Default, Validate, Serialize, Deserialize)]
pub struct MqttMessage {
    pub addr: Option<String>,
    #[validate(range(min = 0, max = 1))]
    pub action: u8,
}

pub async fn start() {
    let mut mqtt_options = MqttOptions::new("rumqtt-async", "192.168.1.110", 1883);
    mqtt_options.set_keep_alive(Duration::from_secs(5));
    let (client, mut event_loop) = AsyncClient::new(mqtt_options, 100);
    MQTT_CLIENT.get_or_init(|| { Arc::new(client) });

    tokio::spawn(async move {
        loop { while let Ok(notification) = event_loop.poll().await {}; }
    });

    log::info!("this point run ...");
}
  • boot/mod.rs
rust 复制代码
pub mod mqtt;

pub async fn start() {
    // xxx others initialization
    mqtt::start().await;
}
  • modules/mod.rs
rust 复制代码
pub mod switch;

pub mod handler {
    use actix_web::dev::HttpServiceFactory;
    use actix_web::web;

    use crate::module::{switch};

    pub fn api_routes() -> impl HttpServiceFactory {
        web::scope("")
            .service(switch::api::index)
    }
}
  • modules/switch/api.rs
rust 复制代码
use rumqttc::QoS::AtLeastOnce;
use validator::Validate;

use crate::boot::mqtt::{MQTT_CLIENT, MqttMessage};

#[post("/switch/{id}")]
pub async fn index(Path(id): Path<String>, mut msg: Json<MqttMessage>) -> impl Responder {
    let ok = vec!["Hello World!", "Hello World!"];

    if let Err(e) = msg.validate() { return HttpResponse::BadRequest().json(e); }
    msg.addr = Some(id);
    let json = serde_json::to_string(&msg).unwrap();
    MQTT_CLIENT.get().unwrap().publish("/hello", AtLeastOnce, false, json).await.unwrap();

    HttpResponse::Ok().json(ok)
}
rust 复制代码
use actix_web::{App, HttpServer, middleware};
use booking::{boot, module};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    boot::start().await;
    HttpServer::new(move || App::new()
        // TODO other initialization
        .service(module::handler::api_routes())
        // other routes
    ).bind("0.0.0.0:8080")?.run().await
}

代码贴完,剩下真是没啥可说的,拜了个 bye ~

相关推荐
初学AI的小高18 分钟前
Agent 工具太多怎么办:BM25 检索、依赖补全与按需加载实战
后端·agent
用户66026761187920 分钟前
AI 代码上线前的第 24 道门禁:上线失败时,怎样在 10 分钟内退回?
后端·架构
总要学点什么21 分钟前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
NishikiAsumi072123 分钟前
一次170万行的导出:sql优化远没有加索引这么简单
后端
xiaoye-duck43 分钟前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
xjz18422 小时前
Rust 注释:从 // 到 rustdoc
后端
Funlang2 小时前
龙芯上的 Fun:从跑起来到机器码
开发语言·龙芯
总要学点什么2 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
旖旎夜光2 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习
ShineWinsu3 小时前
对于Qt:QTabWidget常见属性的解析
开发语言·数据库·c++·qt·浏览器·qtabwidget·标签页