4. 云层架构与平台服务设计
云层是端边云协同架构的“中枢与大脑”。它不只是把数据集中存起来,更承担设备纳管、数据持久化、规则编排、模型训练与全局调度等职责。本节围绕云平台核心服务、微服务与 Serverless 架构、云边协同 API 设计、云层安全与多租户隔离四条主线展开,并给出一个可运行的最小化云平台原型搭建思路。
一、云平台核心服务:四类能力构成平台底座
一个可用的物联网云平台,通常由四类核心服务支撑:
- 设备管理服务:负责设备注册、身份认证、生命周期状态维护(在线/离线/禁用)、设备影子(Device Shadow)与元数据管理。设备影子是关键设计——它保存设备“期望状态”与“上报状态”两份 JSON,即使设备离线,云端也能暂存指令,待设备重连后下发。
- 数据存储服务:物联网数据具有“高频写入、时序性强、冷热分层”的特点。典型做法是热数据写入时序数据库(如 InfluxDB、TDengine),原始报文落入对象存储(如 MinIO、OSS),设备元数据与业务关系存入关系库(如 PostgreSQL)。
- 规则引擎:把“设备上报事件”与“动作”解耦。规则通常由三部分组成:触发条件(如温度 > 40)、过滤/转换(如取最近 5 条均值)、动作(写库、发 MQTT、调 HTTP、告警)。规则引擎让业务变更不必改动设备固件。
- AI 训练服务:接收边缘侧上传的样本数据,完成数据标注、特征工程、模型训练与版本管理,再把模型下发到边缘推理。云训练、边推理是典型的协同分工。
这四类服务并非孤立,而是围绕“设备—数据—规则—模型”形成闭环。下图给出云平台核心服务与云边协同接口的整体关系。
二、微服务与 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 函数按租户设置并发上限与内存配额,防止单租户打满平台资源。
五、实战:搭建最小化云平台原型
目标:用一台 4 核 8G 云主机,跑通“设备上报 → 规则触发 → 数据入库 → 查询展示”闭环。推荐组件与端口如下:
| 组件 | 作用 | 端口 |
|---|---|---|
| EMQX | MQTT 接入与主题路由 | 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/#,应被拒绝。若两条都符合预期,说明最小化云平台的接入、规则、存储与隔离链路已经打通。