网易首页 > 网易号 > 正文 申请入驻

别再裸写 parseFrom() 了!这才是 MQTT + Protobuf 消费的正确姿势!

0
分享至

点击下方“JavaEdge”,选择“设为星标”

第一时间关注技术干货!


免责声明~ 任何文章不要过度深思! 万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」; 不要急着评判文章列出的观点,只需代入其中,适度审视一番自己即可,能「跳脱出来从外人的角度看看现在的自己处在什么样的阶段」才不为俗人。 怎么想、怎么做,全在乎自己「不断实践中寻找适合自己的大道」

本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 魔都架构师 | 全网30W技术追随者

  • 大厂分布式系统/数据中台实战专家

  • 主导交易系统百万级流量调优 & 车联网平台架构

  • AIGC应用开发先行者 | 区块链落地实践者

  • 以技术驱动创新,我们的征途是改变世界!

  • 实战干货:编程严选网

本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!

  • 魔都架构师 | 全网30W技术追随者

  • 大厂分布式系统/数据中台实战专家

  • 主导交易系统百万级流量调优 & 车联网平台架构

  • AIGC应用开发先行者 | 区块链落地实践者

  • 以技术驱动创新,我们的征途是改变世界!

  • 实战干货:编程严选网

0 前言

很多刚接触这个技术栈的同学,可能会觉得有点绕。MQTT 负责传输,Protobuf 负责定义数据结构,听起来是天作之合,但具体到代码层,咋写最“哇塞”?本文以车联网(V2X)场景为例,把这个事儿聊透,让你不仅知其然,更知其所以然。

咱们的案例原型就是这段非常

1 典型的.proto文件

syntax = "proto3"; option java_multiple_files = true; option java_package = "cn.javaedge.v2x.protocol"; package cn.javaedge.v2x.pb; enum Message_Type {     UKNOWN_MSG = 0; } // 消息体定义,如车辆消息 message VehicleMessage {     string vehicle_id = 1; }

实际业务中,通常会有一个统一的“信封”消息,里面包含消息类型和真正的业务数据包。

需求明确:Java服务作MQTT客户端,订阅某Topic,源源不断收到二进制数据。这些数据就是用上面这.proto文件定义的VehicleMessage序列化后的结果。我们的任务就是把它高效、健壮地解码出来。

2 核心思路:从“能跑就行”到“最佳实践”

很多同学第一反应直接在 MQTT 的messageArrived回调方法写一堆try-catch,再调用 Protobuf 的parseFrom()方法:

// 伪代码:一个“能跑就行”的例子 public void messageArrived(String topic, MqttMessage message) {     try {         byte[] payload = message.getPayload(); }

这段代码能工作吗?当然能。但在高并发、要求高可用、业务逻辑复杂的生产环境中,这远远不够。它就像一辆只有发动机和轮子的裸车,能跑,但一阵风雨就可能让它趴窝。

最佳实践是啥?,建立一套分层、解耦、易于维护和扩展的处理流程。

3 最佳实践:构建稳如泰山的 Protobuf 解析层

让我们把这个过程拆解成几个关键步骤,并逐一优化。

3.1 Protobuf代码生成与依赖管理

构建阶段,看似准备工作,却是保证后续一切顺利的基石。

使用 Maven插件自动生成代码

别手动执行protoc命令,再把生成的.java文件拷贝到项目里。这是“上古时期”做法。现代化的构建工具能完美解决这个问题。

Maven示例:


 com.google.protobuf:protoc:3.25.3:exe:${os.detected.classifier} protocArtifact>
这样做的好处
  1. 自动化:每次构建项目时,都会自动检查.proto文件是否有更新,并重新生成 Java 类

  2. 版本一致性:确保protoc编译器版本和protobuf-java运行时库版本的一致,避免因版本不匹配导致的各种诡异错误

  3. IDE 友好:IDEA能很好识别这些生成的源代码,提供代码补全和导航

3.2 定义清晰的解析器接口

设计模式的应用,直接在 MQTT 回调里写解析逻辑,违反单一职责原则。MQTT 客户端的核心职责是网络通信,不应关心消息体的具体格式。

应将解析逻辑抽象出来:

// 定义一个通用的反序列化器接口 public interface MessageDeserializer

  { }

然后,为我们的VehicleMessage实现该接口:

publicclass VehicleMessageDeserializer implements MessageDeserializer

  { }
好处
  1. 解耦:MQTT 消费者代码与 Protobuf 解析逻辑完全分离。未来如果想把数据格式从 Protobuf 换成 JSON,只需要换一个MessageDeserializer的实现类即可,消费者代码一行都不用改。

  2. 职责单一VehicleMessageDeserializer只干一件事:解析VehicleMessage。代码清晰,易于测试。

  3. 统一异常处理:通过自定义的DeserializationException,我们将底层的InvalidProtocolBufferException进行了封装。上层代码只需要捕获DeserializationException,大大简化了错误处理逻辑。

3.3 在 MQTT 消费者中优雅地使用解析器

