ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

本地FastDDS+远端MQTT转发(多主机数据隔离)架构设计与落地

本地FastDDS+远端MQTT转发(多主机数据隔离)架构设计与落地

文章目录

  • 本地FastDDS+远端MQTT转发(多主机数据隔离)架构设计与落地
    • 一、架构核心设计(贴合你的多主机/Qt+C++场景)
      • 1. 整体架构图(文字版)
      • 2. 核心模块职责
    • 二、数据隔离的双层实现(核心需求落地)
      • 1. 本地层:FastDDS Domain ID 物理隔离
      • 2. 远端层:MQTT主题+ACL 逻辑隔离
        • (1)MQTT主题命名规则(统一格式,强制隔离)
        • (2)MQTT Broker ACL权限(强化隔离)
    • 三、架构优缺点
      • 1. 核心优势
      • 2. 潜在劣势与解决方案
    • 四、Qt+C++落地实现要点(核心代码框架)
      • 1. 中转站核心代码(FastDDS接收+MQTT转发)
      • 2. 本地EXE代码(仅需FastDDS,无需关心MQTT)
      • 3. 配置文件(config.ini,跨主机仅需修改此文件)
    • 五、最终建议
      • 1. 架构选型结论
      • 2. 落地优先级
      • 3. 替代方案对比(仅作参考)

本地FastDDS+远端MQTT转发(多主机数据隔离)架构设计与落地

一、架构核心设计(贴合你的多主机/Qt+C++场景)

该架构的核心是**“单主机FastDDS域隔离 + 中转站统一转发 + MQTT主题/ACL远端隔离”**,每台主机部署一个“FastDDS-MQTT中转站”,作为本地FastDDS和远端MQTT的唯一桥梁,既保留FastDDS本地自动配置的优势,又通过MQTT实现跨主机/远端通信,同时保障多主机数据隔离。

1. 整体架构图(文字版)

┌────────────────────────────────────────────── 主机A ──────────────────────────────────────────────┐ │ ┌─────────┐ ┌─────────┐ ┌──────────────────────────────────────────────┐ │ │ │本地EXE 1│ │本地EXE 2│ │ FastDDS-MQTT 中转站 │ │ │ │(FastDDS)│◄──►│(FastDDS)│◄──►│ [FastDDS模块] [MQTT模块] [隔离管控] │◄─────┐ │ │ └─────────┘ └─────────┘ └──────────────────────────────────────────────┘ │ │ │ ▲ │ │ │ │(本地 FastDDS,Domain ID = 100) │ │ └────────────────────────────────────┴────────────────────────────────────────────────┘ │ │ ┌────────────────────────────────────────────── 主机B ──────────────────────────────────────────────┐ │ ┌─────────┐ ┌─────────┐ ┌──────────────────────────────────────────────┐ │ │ │本地EXE 1│ │本地EXE 2│ │ FastDDS-MQTT 中转站 │ │ │ │(FastDDS)│◄──►│(FastDDS)│◄──►│ [FastDDS模块] [MQTT模块] [隔离管控] │◄─────┐ │ │ └─────────┘ └─────────┘ └──────────────────────────────────────────────┘ │ │ │ ▲ │ │ │ │(本地 FastDDS,Domain ID = 101) │ │ └────────────────────────────────────┴────────────────────────────────────────────────┘ │ │ ▼ ▼ ┌───────────────────────────────────────────────────────────────────────────────────────────────────┐ │ 远端 MQTT Broker(EMQ X / 阿里云 IoT) │ │ (主题隔离 + ACL 权限,实现多主机数据隔离) │ └───────────────────────────────────────────────────────────────────────────────────────────────────┘

2. 核心模块职责

模块核心职责
本地EXE(FastDDS)仅接入本机专属FastDDS域,发布/订阅数据(无需关心MQTT),享受FastDDS自动发现/配置的优势;
主机内FastDDS域每台主机分配唯一Domain ID(如主机A=100,主机B=101),本地FastDDS仅发现同域节点,实现本地数据物理隔离;
FastDDS-MQTT中转站1. 本机FastDDS域的“超级节点”:订阅本地所有FastDDS Topic,接收所有EXE数据;
2. 数据转换:将FastDDS的CDR格式转为MQTT可传输的ProtoBuf/JSON;
3. MQTT转发:按“主机标识+Topic”规则发布到远端Broker;
4. 反向转发:接收远端MQTT数据,转换为FastDDS格式,发布到本机域;
5. 隔离管控:严格按权限订阅/发布MQTT主题,禁止跨主机越权;
远端MQTT Broker1. 主题隔离:按“主机标识”划分MQTT主题空间;
2. ACL权限:限制每个中转站仅能访问自身主机的主题;

二、数据隔离的双层实现(核心需求落地)

多主机数据隔离需从“本地物理隔离”和“远端逻辑隔离”两层入手,缺一不可:

