充电桩mqtt弃用后的使用透传的平替方案

mqtt是原本的充电桩项目方案,本身具有按照主题发布消息订阅消息的能力,不过由于硬件方声称使用mqtt丢包率过高,需要更换为透传的方式,故而有了这个平替方案设计

MQTT协议工作原理

在 MQTT 协议中有三种身份:发布者(Publish)、代理(Broker)(服务器)和订阅者(Subscribe)。其中消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者,这三者的关系如下图所示:

mqtt_principle

在 MQTT 协议的实际使用过程中,一般遵循以下流程:

  • 发布者通过代理服务器向指定的 Topic 发布消息。
  • 订阅者通过代理服务器订阅所需要的 Topic。
  • 订阅成功后如果有发布者向订阅者订阅的 Topic 发布消息,那么订阅者就会收到代理服务器的推送消息,通过这种方式可以进行高效的数据交换。

在原本的工作逻辑中,Broker是docker部署的RMQX(一个开箱即用的mqtt代理),需要通信的三方:充电桩、后端服务器、微信小程序,都会同时作为发布者和订阅者,通过合理设置主题,实现充电流程的通信(细节不做说明)

可以看出这里的Broker是核心

然而透传便是去掉这个代理,让硬件客户端直接连接到服务器发送消息,也就是说直接使用TCP发送数据包。

透传的工作原理

去掉Broker后,硬件客户端通过TCP协议连接到后端服务器,因为tcp是全双工的,因此,充电桩和后端服务器之前的通信算是打通了。然而微信客户端如何与硬件进行通信呢?

微信需要向充电桩下达充电指令,结束充电指令以及,状态查询指令,充电桩需要向微信回复指令的执行结果以及充电过程中的计费信息。两者也是需要双向通行的,然而两者都没有固定的ip,因此,需要借助后端服务器进行中转。

小程序 —— 后端服务器

由于前端吐槽ws协议连接起来也不稳定,因此小程序和后端通信使用http协议,为了确保及时性,采用http轮询。

微信小程序→充电桩

小程序通过http协议向后端服务器发送充电开始请求,携带充电桩编号,后端服务器接收到消息以后构建消息通过TCP发送到对应的充电桩。至此小程序到充电桩的消息发送成功。

充电桩→微信小程序

微信小程序需要通过http轮询获取到充电桩信息,因此后端需要记录充电桩回复,将其放回给小程序,由于使用mysql更新对应充电桩字段状态这种方式比较麻烦且性能有限,使用redis记录整个消息无法很好的区分充电桩和主题。因此我选择使用rabbitmq消息对列,将充电桩的回复都发送到rabbitmq中。

为了能够更好的区分不同充电桩的不同类型消息,使用充电桩的编号作为交换机的名称,使用消息主题作为channel的名称。

这样小程序查询对应充电桩回复时后端服务器可以通过充电桩编号以及消息主题作为索引,去对应的消息对列中取消息,解析过后按照json格式放回给小程序。

优点:相较于使用mysql保存字段状态,这个方式不需要改变以及建好的数据库表,可以复用mqtt协议时候的消息解析函数。

图示流程

image-20250803220315270

注:pika是rabbitmq的python SDK