组合与分发。现在,MQTT消费者变得清爽:

public class MqttConsumerService { }
架构精髓 ① 依赖注入 (DI)

通过构造函数注入依赖(解析器和业务处理器),而不是在方法内部new对象。这使得整个服务非常容易进行单元测试。我们可以轻易地 mockMessageDeserializer来测试MqttConsumerService的逻辑,而不需要真实的 Protobuf 数据。

② 关注点分离 (SoC)

  • MqttConsumerService:负责从 MQTT 接收字节流,协调解析和业务处理的流程,并统一处理异常。

  • VehicleMessageDeserializer:负责将字节流转换为VehicleMessage对象。

  • BusinessLogicHandler:负责拿到VehicleMessage对象后所有的业务计算和处理。

③ 健壮的异常处理
  • 区分已知和未知异常:我们明确捕获DeserializationException,这是“已知”的解析失败,通常意味着消息格式有问题。对于这种消息,最佳实践是隔离它,比如发送到“死信队列”,避免它反复阻塞正常消息的处理。

  • **捕获顶级Exception**:这是一个保护性措施,确保任何意想不到的错误(比如空指针、业务逻辑层的运行时异常)都不会导致整个 MQTT 消费者线程崩溃。

4 进阶:应对真实世界的复杂性

上面的架构已很优秀,但更复杂场景下,还需考虑更多。

4.1 多消息类型处理 (Message Dispatching)

通常一个 MQTT Topic 不会只有一种消息类型。还记得我们.proto文件里的Message_Type枚举吗?这正是用于区分不同消息的。

实际的 Protobuf 结构通常是这样的“信封模式” (Envelope Pattern):

message UniversalMessage { }

google.protobuf.Any是 Protobuf 的一个标准类型,可以包含任意一种 Protobuf 消息。

消费者的逻辑就需要升级为一个**分发器 (Dispatcher)**:

public class UniversalMessageDispatcher { }

这种基于“注册表”和Any类型的分发模式,是处理多消息类型时扩展性最好的方案。

4.2 性能考量:对象池与零拷贝

高吞吐量场景下(如每秒处理成千上万条消息),频繁创建和销毁VehicleMessage对象会给 GC 带来巨大压力。

对象池技术

可以使用像 Apache Commons Pool2 这样的库,来复用VehicleMessage.Builder对象。解析时,从池中获取一个 Builder,用mergeFrom()方法填充数据,构建出VehicleMessage对象,使用完毕后再将 Builder 清理并归还到池中。

零拷贝

Protobuf 的ByteString类型在内部做很多优化,可实现对底层byte[]的“零拷贝”引用。在传递数据时,尽量传递ByteString而非byte[],可减少不必要的内存复制。

5 总结

从一个简单的parseFrom()调用,逐步构建一套企业级 MQTT-Protobuf 消费方案。

  1. 构建自动化:Maven插件管理 Protobuf 代码生成,告别刀耕火种

  2. 设计模式先行:定义MessageDeserializer接口,实现策略模式,解耦【解析】与【消费】逻辑

  3. 分层与解耦:将流程清晰划分为网络接入层(MQTT Client)、反序列化层(Deserializer) 和业务逻辑层(Handler),职责分明,易维护

  4. 健壮的错误处理:封装自定义异常,并设计了对解析失败消息的隔离机制(如死信队列),保证系统的韧性

  5. 面向未来的扩展性:引入“信封模式”和“分发器”,从容应对未来不断增加的新消息类型

优秀的代码不仅是让机器读懂,更是让同事(及半年后的自己)轻松读懂。核心思想即通过抽象、解耦和分层,来管理软件的复杂性。

加我好友,一起AI探索交流!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
迁安市荣信钢铁发生重大生产死亡事故,安全生产令人担忧!

迁安市荣信钢铁发生重大生产死亡事故,安全生产令人担忧!

故事换老酒
2026-07-20 13:44:25
停职通报还有后续!强占车位的彭某又面临三个麻烦,其遴选成绩也被公开曝光

停职通报还有后续!强占车位的彭某又面临三个麻烦,其遴选成绩也被公开曝光

奇葩游戏酱
2026-07-19 01:51:48
西安赛格事件又发酵!7月18日晚间,网友实拍现场人流寥寥无几,小寨十字交通也不堵了

西安赛格事件又发酵!7月18日晚间,网友实拍现场人流寥寥无几,小寨十字交通也不堵了

火山詩话
2026-07-19 08:55:32
警惕!多地出现“热射病”病例,该病死亡率最高可达80%,近期高发

警惕!多地出现“热射病”病例,该病死亡率最高可达80%,近期高发

大象新闻
2026-07-20 17:08:13
西班牙夺冠后,FIFA在颁奖仪式上的两个举动,挽回了些许口碑

西班牙夺冠后,FIFA在颁奖仪式上的两个举动,挽回了些许口碑

生活新鲜市
2026-07-20 16:57:11
还以为中国落后一年,Kimi K3突然杀到!特朗普顾问:美国要输掉AI竞赛了