1. 本地层:FastDDS Domain ID 物理隔离

  • 核心逻辑:FastDDS的Domain ID是节点分组的核心标识,不同Domain ID的节点无法互相发现、通信,实现“本机数据不跨域”;
  • 落地配置:
    • 为每台主机分配唯一的Domain ID(范围0-232,避免冲突),写入中转站的配置文件(如domain_id=100);
    • 本地所有EXE和中转站均使用该Domain ID创建FastDDS参与者,跨主机的FastDDS数据完全隔离,即使网络互通也无法访问;
    • 中转站是本机域内唯一能与MQTT交互的节点,本地EXE无MQTT权限,杜绝EXE直接访问远端数据。

2. 远端层:MQTT主题+ACL 逻辑隔离

(1)MQTT主题命名规则(统一格式,强制隔离)

定义全局唯一的主题格式,将“主机标识”作为主题前缀,确保不同主机的数据不会混流:

/host/{主机唯一标识}/{数据类型}/{FastDDS Topic名}
  • 示例:
    • 主机A(标识device001)的北斗数据:/host/device001/sensor/BeidouData;
    • 主机B(标识device002)的USBL数据:/host/device002/sensor/USBLData;
  • 中转站自动拼接规则:读取本机配置的host_id,将本地FastDDS Topic转换为上述MQTT主题,无需手动修改代码。
(2)MQTT Broker ACL权限(强化隔离)

在MQTT Broker(推荐EMQ X)中配置ACL规则,限制每个中转站的MQTT客户端仅能访问自身主机的主题:

# EMQ X ACL配置示例 allow device001 publish /host/device001/# allow device001 subscribe /host/device001/# allow device002 publish /host/device002/# allow device002 subscribe /host/device002/# deny all publish # deny all subscribe #
  • 效果:主机A的中转站只能发布/订阅/host/device001/下的主题,无法访问主机B的主题,即使知道主题名也会被Broker拒绝。

三、架构优缺点

1. 核心优势

优势维度具体价值
本地通信体验完全复用FastDDS的自动发现/配置/序列化,本地EXE仅需订阅Topic即可通信,无需手动配置地址/序列化;
数据隔离安全性双层隔离(Domain ID物理隔离+MQTT主题/ACL逻辑隔离),多主机数据完全隔离,避免越权访问;
远端通信适配性MQTT穿透性强(跨网段/公网/防火墙),部署成本远低于FastDDS的跨网段DS服务器;
Qt+C++适配性FastDDS和Qt MQTT模块(Qt5.10+原生支持)均可集成到Qt项目,跨平台(Win/Linux/macOS)编译;
灵活性本地保留FastDDS的实时性(5-10ms),远端用MQTT降低部署复杂度,兼顾实时性和易用性;

2. 潜在劣势与解决方案

劣势解决方案
中转站单点风险1. 中转站进程加入心跳检测(本地EXE监控,异常则自动重启);
2. 关键主机可部署双中转站,MQTT Broker做主备切换;
数据转换成本封装通用转换模块:FastDDS IDL生成的类 ↔ ProtoBuf/JSON,一次性封装后所有主机复用;
MQTT延迟较高(100-200ms)1. MQTT Broker就近部署(如与主机同区域);
2. 配置MQTT QoS=0(实时性优先);
3. 高频数据压缩后传输;
配置项较多统一配置文件管理:将Domain ID、host_id、MQTT Broker地址等写入config.ini,所有模块读取配置,无需修改代码;

四、Qt+C++落地实现要点(核心代码框架)

1. 中转站核心代码(FastDDS接收+MQTT转发)

