4. Sparkplug B架构与组件

Sparkplug B 并不是一个独立的传输协议,而是一套建立在 MQTT 之上的主题命名规范、载荷编码规范与生命周期状态机。理解它的第一步,是把系统中的参与者按职责拆开:谁负责采集、谁负责承载、谁负责消费、谁负责编排。Sparkplug B 明确定义了四类角色——边缘节点(Edge Node)、设备(Device)、主应用(Primary Host Application)和MQTT 服务器(MQTT Server / Broker)。四者各司其职,通过主题空间与状态主题形成松耦合但语义严格的协作关系。

一、四类角色的职责边界

边缘节点是 Sparkplug 拓扑中的“网关”角色。它直接与 MQTT 服务器建立唯一的 MQTT 会话,代表自己以及其下挂的一台或多台设备发布数据。边缘节点拥有自己的状态主题,负责发布 NBIRTH、NDEATH、NDATA、NCMD 等消息,是设备数据的“代言人”。典型实现包括 PLC 网关、边缘计算盒子、协议转换器。

设备是真正产生物理量或执行动作的终端,例如变频器、温度变送器、机器人控制器。设备本身通常不具备 MQTT 能力,它通过 Modbus、OPC UA、Profinet 等工业协议连接到边缘节点。在 Sparkplug 语义中,设备没有独立的 MQTT 连接,它的所有数据都由边缘节点以 DBIRTH、DDEATH、DDATA、DCMD 的形式代为发布。

主应用是数据的消费者与命令的发起者。它订阅边缘节点与设备的主题,维护整个 Sparkplug 命名空间的“镜像”,并在需要时向设备下发写命令。主应用通常只有一个处于活跃状态(Primary Host),其余为备用,通过 STATE 主题实现主备仲裁,避免命令重复下发。

MQTT 服务器是纯粹的消息中枢。它不理解 Sparkplug 语义,只按主题做发布/订阅路由,并负责会话保持、遗嘱消息(Will)触发、QoS 保障。Sparkplug 的“死亡通知”能力正是借助 MQTT 的遗嘱机制实现的。

核心记忆点:边缘节点是“唯一 MQTT 会话持有者”,设备是“被代理的物理实体”,主应用是“状态镜像与命令源”,MQTT 服务器是“无语义的消息总线”。

二、交互关系全景图

下图展示了四类角色之间的连接方式、主题流向与生命周期消息的传播路径。注意设备与 MQTT 服务器之间没有直接连线,这是 Sparkplug B 架构最容易被误解的地方。

MQTT 服务器 Broker · 主题路由 · 遗嘱触发 边缘节点 Edge Node 唯一 MQTT 会话 NBIRTH / NDEATH / NDATA 设备 Device PLC / 变频器 / 变送器 无独立 MQTT 连接 主应用 Primary Host 订阅全命名空间 STATE / NCMD / DCMD NBIRTH/NDATA 订阅分发 NCMD/DCMD 命令下发 Modbus / OPC UA 采集数据 STATE 主题 主备仲裁 · 在线声明 图例 数据发布 命令下发 STATE 仲裁

三、主题空间与消息类型的对应关系

Sparkplug B 的主题结构是 spBv1.0/<group_id>/<message_type>/<edge_node_id>/[device_id]。四类角色通过主题中的 message_type 字段区分行为。下表梳理了关键消息类型与角色的对应关系,这是排障时最常用的对照清单。

消息类型 发布者 订阅者 作用
NBIRTH 边缘节点 主应用 声明节点上线及全部指标清单
NDEATH MQTT 服务器(遗嘱) 主应用 节点异常离线通知
DBIRTH 边缘节点(代设备) 主应用 声明设备上线及指标清单
DDEATH 边缘节点(代设备) 主应用 设备离线通知
NDATA / DDATA 边缘节点 主应用 发布指标变化值
NCMD / DCMD 主应用 边缘节点 下发写命令或重启指令
STATE 主应用 全体 声明主应用在线状态,用于主备仲裁

四、典型场景:一条温度数据的完整旅程

假设某车间有一台温度变送器,通过 Modbus RTU 接入边缘网关,网关以 group_id=factoryA、edge_node_id=gw01、device_id=temp01 接入 Sparkplug 命名空间。数据从产生到被主应用消费,经历如下链路:

  1. 变送器通过 Modbus 寄存器暴露温度值,边缘节点周期性轮询。
  2. 边缘节点首次上线,向 spBv1.0/factoryA/NBIRTH/gw01 发布 NBIRTH,携带节点级指标清单。
  3. 边缘节点识别到 temp01,向 spBv1.0/factoryA/DBIRTH/gw01/temp01 发布 DBIRTH,声明设备指标。
  4. 温度变化超过死区阈值,边缘节点向 spBv1.0/factoryA/DDATA/gw01/temp01 发布 DDATA,载荷为 Protobuf 编码的指标值。
  5. 主应用订阅 spBv1.0/factoryA/#,收到 DDATA 后更新本地镜像,并触发报警或写入时序库。
  6. 若主应用需要修改温度上限,向 spBv1.0/factoryA/DCMD/gw01/temp01 发布 DCMD,边缘节点解析后写回 Modbus 寄存器。
# 主应用订阅通配主题
spBv1.0/factoryA/#

# 边缘节点发布 DDATA 示例主题
spBv1.0/factoryA/DDATA/gw01/temp01

# 主应用下发 DCMD 示例主题
spBv1.0/factoryA/DCMD/gw01/temp01

五、常见误区与复盘要点

误区一:让设备直接连 MQTT 服务器。Sparkplug B 规定设备不持有 MQTT 会话,所有设备消息必须由边缘节点代理发布。若设备直连,会导致 NDEATH/DDEATH 语义混乱,主应用无法正确判断离线边界。
误区二:多个主应用同时下发命令。Sparkplug 通过 STATE 主题实现主备仲裁,只有 Primary Host 处于活跃状态时才应下发 NCMD/DCMD。若忽略 STATE 机制,会出现命令重复执行、设备状态抖动。
复盘要点:排障时先看 MQTT 服务器上的主题树,确认 NBIRTH/DBIRTH 是否按序到达;再检查边缘节点的遗嘱配置是否指向正确的 NDEATH 主题;最后核对主应用的 STATE 声明是否与当前活跃实例一致。这三步能覆盖绝大多数“数据不上来”或“命令不生效”的问题。

把四类角色的边界记牢,后续学习指标建模、别名机制、状态机细节时,就能清楚每条消息“由谁发、发给谁、为什么发”。架构清晰,是 Sparkplug B 工程落地的前提。