4. 云层架构与平台服务设计

云层是端边云协同架构的“中枢与大脑”。它不只是把数据集中存起来,更承担设备纳管、数据持久化、规则编排、模型训练与全局调度等职责。本节围绕云平台核心服务、微服务与 Serverless 架构、云边协同 API 设计、云层安全与多租户隔离四条主线展开,并给出一个可运行的最小化云平台原型搭建思路。

一、云平台核心服务:四类能力构成平台底座

一个可用的物联网云平台,通常由四类核心服务支撑:

  • 设备管理服务:负责设备注册、身份认证、生命周期状态维护(在线/离线/禁用)、设备影子(Device Shadow)与元数据管理。设备影子是关键设计——它保存设备“期望状态”与“上报状态”两份 JSON,即使设备离线,云端也能暂存指令,待设备重连后下发。
  • 数据存储服务:物联网数据具有“高频写入、时序性强、冷热分层”的特点。典型做法是热数据写入时序数据库(如 InfluxDB、TDengine),原始报文落入对象存储(如 MinIO、OSS),设备元数据与业务关系存入关系库(如 PostgreSQL)。
  • 规则引擎:把“设备上报事件”与“动作”解耦。规则通常由三部分组成:触发条件(如温度 > 40)、过滤/转换(如取最近 5 条均值)、动作(写库、发 MQTT、调 HTTP、告警)。规则引擎让业务变更不必改动设备固件。
  • AI 训练服务:接收边缘侧上传的样本数据,完成数据标注、特征工程、模型训练与版本管理,再把模型下发到边缘推理。云训练、边推理是典型的协同分工。

这四类服务并非孤立,而是围绕“设备—数据—规则—模型”形成闭环。下图给出云平台核心服务与云边协同接口的整体关系。

云层 · 平台核心服务 设备管理 注册 / 认证 / 影子 在线状态维护 数据存储 时序库 / 对象存储 关系库元数据 规则引擎 条件 / 转换 / 动作 事件驱动解耦 AI 训练 样本 / 训练 / 版本 模型下发 微服务 + Serverless 运行底座 API 网关 · 服务注册发现 · 消息总线 · 函数计算 · 容器编排 云边协同 API 层 设备接入 MQTT/CoAP · 模型下发 HTTPS · 规则同步 gRPC · 状态上报 WebSocket 边缘层 · 网关 / 边缘节点 协议转换 本地规则 模型推理 断网缓存 下行:指令/模型/规则 上行:数据/状态/样本

二、微服务与 Serverless:让平台可伸缩、可演进

把四类核心服务做成单体应用,早期开发快,但设备量增长后会出现“一处扩容、全量重启”的问题。微服务化把设备管理、数据写入、规则执行、模型训练拆成独立部署单元,各自独立扩缩容。例如规则执行服务在告警高峰期可单独扩到 10 个实例,而设备管理服务保持 2 个实例即可。

Serverless 进一步降低运维负担。以“设备上线触发规则校验”为例,可写成函数:

def on_device_online(event, context):
    device_id = event["deviceId"]
    # 1. 更新设备影子期望状态
    shadow = get_shadow(device_id)
    shadow["desired"]["reportInterval"] = 30
    update_shadow(device_id, shadow)
    # 2. 触发规则引擎重新评估
    publish("rule/eval", {"deviceId": device_id})
    return {"status": "ok"}

函数只在事件到达时计费,适合突发性、低频但关键的任务。需要注意的是,Serverless 有冷启动延迟,对毫秒级实时控制不友好,因此实时控制仍应放在边缘侧完成。

三、云边协同 API 设计:方向、语义与幂等

云边 API 设计要明确三件事:方向(上行/下行)、语义(命令/事件/查询)、可靠性(幂等、重试、超时)。建议约定:

  • 上行数据用 MQTT 主题 edge/{edgeId}/telemetry,QoS 1,保证至少一次送达。
  • 下行指令用 cloud/{deviceId}/command,携带 requestId 实现幂等,设备重复收到同一 requestId 只执行一次。
  • 模型下发用 HTTPS 拉取,边缘侧校验 SHA-256 后再加载,避免传输损坏。
  • 规则同步用 gRPC 流式接口,云端规则变更后 1 秒内推送到边缘。

一个常见的坑是“指令丢失”。若设备离线,云端应把指令写入设备影子的 desired 区,设备重连后主动拉取并执行,而不是反复重发 MQTT 消息。

四、云层安全与多租户隔离

多租户隔离要贯穿四个层面:

  • 身份隔离:每个租户独立 AppKey/Secret,设备证书按租户签发,禁止跨租户注册。
  • 数据隔离:时序库按租户分 measurement 或分库,对象存储按 tenantId/ 前缀隔离,查询强制带租户过滤条件。
  • 网络隔离:不同租户的 MQTT 接入使用独立端口或独立 Broker 集群,避免主题越权订阅。
  • 资源隔离:Serverless 函数按租户设置并发上限与内存配额,防止单租户打满平台资源。
安全红线:任何 API 都必须从令牌中解析 tenantId,而不是从请求参数中读取。否则攻击者只需改一个参数就能访问他人数据。

五、实战:搭建最小化云平台原型

目标:用一台 4 核 8G 云主机,跑通“设备上报 → 规则触发 → 数据入库 → 查询展示”闭环。推荐组件与端口如下:

组件作用端口
EMQXMQTT 接入与主题路由1883 / 8083
PostgreSQL设备元数据、租户表5432
TDengine时序数据存储6041
Node-RED规则引擎原型1880
MinIO模型与原始报文存储9000

关键配置示例(EMQX 开启租户级 ACL):

# emqx.conf 片段
authorization {
  sources = [
    {
      type = file
      enable = true
      path = "/etc/emqx/acl.conf"
    }
  ]
}
# acl.conf:只允许租户订阅自己的主题
{allow, {user, "tenant_a"}, subscribe, ["tenant_a/#"]}.
{deny, all, subscribe, ["#"]}.

验证方法:用 mosquitto_pub 以 tenant_a 身份向 tenant_a/dev1/telemetry 发布一条温度 45℃ 的消息,观察 Node-RED 是否触发“温度 > 40”规则并写入 TDengine;再用 tenant_b 身份尝试订阅 tenant_a/#,应被拒绝。若两条都符合预期,说明最小化云平台的接入、规则、存储与隔离链路已经打通。

原型阶段不必追求高可用,但租户隔离与幂等设计必须从第一天就做对,否则后期改造成本极高。