#include<QCoreApplication>#include<QSettings>#include<QMqttClient>#include"fastdds/dds/domain/DomainParticipantFactory.hpp"#include"UnifiedDataPubSubTypes.h"// FastDDS IDL生成的类// 全局配置(从config.ini读取)QSettingssettings("config.ini",QSettings::IniFormat);intdomainId=settings.value("fastdds/domain_id").toInt();QString hostId=settings.value("mqtt/host_id").toString();QString mqttBroker=settings.value("mqtt/broker").toString();intmqttPort=settings.value("mqtt/port").toInt();// FastDDS数据监听类classFastDDSListener:publicDataReaderListener{public:voidon_data_available(DataReader*reader)override{UnifiedData data;SampleInfo info;if(reader->take_next_sample(&data,&info)==RETCODE_OK&&info.valid_data){// 1. FastDDS数据转换为ProtoBuf(或JSON)std::string serializedData;data.SerializeToString(&serializedData);// 2. 拼接MQTT主题(/host/device001/sensor/UnifiedData)QString mqttTopic=QString("/host/%1/sensor/%2").arg(hostId).arg(data.topic_name());// 3. MQTT发布QMqttClient*client=qobject_cast<QMqttClient*>(parent());client->publish(mqttTopic,QByteArray(serializedData.c_str(),serializedData.size()));}}};intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);// ========== 1. 初始化FastDDS(本机Domain ID) ==========DomainParticipant*participant=DomainParticipantFactory::get_instance()->create_participant(domainId,PARTICIPANT_QOS_DEFAULT);UnifiedDataPubSubType type;participant->register_type(&type);Topic*topic=participant->create_topic("UnifiedData",type.get_type_name(),TOPIC_QOS_DEFAULT);Subscriber*subscriber=participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);FastDDSListener listener;DataReader*reader=subscriber->create_datareader(topic,DATAREADER_QOS_DEFAULT,&listener);// ========== 2. 初始化MQTT客户端 ==========QMqttClient mqttClient;mqttClient.setHostname(mqttBroker);mqttClient.setPort(mqttPort);mqttClient.setClientId(hostId);// MQTT客户端ID=主机标识,便于Broker ACL管控mqttClient.connectToHost();// 绑定FastDDS监听器的父对象为MQTT客户端,便于转发listener.setParent(&mqttClient);// ========== 3. MQTT接收远端数据,转发到本地FastDDS ==========connect(&mqttClient,&QMqttClient::messageReceived,[&](constQByteArray&msg,constQMqttTopicName&topic){// 仅处理本机主题(避免跨主机数据)if(!topic.name().startsWith(QString("/host/%1/").arg(hostId)))return;// MQTT数据转换为FastDDS格式,发布到本机域UnifiedData data;data.ParseFromArray(msg.data(),msg.size());DataWriter*writer=participant->create_datawriter(topic,DATAWRITER_QOS_DEFAULT);writer->write(&data);});// 订阅本机MQTT主题mqttClient.subscribe(QMqttTopicFilter(QString("/host/%1/#").arg(hostId)));returna.exec();}

2. 本地EXE代码(仅需FastDDS,无需关心MQTT)

#include<QCoreApplication>#include<QSettings>#include"fastdds/dds/domain/DomainParticipantFactory.hpp"#include"UnifiedDataPubSubTypes.h"intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);// 读取本机Domain ID(与中转站一致)QSettingssettings("config.ini",QSettings::IniFormat);intdomainId=settings.value("fastdds/domain_id").toInt();// FastDDS初始化(仅需3步,自动发现中转站)DomainParticipant*participant=DomainParticipantFactory::get_instance()->create_participant(domainId,PARTICIPANT_QOS_DEFAULT);UnifiedDataPubSubType type;participant->register_type(&type);Topic*topic=participant->create_topic("UnifiedData",type.get_type_name(),TOPIC_QOS_DEFAULT);// 发布数据(自动发现本机域内的订阅者,无需指定地址)Publisher*publisher=participant->create_publisher(PUBLISHER_QOS_DEFAULT);DataWriter*writer=publisher->create_datawriter(topic,DATAWRITER_QOS_DEFAULT);UnifiedData data;data.set_topic_name("UnifiedData");data.set_content("本地EXE的北斗数据");writer->write(&data);returna.exec();}

3. 配置文件(config.ini,跨主机仅需修改此文件)

[fastdds] domain_id = 100 # 主机A=100,主机B=101,以此类推 [mqtt] host_id = device001 # 主机唯一标识 broker = 47.96.38.26 # MQTT Broker公网IP port = 1883

五、最终建议

1. 架构选型结论

该架构(本地FastDDS+远端MQTT+双层隔离)是你场景的最优解:

  • 满足“本地EXE仅订阅即可通信”:复用FastDDS自动配置/发现的优势,降低本地EXE开发成本;
  • 满足“多主机数据隔离”:Domain ID物理隔离+MQTT主题/ACL逻辑隔离,安全性可控;
  • 跨平台适配:FastDDS和Qt MQTT均支持Win/Linux/macOS,配置文件统一管理,部署灵活;
  • 成本平衡:本地实时性(FastDDS)+ 远端易用性(MQTT),比纯FastDDS跨网段部署成本低,比纯MQTT本地通信实时性高。

2. 落地优先级

  1. 先完成单主机验证:部署中转站+本地EXE,测试FastDDS本地通信+MQTT转发;
  2. 配置Broker ACL规则,验证多主机数据隔离;
  3. 封装通用转换模块(FastDDS↔ProtoBuf),所有主机复用;
  4. 增加中转站容灾、数据压缩、心跳检测等优化。

3. 替代方案对比(仅作参考)

方案隔离性本地体验远端部署成本实时性适配性
本地FastDDS+远端MQTT高优低中高优
纯FastDDS(跨网段)高优高(需DS集群)高中
纯MQTT(本地+远端)中差(手动配置)低中中

综上,该架构完美适配你的核心需求:本地FastDDS简化配置、远端MQTT降低部署成本、双层隔离保障多主机数据安全,且完全兼容Qt+C++跨平台开发体系。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进