RPC 是一种基于request/response 模式的分布式协议。而MQTT 是基于pub/sub模式的协议。是否能够将这两种协议相结合,实现RPC Over MQTT ?我并没有发现由比较知名的RPC over MQTT协议。于是,自己着手设计一个极简的RPC Over MQTT 协议。

本文介绍modular-2 Edge 中,使用MQTT 协议实现RPC 的方法。

 

mqtt rpc mqtt rpc协议_App

 

在modular-2 Edge 微服务架构中,提供了三种RPC 形式,它们分别是:

1 websocket RPC

2 MQTT RPC

3 HTML Restfull RPC

 

虽然三种方式的协议不同,但是消息体(message body )是一样的都是json格式的消息体,可以相互转换。当一个App 通过MQTT 客户端发布了一个RPC 消息后,如果该RPC 是websocket 类型的,会被base service 自动接收,并且通过websocket 转发到相关的App。

同样地,如果一个websocket RPC ,会被base service 发送给MQTT Broker ,有它转换成为MQTT 消息,发送给相关的App。

topic语法

MQTT 是基于topic 订阅和发布的通信方式。实现MQTT 协议的难点是设计一个合适的topic 命名方式和语法。

对于一个复杂系统,topic 命名更具有挑战性。

在实现RPC Over MQTT时,需要有一个唯一的topic 来标识一个RPC 调用和结构。它需要反映如下信息

目标名称 发往的App名称

信源名称 发送App 的名称

RPC方法 虽然在消息体的json 描述中含有RPC 但是为了订阅和发布的方便。在topic 中也需要包含了method 的名称。

 因此,我们设计的topic 格式为:

<destination>/<originator>/<method>

其中

<destination> 接收者的App名称

<originator>  发送者的App名称

<method>方法的名称

 

通知

<destination><originator><method><inf>

 为什么要在topic 中包含目标和信源的名称呢?

实例:

App 注册 (register App)
microservice1/gpio/register
数字IO 写(DigitalOut.Write)
microservice1/gpio/digitaloutwrite
数字IO翻转(DigitalOut.flipflop)
microservice1/gpio/digitaloutflipflop
模拟量输入
microservice1/vibration/analogread
modbus请求
microservice1/weather/modbusrequest

 

消息体

MQTT 的payload 采用了json 格式的rpc,例如

jsonrpc={
method:“microservice/digitalOut.write";
mode:2;
params:{
value[1,0]
}
id:1
}

处理流程

  1 baseservice 订阅

  • 订阅baseservice 的RPC。

subscribe(“baseservice/#”)

  • 订阅所有websocket RPC
当一个websocket 的RPC 注册时,要向MQTT Broker 订阅该RPC.例如:
subscribe(“microservice/+/digitalOut.write);
2 App 订阅发送给它的MQTT 消息,如果App 是gpiomqtt,那么它会订阅:
       subscribe(“”gpiomqtt/#”);
  3 MQTT 命令出错
baseservice 会向App 发送 error 消息,topic为
<appname>/<baseservice>/error
消息体是json 格式的出错信息。

结论

在modular-2 微服务架构中,采用了最简单的MQTT topic 设计,实现了RPC over MQTT 协议。并且和websocket RPC 兼容。MQTT 的应用中,应该避免MQTT topic 的随意性,将topic 减少到最简单。是一个好的方法。