还以为中国落后一年,Kimi K3突然杀到!特朗普顾问:美国要输掉AI竞赛了

青青子衿
2026-07-18 13:01:05
恩佐决赛染红!一脚踢飞库巴西,16年第一人,名宿怒斥太愚蠢

恩佐决赛染红!一脚踢飞库巴西,16年第一人,名宿怒斥太愚蠢

奥拜尔
2026-07-20 05:21:27
斯卡洛尼也拦不住!阿根廷莽汉赛后失控吃红牌:暴力锁喉 怒推对手

斯卡洛尼也拦不住!阿根廷莽汉赛后失控吃红牌:暴力锁喉 怒推对手

风过乡
2026-07-20 06:38:00
7月16日,陈冠希分享了一张去看世界杯的近照,只见他在观众席穿着球衣戴着眼镜和帽子,与年轻时的痞帅判若两人

7月16日,陈冠希分享了一张去看世界杯的近照,只见他在观众席穿着球衣戴着眼镜和帽子,与年轻时的痞帅判若两人

牛油果生活观
2026-07-19 12:09:43
破案了!阿根廷为何没拖进点球大战?徐亮和董路给出观点 因为梅

破案了!阿根廷为何没拖进点球大战?徐亮和董路给出观点 因为梅

梅亭谈
2026-07-20 13:33:27
全世界声讨阿根廷有失体面,德国前国脚:一群毫无体育精神的败类

全世界声讨阿根廷有失体面,德国前国脚:一群毫无体育精神的败类

杨华评论
2026-07-20 13:47:16
二胎、三胎催生无果,国家换新思路!马光远“新方案”得到支持

二胎、三胎催生无果,国家换新思路!马光远“新方案”得到支持

快乐彼岸
2026-07-18 19:01:46
坏了!马斯克真是在搞庞氏骗局!万亿美元蒸发只是开始

坏了!马斯克真是在搞庞氏骗局!万亿美元蒸发只是开始

丹妮观
2026-07-20 12:25:26
阿媒:阿根廷足协立即行动,全力挽留斯卡洛尼

阿媒:阿根廷足协立即行动,全力挽留斯卡洛尼

体坛周报
2026-07-20 14:36:20
孙宇晨犀利点评邹市明夫妇:冉莹颖吸血奋斗者,鸠占鹊巢!拿刘邦吕后作比,一针见血

孙宇晨犀利点评邹市明夫妇:冉莹颖吸血奋斗者,鸠占鹊巢!拿刘邦吕后作比,一针见血

火山詩话
2026-07-19 16:20:44
何长工在关键时刻站错队,此后官越做越小,建国后也没能参加授衔

何长工在关键时刻站错队,此后官越做越小,建国后也没能参加授衔

云端小院
2026-07-20 08:19:33
接亲被伴娘堵门要999红包,新郎喊三遍新娘不开门,转身带走婚车队:这婚不结了!

接亲被伴娘堵门要999红包,新郎喊三遍新娘不开门,转身带走婚车队:这婚不结了!

一丝不苟的法律人
2026-07-18 17:33:11
地铁安检到底在防谁?国外多年没有照样过,国内为何层层设防?

地铁安检到底在防谁?国外多年没有照样过,国内为何层层设防?

抽象派大师
2026-07-20 02:07:32
39岁拜纳姆近况,退役远离NBA,满头白发,财富自由也发福了

39岁拜纳姆近况,退役远离NBA,满头白发,财富自由也发福了

大西体育
2026-07-20 17:14:58
在境外针对中国公民实施绑架杀人犯罪的嫌疑人刘某文被遣返我方

在境外针对中国公民实施绑架杀人犯罪的嫌疑人刘某文被遣返我方

界面新闻
2026-07-20 17:46:50
2026-07-20 19:35:00
JavaEdge incentive-icons
JavaEdge
Java 技术
499文章数 458关注度
往期回顾 全部

科技要闻

中兴阶跃荣耀齐出手,AI手机争夺系统入口

头条要闻

女子带88岁奶奶自驾游8省 耗时21天总花费约2万

头条要闻

女子带88岁奶奶自驾游8省 耗时21天总花费约2万

体育要闻

65岁肌肉男,世界杯最年长冠军主帅

娱乐要闻

谢霆锋发文确认父亲谢贤去世 享年89岁

财经要闻

AI开始挤泡沫

汽车要闻

宾利第四大车系定名托卡尔 9月23日伦敦全球首秀

态度原创

亲子
房产
健康
数码
手机

亲子要闻

夏季湿疹热疹虫咬皮炎高发,儿童皮肤科专家支招科学防治

房产要闻

北师附、人大附、西侨、丘海…招生、划片最新变化来了!

“斑块”患者要小心中风?

数码要闻

日本推出“人体冰箱”:5分钟快速降温 售价约150万日元

手机要闻

大疆Osmo 360 II原型机真机曝光:延续现款外形设计、新增NFC

无障碍浏览 进入关怀版