[{"data":1,"prerenderedAt":475},["ShallowReactive",2],{"blog-post-zh-nanomq-newsletter-202302":3},{"post":4,"translationPath":-1},{"id":5,"title":6,"author":7,"body":8,"cover":456,"coverHeight":457,"coverWidth":55,"date":458,"description":459,"draft":460,"extension":461,"meta":462,"navigation":463,"path":464,"pinned":460,"seo":465,"sitemap":466,"stem":471,"tags":472,"__hash__":474},"blog_zh\u002Fzh\u002Fblog\u002Fnanomq-newsletter-202302.md","QUIC 多流桥接、新增 DDS 协议转换代理",null,{"type":9,"value":10,"toc":435},"minimark",[11,27,32,40,45,48,57,60,63,80,87,90,94,97,100,111,114,120,123,129,132,136,139,143,146,149,158,164,168,171,174,179,185,191,195,201,205,208,236,239,243,249,253,256,262,269,272,275,285,291,294,300,313,319,333,339,342,349,355,362,368,374,377,380,383,395,399,402,405,429,432],[12,13,14,18,19,26],"p",{},[15,16,17],"em",{},"驽马十驾，功在不舍","。新春之交，NanoMQ 继续保持稳步更新，最新的 0.16 版本将于三月初发布。NanoMQ 为用户提供了 2 个重要新功能：",[20,21,25],"a",{"href":22,"rel":23},"https:\u002F\u002Fwww.emqx.com\u002Fzh\u002Fblog\u002Fthe-easiest-guide-to-getting-started-with-mqtt",[24],"nofollow","MQTT"," over QUIC 的多流桥接和 DDS 协议转换代理，拓宽了 NanoMQ 的弱网桥接传输性能和在边缘端的使用场景。同时 NanoMQ 项目也在不懈努力提高项目的鲁棒性和安全性，积极快速响应社区提出的 Issue 和使用问题，新增了模糊测试用例和自动化的代码覆盖测试脚本。另外还新增了绿色安装版的 Windows 平台安装包。",[28,29,31],"h2",{"id":30},"quic-多流桥接","QUIC 多流桥接",[12,33,34,39],{},[20,35,38],{"href":36,"rel":37},"https:\u002F\u002Fwww.emqx.com\u002Fzh\u002Fblog\u002Fquic-protocol-the-features-use-cases-and-impact-for-iot-iov",[24],"QUIC 协议","相较于 TCP 的一大优势在于解决了队首阻塞的问题，但这是依赖于 QUIC 的单链接多 Stream 特性的。NanoMQ 之前发布的 MQTT over QUIC 桥接功能中暂时只支持单流模式，所有的 MQTT 包都在单一消息流（Stream）上面传输。单流传输当遇到网络拥塞或者网络抖动的情况时，会引起大量的消息重传，一样会阻塞后续到达的消息，从而造成逐步提高的消息延时，甚至是连接断开。 为了解决这一问题，NanoMQ 和 EMQX 5.0 一起设计和引入了 Mutli-stream QUIC 协议标准，以提供更好消息传输体验。",[41,42,44],"h3",{"id":43},"何为-mqtt-over-quic-mutli-stream","何为 MQTT over QUIC + Mutli-Stream?",[12,46,47],{},"Stream 是 QUIC 协议中传输层轻量级的有序字节流抽象，流可以是双工或半双工的。每个 QUIC 链接必须有大于等于一个的 Stream。客户端发起连接和创建 Stream 后，在 Stream 的基础上建立 MQTT 连接和进行报文交互。",[12,49,50],{},[51,52],"img",{"alt":53,"src":54,"title":53,"width":55,"height":56},"QUIC Multi-Stream","\u002Fimages\u002Fblog\u002Fzh\u002Fnanomq-newsletter-202302\u002F01.webp",1520,478,[12,58,59],{},"而在 0.16 版本中 NanoMQ 正式支持了多流桥接，当用户使用 MQTT over QUIC 桥接功能并开启多流选项时，NanoMQ 会根据用户配置的桥接上下行主题自动创建对应的 Topic-Stream 配对，每个主题之间的消息互相隔离。",[12,61,62],{},"目前多流桥接将 Stream 分为以下两种类型",[64,65,66,74],"ul",{},[67,68,69,73],"li",{},[70,71,72],"strong",{},"控制流："," 对于每个 MQTT over QUIC 连接，首次建立时必须先建立此 Stream，所有 MQTT 控制信令如 CONNECT\u002FPINGREQ\u002FPINGRESP 都默认在此流上传输。连接以控制流作为探测当前网络环境和连接健康度的唯一指标，控制流断开将导致连接重连。但用户也可以选择在控制流上传输 PUBLISH 包。",[67,75,76,79],{},[70,77,78],{},"数据流："," 桥接客户端每次进行 PUBLISH 和 SUBSCRIBE 操作都会根据使用的主题创建一个对应的数据流。此流由订阅或发布行为开启，服务端与客户端都会标识记录 PUBLISH 和 SUBSCRIBE 包中 Topic 和 此 Stream 的对应关系。所有发布到此 Topic 的数据都会被定向到此数据流。有别于控制流，数据流断开不会导致连接断开，而是下次自动重建。",[12,81,82],{},[51,83],{"alt":84,"src":85,"width":55,"height":86},"NanoMQ 多流桥接","\u002Fimages\u002Fblog\u002Fzh\u002Fnanomq-newsletter-202302\u002F02.webp",1114,[12,88,89],{},"如上图所示，单路 Stream 的情况下若 Topic 1 QoS 1 消息重传，会导致 Topic 2 和 Topic 3 的消息被阻塞。若使用多 Stream 桥接则可以在带宽未耗尽的情况下让多个主题的消息并行传输。当然相对应而言只能够保证在同一个主题内部的 QoS 消息的传输和到达顺序。",[41,91,93],{"id":92},"如何使用多流桥接","如何使用多流桥接？",[12,95,96],{},"目前使用多流桥接只需打开对应的配置选项：",[12,98,99],{},"旧配置文件格式：",[101,102,107],"pre",{"className":103,"code":105,"language":106},[104],"language-text","## multi-stream: enable or disable the multi-stream bridging mode\n## Value: true\u002Ffalse\n## Default: false\nbridge.mqtt.emqx.quic_multi_stream=false\n\n## 在流中是否赋予Qos消息高传输优先级\n## 针对每个流单独生效，非主题优先级\n## Value: true\u002Ffalse\n## Default: true\nbridge.mqtt.emqx.quic_qos_priority=true\n","text",[108,109,105],"code",{"__ignoreMap":110},"",[12,112,113],{},"HOCON 格式:",[101,115,118],{"className":116,"code":117,"language":106},[104],"quic_multi_stream = false\nquic_qos_priority=true\n",[108,119,117],{"__ignoreMap":110},[12,121,122],{},"之后根据用户 Pub\u002FSub 的具体主题会建立对应的 Stream，可以在 log 中检查功能是否生效，如订阅 nanomq\u002F1 主题就会自动创建一个 data stream：",[101,124,127],{"className":125,"code":126,"language":106},[104],"quic_ack_cb: Quic bridge client subscribe to topic (QoS 1)nanomq\u002F1.\nmqtt_sub_stream: topic nanomq\u002F1 qos 1\nbridge client is connected!\nquic_pipe_open: [strm][0x618000020080] Starting...\nquic_pipe_open: [strm][0x618000020080] Done...\nquic_strm_cb: quic_strm_cb triggered! 0\ndecode_pub_message: topic: [$SYS\u002Fbrokers\u002Fconnected], qos: 0\nmqtt_sub_stream: create new pipe 0x61c000020080 for topic nanomq\u002F1\nquic_strm_cb: QUIC_STREAM_EVENT_START_COMPLETE [0x618000020080] ID: 4 Status: 0\n",[108,128,126],{"__ignoreMap":110},[12,130,131],{},"之后 NanoMQ 就会自动根据 Topic 将数据包导流至不同的 Stream 发送。经过内部测试，在使用模拟 2s 延迟和 40% 丢包的弱网环境时，能够得到 stream 数量倍数的延时降低。",[41,133,135],{"id":134},"sub-包优先传输","Sub 包优先传输",[12,137,138],{},"在上一个版本中，NanoMQ 支持了 MQTT over QUIC 桥接中的 QoS 消息的优先传输。从 0.16 版本开始，Subscribe\u002FUnSubscribe 也将优先得到传输，来保证弱网下业务的正常运行。",[28,140,142],{"id":141},"dds-协议代理","DDS 协议代理",[12,144,145],{},"DDS 即 Data Distribution Service 数据分发服务，是以数据为中心的分布式实时通信中间件协议，采用发布\u002F订阅体系架构，强调以数据为中心，提供丰富的 QoS 服务质量策略，以保障数据进行实时、高效、灵活地分发，可满足各种去中心化的实时通信应用需求。",[12,147,148],{},"DDS 多用于点对点形式将数据在进程间通信。DDS 虽然也可以允许发布者发布数据，订阅者订阅数据，以及发布者和订阅者之间的双向通信，但仅局限在同一个域内，难以进行跨域通信。而在云边一体化的消息场景中，结合 MQTT + DDS 两种协议可以完美融合 broker + brokerless 两种消息模式。",[12,150,151,152,157],{},"NanoMQ 0.16 发布了 DDS Proxy 插件，其基于 ",[20,153,156],{"href":154,"rel":155},"https:\u002F\u002Fcyclonedds.io\u002F",[24],"Cyclone DDS"," （基于 OMG（Object Management Group）DDS 规范的开源 DDS 实现）开发，能够完成将 DDS 消息转换为 MQTT 消息并桥接上云的功能，以支持用户将 DDS 的数据通过 NanoMQ 来完成跨域传输并通过 MQTT 和云端互通。",[12,159,160],{},[51,161],{"alt":142,"src":162,"width":55,"height":163},"\u002Fimages\u002Fblog\u002Fzh\u002Fnanomq-newsletter-202302\u002F03.webp",623,[41,165,167],{"id":166},"dds-proxy-使用方法","DDS Proxy 使用方法",[12,169,170],{},"NanoMQ 的 DDS 协议转换插件通过 nanomq_cli 启动。目前该功能尚未集成到 Release 安装包中，如需使用还需要编译安装。",[12,172,173],{},"NanoMQ 并未直接引入 DDS 库，所以需要在运行环境中安装 CycloneDDS。在下一版本中，会在常见的平台版本的官方发行安装包里内置 CycloneDDS 的静态库，但如需交叉编译还需按照以下流程：",[175,176,178],"h4",{"id":177},"安装-iceoryx","安装 Iceoryx",[180,181,182],"blockquote",{},[12,183,184],{},"iceoryx 是 CycloneDDS 通过共享内存通信所需的依赖，如不需共享内存 IPC 可跳过本步骤",[101,186,189],{"className":187,"code":188,"language":106},[104],"$ git clone https:\u002F\u002Fgithub.com\u002Feclipse-iceoryx\u002Ficeoryx.git\n$ cd iceoryx\n$ git checkout release_2.0\n$ mkdir build && cd build\n$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX={USER_LIBRARY_PATH} ..\u002Ficeoryx_meta\n$ ninja\n$ sudo ninja install\n",[108,190,188],{"__ignoreMap":110},[175,192,194],{"id":193},"安装-cyclonedds","安装 CycloneDDS",[101,196,199],{"className":197,"code":198,"language":106},[104],"$ git clone https:\u002F\u002Fgithub.com\u002Feclipse-cyclonedds\u002Fcyclonedds.git\n$ cd cyclonedds\n$ mkdir build && cd build\n$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX={USER_LIBRARY_PATH} -DCMAKE_PREFIX_PATH={YOUR_LIBRARY_PATH} -DBUILD_EXAMPLES=ON ..\n$ ninja\n$ sudo ninja install\n",[108,200,198],{"__ignoreMap":110},[175,202,204],{"id":203},"配置-dds-的-idl","配置 DDS 的 IDL",[12,206,207],{},"DDS 相较于 MQTT 对于 payload 的定义方式不同，MQTT 协议并不关心消息的 Payload 内容， 而 DDS 通过用户编写的 IDL 文件来定义 DDS 消息的数据格式和类型。IDL（Interface Description Language）是一种通用的描述语言，用于在不同的编程语言之间定义数据类型，以保证不同节点之间以正确的格式通信。",[12,209,210,211,214,215,218,219,224,225,224,230,235],{},"CycloneDDS 库中通过 CMake 工具来自动根据用户内置的 IDL 文件来生成消息解析代码，其函数名和变量名会根据 IDL 中的定义改变。NanoMQ 保留了这一流程，每次编译时会根据 nanomq_cli\u002Fdds2mqtt\u002Fdds_type.idl 这一 IDL 文件来生成消息序列化和反序列化的代码。目前还需要用户自行将生成的代码 ",[108,212,213],{},"dds_type.h"," 和 ",[108,216,217],{},"dds_type.c"," 替换 ",[20,220,223],{"href":221,"rel":222},"https:\u002F\u002Fgithub.com\u002Fnanomq\u002Fnanomq\u002Fblob\u002F0.16.0\u002Fnanomq_cli\u002Fdds2mqtt\u002Fdds_mqtt_type_conversion.h",[24],"dds_mqtt_type_conversion.h","\u002F",[20,226,229],{"href":227,"rel":228},"https:\u002F\u002Fgithub.com\u002Fnanomq\u002Fnanomq\u002Fblob\u002F0.16.0\u002Fnanomq_cli\u002Fdds2mqtt\u002Fdds_mqtt_type_conversion.c",[24],"dds_mqtt_type_conversion.c",[20,231,234],{"href":232,"rel":233},"https:\u002F\u002Fgithub.com\u002Fnanomq\u002Fnanomq\u002Fblob\u002F0.16.0\u002Fnanomq_cli\u002Fdds2mqtt\u002Fdds_client.c",[24],"dds_client.c"," 文件中的函数名和引用。",[12,237,238],{},"在后续的 NanoMQ 版本规划中，将提供一个自动化的代码生成工具，能够根据 IDL 来自动替换源文件完成这部分工作，不再需要用户手动修改源码适配 DDS 结构体定义。",[41,240,242],{"id":241},"编译安装-nanomq-dds-proxy","编译安装 NanoMQ + DDS Proxy",[101,244,247],{"className":245,"code":246,"language":106},[104],"$ git clone https:\u002F\u002Fgithub.com\u002Fnanomq\u002Fnanomq.git\n$ cd nanomq\n$ mkdir build && cd build\n$ cmake -G Ninja -DCMAKE_PREFIX_PATH={USER_LIBRARY_PATH} -DBUILD_DDS_PROXY=ON ..\n$ ninja\n$ sudo ninja install\n",[108,248,246],{"__ignoreMap":110},[41,250,252],{"id":251},"配置打开-dds-proxy","配置打开 DDS Proxy",[12,254,255],{},"配置 \u002Fetc\u002Fnanomq_dds_gateway.conf 来设置需要进行桥接和转发的 MQTT 和 DDS 主题。",[101,257,260],{"className":258,"code":259,"language":106},[104],"## 转发规则配置\nforward_rules = {\n    ## DDS to MQTT 主题\n    dds_to_mqtt = {\n        from_dds = \"MQTTCMD\u002Ftopic1\"\n        to_mqtt = \"DDS\u002Ftopic1\"\n    }\n    ## MQTT to DDS 主题\n    mqtt_to_dds = {\n        from_mqtt = \"DDSCMD\u002Ftopic1\"\n        to_dds = \"MQTT\u002Ftopic1\"\n    }\n}\n\n## DDS 配置参数\ndds {\n    idl_type = topic1Type\n    domain_id = 0\n\n    shared_memory = {\n        enable = false\n        log_level = info\n    }\n}\n\n## MQTT 配置参数\nmqtt {\n    connector {\n        server = \"mqtt-tcp:\u002F\u002F127.0.0.1:1883\"\n        proto_ver = 4\n        # clientid=\"bridge_client\"\n        keepalive = 60s\n        clean_start = false\n        username = username\n        password = passwd\n\n        ssl {\n            enable = false\n            key_password = \"yourpass\"\n            keyfile = \"\u002Fetc\u002Fcerts\u002Fkey.pem\"\n            certfile = \"\u002Fetc\u002Fcerts\u002Fcert.pem\"\n            cacertfile = \"\u002Fetc\u002Fcerts\u002Fcacert.pem\"\n        }\n    }\n}\n\n",[108,261,259],{"__ignoreMap":110},[12,263,264,265],{},"启用 iceoryx 传输可参考文档",[20,266,267],{"href":267,"rel":268},"https:\u002F\u002Fgithub.com\u002Fnanomq\u002Fnanomq\u002Fblob\u002F0.16.0\u002Fnanomq_cli\u002Fdds2mqtt\u002Fdoc\u002FShared_memory.md",[24],[41,270,271],{"id":271},"启动和测试",[12,273,274],{},"此处以 DDS - MQTT 双向消息桥接为例。",[64,276,277],{},[67,278,279,280],{},"启动 ",[20,281,284],{"href":282,"rel":283},"https:\u002F\u002Fwww.emqx.com\u002Fzh\u002Fblog\u002Fthe-ultimate-guide-to-mqtt-broker-comparison",[24],"MQTT Broker",[101,286,289],{"className":287,"code":288,"language":106},[104],"$ nanomq start\n",[108,290,288],{"__ignoreMap":110},[12,292,293],{},"或",[101,295,298],{"className":296,"code":297,"language":106},[104],"$ emqx start\n",[108,299,297],{"__ignoreMap":110},[64,301,302],{},[67,303,304,305,308,309,312],{},"启动 DDS Proxy 桥接 MQTT 的",[108,306,307],{},"DDSCMD\u002Ftopic1"," 主题到 DDS 的 ",[108,310,311],{},"MQTT\u002Ftopic1"," 主题。",[101,314,317],{"className":315,"code":316,"language":106},[104],"$ .\u002Fnanomq_cli ddsproxy proxy --conf nanomq_dds_gateway.conf\n",[108,318,316],{"__ignoreMap":110},[64,320,321],{},[67,322,279,323,328,329,332],{},[20,324,327],{"href":325,"rel":326},"https:\u002F\u002Fwww.emqx.com\u002Fzh\u002Fblog\u002Fmqtt-client-tools",[24],"MQTT 客户端","订阅主题 ",[108,330,331],{},"DDS\u002Ftopic1"," 以验证消息是否桥接成功。",[101,334,337],{"className":335,"code":336,"language":106},[104],"$ .\u002Fnanomq_cli sub --url \"mqtt-tcp:\u002F\u002F127.0.0.1:1883\" -t \"DDS\u002Ftopic1\"\n",[108,338,336],{"__ignoreMap":110},[12,340,341],{},"现在我们发布一些消息到 DDS 主题来验证桥接是否成功。",[64,343,344],{},[67,345,346,347],{},"启动 DDS 客户端订阅 DDS 主题 ",[108,348,311],{},[101,350,353],{"className":351,"code":352,"language":106},[104],"$ .\u002Fnanomq_cli ddsproxy sub -t \"MQTT\u002Ftopic1\"\n",[108,354,352],{"__ignoreMap":110},[64,356,357],{},[67,358,359,360],{},"启动 MQTT 客户端发布消息到 MQTT 主题 ",[108,361,307],{},[101,363,366],{"className":364,"code":365,"language":106},[104],"$ .\u002Fnanomq_cli pub --url \"mqtt-tcp:\u002F\u002F127.0.0.1:1883\" -t \"DDSCMD\u002Ftopic1\" -m '{\n  \"int8_test\":    1,\n  \"uint8_test\":   50,\n  \"int16_test\":   27381,\n  \"uint16_test\":  1,\n  \"int32_test\":   0,\n  \"uint32_test\":  32,\n  \"int64_test\":   6820785120,\n  \"uint64_test\":  25855901936,\n  \"message\":      \"aaabbbddd\",\n  \"example_enum\": 0,\n  \"example_stru\": {\n    \"message\":      \"abc\"\n    }\n}'\n",[108,367,365],{"__ignoreMap":110},[12,369,370,371,373],{},"就能在订阅 ",[108,372,311],{}," 的 DDS 客户端处收到对应消息。如此就完成了将 MQTT 消息转化为 DDS 消息的过程，反之亦可。",[28,375,376],{"id":376},"其他优化",[41,378,379],{"id":379},"增加覆盖率测试和模糊测试",[12,381,382],{},"为了继续提高 NanoMQ 的工程质量和安全性，我们从 0.15.1 版本开始引入了 CodeCOV 来完成自动化代码覆盖率测试。",[12,384,385,386,214,390,394],{},"在 2 月中，NanoMQ 收到了许多有价值的模糊测试数据集和 Issue，在用户的帮助下找到了许多潜在安全隐患，在此对 ",[20,387,388],{"href":388,"rel":389},"https:\u002F\u002Fgithub.com\u002FNereuxofficial",[24],[20,391,392],{"href":392,"rel":393},"https:\u002F\u002Fgithub.com\u002Frealsung",[24]," 两位用户致以真挚的感谢。所有 Issue 都已经在一天内完全修复，所有他们提供的数据集都已纳入项目的自动模糊测试。",[41,396,398],{"id":397},"推出-windows-绿色版","推出 Windows 绿色版",[12,400,401],{},"为了更好的支持 Windows 平台的用户，我们基于之前发布的 msi 安装包基础上，推出了绿色版的安装包，解压即可用。目前 Windows 版本只支持基础的 MQTT broker 桥接、断网续传等功能。",[28,403,404],{"id":404},"问题修复",[406,407,408,411,414,417,420,423,426],"ol",{},[67,409,410],{},"修复 0.15.1 版本中多路桥接中消息回环触发异步 IO 越界的问题。",[67,412,413],{},"修复若干由模糊测试发现的安全隐患和内存泄漏，提高鲁棒性。",[67,415,416],{},"修复 nanomq_cli 的 quic工具使用。",[67,418,419],{},"修复 nanomq_cli 的无法将输出重定向至文件的问题。",[67,421,422],{},"修复 TSAN 发现的 MQTT over QUIC 传输层的线程竞争问题。",[67,424,425],{},"修复 NanoMQ 0.15 版本在 Windows 平台的兼容问题。",[67,427,428],{},"增加了可以在 MQTT 5 桥接连接中定义连接属性。",[28,430,431],{"id":431},"即将到来",[12,433,434],{},"NanoMQ 项目进入了第三个年头，感谢大家对项目的使用和支持。在下一个版本，NanoMQ 项目计划引入 SOME\u002FIP 协议的桥接转换。同时还会继续改进 DDS Proxy 功能的易用性，推出包含此功能的安装包，并为其加入 IDL 自动代码生成功能。此外，在 MQTT over QUIC 桥接部分还会增加双向认证和证书配置功能。",{"title":110,"searchDepth":436,"depth":436,"links":437},2,[438,444,450,454,455],{"id":30,"depth":436,"text":31,"children":439},[440,442,443],{"id":43,"depth":441,"text":44},3,{"id":92,"depth":441,"text":93},{"id":134,"depth":441,"text":135},{"id":141,"depth":436,"text":142,"children":445},[446,447,448,449],{"id":166,"depth":441,"text":167},{"id":241,"depth":441,"text":242},{"id":251,"depth":441,"text":252},{"id":271,"depth":441,"text":271},{"id":376,"depth":436,"text":376,"children":451},[452,453],{"id":379,"depth":441,"text":379},{"id":397,"depth":441,"text":398},{"id":404,"depth":436,"text":404},{"id":431,"depth":436,"text":431},"\u002Fimages\u002Fblog\u002Fzh\u002Fnanomq-newsletter-202302\u002Fcover.webp",532,"2023-03-06","将于三月初发布的 0.16 为用户提供了 2 个重要新功能：MQTT over QUIC 的多流桥接和 DDS 协议转换代理，拓宽了 NanoMQ 的弱网桥接传输性能和在边缘端的使用场景。",false,"md",{},true,"\u002Fzh\u002Fblog\u002Fnanomq-newsletter-202302",{"title":6,"description":459},{"loc":464,"images":467,"lastmod":458},[468,469,470],{"loc":54},{"loc":85},{"loc":162},"zh\u002Fblog\u002Fnanomq-newsletter-202302",[473],"NanoMQ Newsletter","fNrJcDVB3sq15Kpah75eTEtOVdgby6LWmbMaM33ZCmY",1794542897078]