很多人聊 IoT 实时链路,一上来就问:
“用 Kafka 还是 Pulsar?”
“Flink 窗口怎么写?”
“时序库选 IoTDB、InfluxDB 还是 ClickHouse?”
“要不要上湖仓?”
这些问题当然重要,但顺序其实反了。
真正设计 IoT 实时链路,第一步不是选组件,而是先搞清楚一件事:
设备事件进入平台之后,到底要在多长时间内,触发什么业务结果?
如果只是“采集数据、存起来、做报表”,那它是数据链路。
如果能做到“设备异常上报、实时识别、自动告警、联动服务、反写设备、沉淀资产”,那才是 IoT 实时闭环。
尤其在智慧康养、智慧水务、智慧农业、智能家居、智慧幼教、工业设备、连锁门店、美业设备这些场景里,IoT 实时链路不是一个技术模块,而是业务中枢。它既要接住海量设备事件,也要把这些事件变成实时告警、设备画像、用户画像、运营动作、算法特征、产品策略和数据资产。
这篇文章就从架构师视角,把一条完整的 IoT 实时链路讲透:
设备事件
-> 边缘网关 / IoT 网关
-> 消息队列
-> 标准物模型和数据契约
-> Flink 实时计算
-> 时序库 / OLAP / 湖仓
-> 告警、规则、工单、设备控制、业务动作
我会尽量少讲空话,重点讲“为什么这么设计、坑在哪里、怎么落地”。
一、先说背景:IoT 实时链路为什么越来越重要?
过去很多 IoT 平台,本质上是“设备联网平台”。
设备能上云,App 能控制,后台能看到在线状态,这就算完成第一阶段了。
但现在不一样了。企业真正想要的不是“设备连上来”,而是:
设备异常能不能实时发现?
老人摔倒、离床、心率异常能不能及时告警?
水质异常、管网漏损、设备离线能不能提前预警?
农业传感器数据能不能联动灌溉、施肥、病虫害识别?
门店设备、货架、客流、SKU 和用户行为能不能联动?
设备数据能不能沉淀成画像、模型、规则和商业服务?
这也是很多 IoT 平台从“连接平台”走向“实时运营平台”的原因。
以 C-Life 这类 IoT 平台为例,公开资料里可以看到,它的开放平台覆盖通信模块、协议配置、App / 小程序 / H5、场景联动、AI 场景、时序数据实时窗口分析、设备分析、设备用户分析、APP 用户分析等能力;它的 IoT Cube 私有化方案也强调多协议接入、行业物模型标准接入、百万级设备扩展和并发连接能力。
这背后有一个非常清晰的趋势:
IoT 的价值,不在“数据采集”本身,而在“实时感知 + 实时决策 + 实时动作 + 长期资产沉淀”。
所以,一条好的 IoT 实时链路,必须同时服务三类目标。
第一类是实时目标。比如秒级告警、设备联动、异常识别、工单触发。
第二类是分析目标。比如分钟级看板、设备活跃率、告警趋势、场景效果、用户留存。
第三类是资产目标。比如设备画像、用户画像、场景画像、SKU / 产品能力画像、算法特征、行业知识库。
只满足第一类,会变成烟囱式告警系统。
只满足第二类,会变成普通实时数仓。
只满足第三类,又容易变成“数据资产很漂亮,但业务没感觉”。
真正成熟的 IoT 实时链路,要把三者串起来。
二、技术来龙去脉:从设备上云,到事件驱动,再到实时智能闭环
IoT 实时链路的发展,大概经历了四个阶段。
1. 第一阶段:设备上云
最早的核心诉求很简单:设备能连上平台。
常见能力包括:
设备注册
设备认证
设备在线 / 离线
属性上报
命令下发
远程控制
固件升级
App 控制
这个阶段里,MQTT 非常常见。MQTT 5.0 是 OASIS 标准,它是一个轻量级的客户端-服务端发布/订阅消息传输协议,设计目标就是简单、开放、易实现,适用于 M2M 和 IoT 等受限环境。
这个阶段的重点不是大数据,而是连接稳定性。
2. 第二阶段:设备数据平台化
设备越来越多之后,只能连上来已经不够了。
这时平台开始关注:
设备数据怎么标准化?
不同厂商协议怎么统一?
设备属性、事件、服务怎么建模?
历史数据怎么查?
异常数据怎么处理?
于是出现了“物模型”。
物模型本质上就是给设备建立一个标准语义模型。比如一个空气传感器,有温度、湿度、PM2.5 这些属性;有超标告警、设备故障这些事件;有重启、校准、设置阈值这些服务。
阿里云 IoT 文档中也把物模型概括为属性、事件和服务三类能力,设备与平台之间可以通过物模型实现多场景消息通信。 W3C Web of Things 的 Thing Description 也定义了“Thing”的元数据和接口描述,用来抽象物理或虚拟实体及其交互能力。
这个阶段的重点,是从“协议接入”走向“语义统一”。
3. 第三阶段:实时计算和实时告警
当设备规模变大,业务开始问:
“设备故障能不能 10 秒内发现?”
“水质指标连续 3 分钟异常能不能告警?”
“老人离床超过 15 分钟能不能提醒护理员?”
“设备频繁上下线是不是网络问题?”
“用户打开 App 后设备控制失败率是不是突然升高?”
这时就需要实时计算。
Flink 这类流处理引擎开始进入核心链路。Apache Flink 官方定位是对无界流和有界流做有状态计算的分布式处理引擎,支持事件时间、Exactly-once 状态一致性和迟到数据处理。
这个阶段的重点,是从“数据存起来”走向“数据实时变成判断”。
4. 第四阶段:AIoT、数字孪生和业务闭环
再往后,IoT 链路不只是告警,而是变成业务操作系统:
设备状态 -> 数字孪生
实时事件 -> 风险评分
用户行为 -> 个性化服务
场景数据 -> 自动决策
异常模式 -> 预测性维护
设备 + 用户 + SKU -> 精准运营
AWS IoT Device Shadow 这类能力就是典型思路:即使设备离线,云端也能保存设备状态,让应用和服务仍然可以读取或更新设备状态。 Eclipse Ditto 这类开源框架则把 IoT 设备抽象成云端数字孪生,用虚拟表示来和真实设备交互。
这个阶段的重点,是从“实时处理”走向“实时智能闭环”。
三、一条标准 IoT 实时链路长什么样?
先给一张白板架构图。
这条链路看起来复杂,但本质上只是在回答 6 个问题:
1. 设备怎么安全、稳定、低成本接入?
2. 事件怎么标准化,避免每个设备一套格式?
3. 数据怎么在高峰期不丢、不乱、不堵?
4. 实时计算怎么处理乱序、迟到、状态和窗口?
5. 结果分别落到哪里,支持什么业务查询?
6. 告警和动作怎么做到可解释、可追踪、可闭环?
接下来拆开讲。
四、设备事件进入网关:不要把网关只当“转发器”
很多团队的第一个坑,就是把 IoT 网关理解成消息转发器。
设备发什么,网关就转什么;
协议是什么,后面就接什么;
字段怎么传,平台就怎么存。
这样短期最快,长期一定崩。
因为一旦设备类型多、厂商多、协议多,后面的计算和应用会被拖死。你会看到各种奇怪字段:
temp
temperature
tmp
t
T01
sensor_temp
有的单位是摄氏度,有的是华氏度。
有的时间戳是秒,有的是毫秒。
有的设备离线后补传,有的设备乱序上报。
有的事件表示异常开始,有的事件表示异常结束。
有的字段含义改了,但字段名没改。
所以,IoT 网关至少要做 8 件事。
1. 设备身份认证
每个设备必须有身份。
常见方式包括:
ProductKey / DeviceName / DeviceSecret
X.509 证书
动态注册
网关子设备拓扑
租户 + 产品 + 设备三元组
不要让设备用一个公共 token 上报。那样出了问题,根本追不到是哪台设备、哪个批次、哪个厂商、哪个客户现场。
2. 协议适配
IoT 世界里协议很杂:
MQTT
HTTP
CoAP
WebSocket
TCP 私有协议
Modbus
OPC UA
BLE
Zigbee
LoRa
NB-IoT
4G / 5G
网关要把这些协议转换成平台内部统一事件。
这里要记住一句话:
外部可以多协议,内部必须标准化。
外部多协议是为了兼容设备生态。
内部标准化是为了降低数据计算和应用开发成本。
3. 数据解析
有的设备直接上报 JSON。
有的设备上报二进制。
有的设备上报厂商私有 payload。
有的设备只发寄存器地址和数值。
网关要做解析,但不要把所有业务逻辑都塞到网关里。
比较合理的分层是:
网关负责:协议解析、基础校验、字段映射、单位转换、时间戳修正
实时计算负责:规则判断、窗口聚合、异常识别、复杂模式检测
业务系统负责:工单、通知、用户服务、设备控制策略
4. 限流和削峰
设备一旦批量重连,会非常凶。
比如停电恢复、网络恢复、运营商抖动、固件升级后重启,几十万设备可能同时上线并补传数据。
网关层要有:
连接数限制
单设备 QPS 限制
单租户 QPS 限制
消息大小限制
异常设备隔离
黑名单 / 灰名单
背压保护
否则后面的 Kafka、Flink、数据库都会被打穿。
5. 边缘缓存和断点补传
IoT 设备经常网络不稳定。
尤其是农业、水务、养老院、工业现场、地下室、弱网区域,不能假设设备永远在线。
所以链路要支持:
设备本地缓存
边缘网关缓存
断网补传
补传标识
补传时间范围
重复数据去重
迟到数据处理
这里有个细节:补传数据一定要带设备事件时间,而不是只用平台接收时间。否则 Flink 窗口会算错。
6. 设备影子
设备影子不是必需,但在很多场景非常有用。
设备影子保存的是设备在云端的虚拟状态。设备离线时,应用仍然可以读取它的最后状态,也可以把期望状态写到影子里,等设备上线后同步。AWS IoT Device Shadow 就是这种设计,它可以让设备状态在设备离线时仍然对应用和其他服务可用。
典型场景:
设备离线,但 App 仍然能看到最近状态
用户设置目标温度,设备上线后执行
平台记录 desired / reported 状态差异
设备控制命令有版本号,避免旧命令覆盖新命令
7. 设备拓扑
很多 IoT 场景不是单设备直连,而是:
网关 -> 子设备
边缘盒子 -> 多传感器
控制器 -> 多执行器
园区网关 -> 多楼层设备
这时要管理设备拓扑:
父设备
子设备
设备组
空间位置
产品型号
安装点位
客户项目
服务合同
这些不是“附属信息”,而是实时计算和告警路由的重要维度。
比如同一个温度异常,发生在普通办公室和幼儿园午休室,业务优先级完全不一样。
8. 边缘预处理
不是所有数据都要原封不动打到云端。
边缘侧可以做:
降采样
去噪
本地阈值告警
本地联动
视频 / 图像初步识别
断网自治
低价值数据过滤
但要注意,边缘侧不要做太复杂、太难治理的业务逻辑。否则规则散落在设备、网关、云端三处,后面维护会很痛苦。
一个比较稳的原则是:
边缘做低延迟和降本
云端做统一规则和资产沉淀
五、消息队列:它不是中转站,而是实时链路的“缓冲池”和“重放器”
设备事件进入平台后,下一站一般是消息队列。
Kafka、Pulsar、RocketMQ 都有人用。这里不纠结选型,先讲设计原则。
Kafka 官方把自己定义为分布式事件流平台,用于高性能数据管道、流式分析、数据集成和关键业务应用。 在 IoT 实时链路里,消息队列至少有 5 个作用。
1. 解耦
设备接入层不应该直接写 Flink、OLAP、湖仓、告警系统。
否则任何一个下游慢了,都会反压到设备接入。
正确做法是:
设备接入 -> MQ
实时计算 -> 消费 MQ
时序写入 -> 消费 MQ
湖仓落盘 -> 消费 MQ
告警规则 -> 消费 MQ
离线补偿 -> 消费 MQ
MQ 是中间缓冲带。
2. 削峰
设备上报不是均匀的。
实际情况经常是:
整点批量上报
设备重启批量上报
网络恢复批量补传
活动期间高频上报
异常场景高频告警
MQ 能把尖峰变成下游可承受的消费压力。
3. 保序
很多 IoT 场景需要单设备维度顺序。
比如:
开机 -> 运行 -> 告警 -> 恢复 -> 关机
如果顺序乱了,状态机会错。
通常做法是用 device_id 作为消息 key,让同一设备进入同一个分区。
topic: iot.telemetry.raw
key: device_id
value: event payload
这样可以保证单设备维度相对有序。
注意,是“单设备维度”,不是全局有序。全局有序成本太高,也没必要。
4. 重放
实时链路一定要支持重放。
原因很简单:Flink 任务会改,规则会改,Schema 会改,数据会延迟,业务会复盘。
如果没有重放能力,很多问题只能靠补丁。
有 MQ retention 和湖仓原始明细之后,可以做:
规则重算
告警复盘
算法特征重放
新链路灰度
故障恢复
数据质量修复
5. 多消费者并行
同一份设备事件,可能有多个用途:
实时告警
设备状态更新
时序数据落库
用户行为分析
OLAP 看板
湖仓明细
算法特征
客户数据接口
不要让一条链路承担所有事情。用 MQ 做事件分发,才有扩展性。
六、Topic 怎么设计?别把所有设备事件塞进一个大 Topic
很多平台一开始会建一个 topic:
iot_event
所有数据都往里塞。
短期很方便,长期非常难受。不同类型数据量不同、延迟要求不同、消费逻辑不同、保留周期不同、敏感级别不同,塞在一个 topic 里会让治理变复杂。
比较推荐的做法是按事件大类拆分:
iot.telemetry.raw # 属性 / 遥测数据
iot.event.raw # 业务事件
iot.status.raw # 在线、离线、心跳
iot.command.raw # 命令下发
iot.command.reply.raw # 命令回执
iot.alarm.raw # 设备原始告警
iot.lifecycle.raw # 注册、绑定、解绑、激活、退役
iot.dlq # 死信队列
如果规模更大,可以继续按租户、业务域、产品线拆:
iot.water.telemetry.raw
iot.eldercare.telemetry.raw
iot.agriculture.telemetry.raw
iot.beauty.telemetry.raw
但也不要过度拆。Topic 太多,运维和治理成本会上来。
一般可以按下面几个维度决策:
| 维度 | 是否需要拆 Topic |
|---|---|
| 数据量差异巨大 | 建议拆 |
| 延迟要求不同 | 建议拆 |
| 消费者完全不同 | 建议拆 |
| 安全级别不同 | 建议拆 |
| 保留周期不同 | 建议拆 |
| 只是字段略有不同 | 不一定拆,可用 Schema 区分 |
分区数也要认真设计。
分区太少,消费并行度不够。
分区太多,元数据、连接、文件句柄、rebalance 成本变高。
常见分区 key:
device_id
tenant_id + device_id
product_id + device_id
gateway_id + device_id
我的建议是:大多数遥测数据用 device_id,多租户平台用 tenant_id + device_id,网关型场景要小心 gateway_id 热点。
七、标准物模型:IoT 平台能不能规模化,关键看这一层
IoT 里最难的不是协议,是语义。
同样是“温度”,它可能是:
环境温度
水温
设备内部温度
老人腋下体温
皮肤表面温度
冷链箱温度
电机绕组温度
如果只看字段名 temperature,你根本不知道该怎么判断。
所以要做物模型。
一个实用物模型通常包括:
产品 Product
设备 Device
属性 Property
事件 Event
服务 Service
关系 Relation
空间 Space
场景 Scene
版本 Version
1. 属性:描述设备状态
属性一般是可读、可写或只读的状态。
{
"identifier": "temperature",
"name": "环境温度",
"dataType": "double",
"unit": "℃",
"accessMode": "r",
"min": -40,
"max": 100,
"precision": 1
}
2. 事件:描述已经发生的事情
事件是设备主动上报的业务事实。
{
"identifier": "water_quality_abnormal",
"name": "水质异常",
"eventType": "alert",
"fields": {
"ph": "double",
"turbidity": "double",
"reason": "string"
}
}
3. 服务:描述平台可以调用的能力
服务一般用于控制设备或触发动作。
{
"identifier": "set_threshold",
"name": "设置阈值",
"input": {
"metric": "string",
"threshold": "double"
},
"output": {
"success": "boolean"
}
}
4. 物模型真正解决什么问题?
它至少解决 5 个问题。
第一,统一设备语义。不同厂商设备接进来后,平台内部看到的是统一属性、事件和服务。
第二,降低应用开发成本。应用不用关心原始协议,只关心标准模型。
第三,支持规则和告警配置。规则可以基于物模型字段配置,而不是基于厂商私有字段。
第四,支持数据治理。字段类型、单位、取值范围、版本、Owner 都能管理。
第五,支持跨行业复用。比如水质、空气、能耗、健康、定位、门禁这些模型可以沉淀成行业模板。
一句话:
物模型是 IoT 的数据语义层。没有物模型,实时链路就是一堆 payload;有了物模型,事件才变成可治理、可计算、可复用的数据资产。
八、数据契约:不要让设备“想怎么发就怎么发”
物模型偏业务语义,数据契约偏工程约束。
一个设备事件进入实时链路之前,必须说清楚:
事件名称是什么?
字段有哪些?
字段类型是什么?
哪些字段必填?
时间戳来自哪里?
单位是什么?
Schema 版本是什么?
兼容规则是什么?
谁是生产者?
谁是消费者?
SLA 是什么?
数据质量规则是什么?
这就是数据契约。
CloudEvents 给事件元数据提供了一种通用描述方式,它的目标是在服务、平台和系统之间用共同格式描述事件。(GitHub) AsyncAPI 则用于用机器可读格式描述消息驱动 API,并且是协议无关的,可以用于 MQTT、Kafka、WebSocket、HTTP 等协议。(AsyncAPI) Schema Registry 的设计思想也很关键:Schema 像 API 一样,生产者和消费者依赖它,变更时需要兼容性检查,避免破坏下游应用。(Confluent 文档)
一个 IoT 事件可以设计成这样:
{
"specversion": "1.0",
"id": "evt_20260508_000001",
"type": "com.company.iot.telemetry.reported",
"source": "/tenant/t001/product/air_sensor/device/d10001",
"subject": "temperature",
"time": "2026-05-08T10:15:30.123Z",
"datacontenttype": "application/json",
"dataschema": "iot.telemetry.v1.2.0",
"tenant_id": "t001",
"product_id": "air_sensor",
"device_id": "d10001",
"gateway_id": "gw_001",
"trace_id": "trace_abc",
"data": {
"metric": "temperature",
"value": 31.6,
"unit": "C",
"event_time": 1778235330123,
"ingest_time": 1778235331120,
"seq": 102938,
"quality": "good"
}
}
这里有几个字段非常关键。
event_time 是设备事件发生时间。
ingest_time 是平台接收时间。
seq 是设备侧序列号,用于去重和乱序判断。
dataschema 是契约版本。
trace_id 用于全链路追踪。
quality 用于标记数据质量,比如 good、late、duplicated、invalid。
契约变更要有规矩
IoT 设备生命周期很长,很多设备一跑就是几年。你不可能要求所有设备同一天升级协议。
所以 Schema 变更要遵循兼容规则。
通常允许:
新增可选字段
新增字段带默认值
放宽枚举值
新增事件类型
通常不允许:
删除必填字段
修改字段类型
修改字段单位但不改版本
改变字段语义但字段名不变
修改时间戳含义
最危险的是“字段名没变,语义变了”。
比如原来 status=1 表示在线,后来某个厂商改成 status=1 表示运行中。平台如果没有版本管理,后面所有统计都会错。
九、Flink 实时计算:窗口只是表面,核心是事件时间、状态和一致性
很多人写 Flink 窗口时只关注:
Tumbling Window
Sliding Window
Session Window
但在 IoT 场景里,真正要关注的是:
事件时间
水位线
乱序
迟到
状态
Checkpoint
幂等输出
1. 为什么不能只用处理时间?
处理时间是平台收到数据的时间。
事件时间是设备真实发生事件的时间。
在 IoT 场景里,设备可能离线后补传,也可能网络延迟,也可能边缘网关缓存后再发。
如果只用处理时间,会出现这种问题:
设备 10:00 发生温度异常
设备 10:08 网络恢复后补传
平台按 10:08 计算
结果 10:00-10:05 的异常窗口被漏算
所以实时计算要优先基于事件时间。
Flink 用 Watermark 来衡量事件时间进展。官方文档里说,Watermark 会随着数据流动,并携带一个时间戳 t,表示事件时间已经推进到 t;这意味着系统认为不会再有时间戳小于等于 t 的事件到达。
简单理解:
Watermark 是 Flink 对“我等迟到数据等到什么时候”的判断。
2. 窗口怎么选?
常见窗口有三类。
滚动窗口
固定时间切片,不重叠。
每 1 分钟统计一次设备平均温度
每 5 分钟统计一次设备在线率
适合周期统计。
滑动窗口
窗口重叠,按滑动步长输出。
最近 5 分钟,每 1 分钟计算一次水质异常趋势
最近 10 分钟,每 30 秒计算一次设备故障率
适合趋势和连续监控。
会话窗口
根据事件间隔自动切分。
用户一次设备控制会话
设备一次异常持续过程
老人一次离床活动
适合行为分析。
Flink 的窗口触发可以基于事件时间、处理时间、计数等条件,事件时间触发依赖 Watermark 推进。
3. 迟到数据怎么处理?
IoT 迟到数据是常态,不是异常。
常见策略:
轻微迟到:允许进入窗口修正
严重迟到:进入侧输出流
超期迟到:写入补偿链路
比如:
0-2 分钟迟到:正常参与窗口计算
2-30 分钟迟到:进入 late_event 流,更新明细和补偿指标
超过 30 分钟:只入湖仓,不触发实时告警
为什么超过一定时间不触发实时告警?
因为实时告警是为了当下处理。
昨天补传的“温度异常”再发短信,可能已经没有业务意义,甚至会造成误扰。
所以迟到数据要分业务场景处理。
4. 状态计算是 IoT 实时链路的灵魂
很多 IoT 规则不是单条事件能判断的。
比如:
连续 3 次心率异常
10 分钟内设备上下线超过 5 次
水质 PH 连续 5 分钟超过阈值
老人离床超过 15 分钟未返回
设备温度持续上升且风扇未启动
这些都需要状态。
Flink 的有状态计算可以记住历史事件,用状态来影响后续判断。Flink 的 Checkpoint 机制则可以在故障恢复时恢复算子状态和输入流位置,从而维持一致性;官方文档也提到 Exactly-once 通常适合大多数应用,而 At-least-once 可以用于极低延迟场景。
5. 一个 Flink SQL 示例
假设我们要做一个规则:同一设备 5 分钟内平均温度超过 35℃,触发高温告警。
CREATE TABLE iot_telemetry (
tenant_id STRING,
product_id STRING,
device_id STRING,
metric STRING,
value DOUBLE,
event_time TIMESTAMP(3),
WATERMARK FOR event_time AS event_time - INTERVAL '30' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'iot.telemetry.raw',
'properties.bootstrap.servers' = 'kafka:9092',
'format' = 'json'
);
CREATE TABLE iot_alarm (
tenant_id STRING,
product_id STRING,
device_id STRING,
alarm_type STRING,
alarm_level STRING,
alarm_value DOUBLE,
window_start TIMESTAMP(3),
window_end TIMESTAMP(3),
created_at TIMESTAMP(3)
) WITH (
'connector' = 'kafka',
'topic' = 'iot.alarm.detected',
'format' = 'json'
);
INSERT INTO iot_alarm
SELECT
tenant_id,
product_id,
device_id,
'temperature_high' AS alarm_type,
'P1' AS alarm_level,
AVG(value) AS alarm_value,
window_start,
window_end,
CURRENT_TIMESTAMP AS created_at
FROM TABLE(
TUMBLE(TABLE iot_telemetry, DESCRIPTOR(event_time), INTERVAL '5' MINUTE)
)
WHERE metric = 'temperature'
GROUP BY tenant_id, product_id, device_id, window_start, window_end
HAVING AVG(value) > 35;
这个例子很简单,但生产上还要加很多东西:
阈值不是写死的,要从规则配置表读取
不同设备型号阈值不同
不同客户、不同场景阈值不同
异常要去重,不要每分钟狂发
告警要有恢复事件
告警要有抑制、升级、合并
输出要幂等
6. CEP:处理“事件序列”而不是单点阈值
有些规则不是简单聚合,而是事件模式。
比如:
设备故障 -> 维修命令下发 -> 10 分钟内没有恢复
老人离床 -> 15 分钟未回床 -> 夜间高风险
水质异常 -> 加药设备未启动 -> 继续恶化
门店客流升高 -> 智能货架缺货 -> SKU 补货提醒
这就适合 CEP。
FlinkCEP 是 Flink 上的复杂事件处理库,可以在无界事件流中检测事件模式。
注意,CEP 不要滥用。
简单阈值和窗口聚合,用普通 Flink 就够了。
CEP 适合“有顺序、有时间约束、有多个事件组合”的场景。
十、结果到底落哪里?时序库、OLAP、湖仓不是三选一
很多架构评审会上,大家会争:
“实时数据落 ClickHouse 就够了吧?”
“是不是该上时序库?”
“湖仓是不是太重?”
“Doris 能不能替代所有东西?”
我的观点比较明确:
IoT 实时链路里,时序库、OLAP、湖仓不是替代关系,而是服务不同查询模式。
1. 时序库:服务设备级时间序列查询
时序库适合:
单设备历史曲线
多测点时间对齐
传感器数据下钻
按时间范围查询
降采样
设备状态趋势
Apache IoTDB 官方定位就是工业 IoT 时序数据库管理系统,支持边云协同,面向 IoT 时序数据的采集、存储、管理和分析。
典型查询:
查看某台水质传感器过去 24 小时 PH 曲线
查看某个养老房间过去一晚的离床传感器状态
查看某台设备温度、湿度、电压的时间对齐变化
时序库的核心优势是时间维度的高频写入、压缩和曲线查询。
2. OLAP:服务聚合分析和运营看板
OLAP 适合:
设备在线率
告警趋势
客户项目对比
区域分布
用户活跃
App 控制成功率
设备故障 TopN
SKU 使用效果
ClickHouse 官方把自己描述为面向 OLAP 的高性能列式 SQL 数据库,也强调可以实时生成分析报表。
典型查询:
SELECT
product_id,
countIf(status = 'online') / count(*) AS online_rate,
countIf(alarm_level = 'P1') AS p1_alarm_count
FROM device_status_wide
WHERE dt = today()
GROUP BY product_id
ORDER BY p1_alarm_count DESC;
OLAP 的优势是多维分析、聚合性能、报表体验。
3. 湖仓:服务明细留存、回放、训练和治理
湖仓适合:
原始明细长期留存
实时链路重放
离线宽表加工
算法训练样本
特征工程
审计追溯
Schema 演进
跨引擎查询
Iceberg 这类表格式的核心价值之一就是 Schema 演进和分区演进。官方文档提到,Iceberg 支持像 SQL 一样演进表 Schema,甚至支持嵌套结构,分区布局也可以随数据量变化调整,而不需要昂贵地重写整表。
IoT 场景里,设备型号会变、字段会变、协议会变、算法特征会变,所以湖仓的 Schema 演进能力很重要。
4. 一个推荐的数据落地模型
原始事件:
Kafka -> Lakehouse ODS
用于回放、审计、补偿、训练
清洗标准事件:
Flink -> Lakehouse DWD
用于统一明细、血缘、治理
设备最新状态:
Flink -> Redis / KV / Device Shadow
用于 App、控制台、规则判断
设备时序数据:
Flink / Connector -> IoTDB / InfluxDB
用于曲线、下钻、时间序列分析
实时聚合结果:
Flink -> ClickHouse / Doris
用于运营看板、客户报表、项目大屏
告警事件:
Flink -> Kafka -> 告警服务 / 工单系统
用于业务动作闭环
算法特征:
Flink -> Feature Store / Lakehouse
用于模型训练和在线推理
这套设计不是最省组件的,但职责清楚。
最怕的是把所有东西都塞进一个数据库。
一开始看起来省事,后面查询慢、成本高、扩展差、治理乱。
十一、告警和业务动作:别让实时链路止步于“发一条消息”
很多 IoT 实时链路做到告警就停了。
比如:
检测到异常 -> 发短信
检测到离线 -> 发通知
检测到超标 -> 写告警表
这只能算半条链路。
真正的实时闭环应该是:
检测异常
-> 生成告警
-> 判断等级
-> 去重合并
-> 找到责任人
-> 触发通知 / 工单 / 设备控制
-> 跟踪处理状态
-> 判断是否恢复
-> 复盘和优化规则
1. 告警不是越多越好
IoT 平台很容易告警泛滥。
比如一台设备 5 分钟上报 300 条异常,如果每条都发通知,业务方很快就麻木了。
告警系统要做:
去重
合并
抑制
升级
恢复
静默
值班路由
责任人路由
例子:
同一设备、同一告警类型,10 分钟内只生成一条主告警
如果 30 分钟未恢复,从 P2 升级到 P1
如果同一区域 100 台设备同时离线,合并成区域网络故障
如果设备处于维护期,告警静默但保留记录
2. 告警要分级
不是所有异常都要立即打扰人。
P0:人身安全、重大损失、监管风险
P1:关键设备故障、核心服务异常
P2:普通设备异常、可延迟处理
P3:趋势风险、运营提醒
比如养老场景里,老人摔倒是 P0。
水务场景里,水质指标严重超标可能是 P0 / P1。
设备电量低可能只是 P3。
3. 业务动作要幂等
实时链路最容易忽略幂等。
Flink 可能重启,消息可能重放,告警可能重复输出。
如果动作不幂等,就会出现:
重复发短信
重复派工单
重复扣费
重复下发设备命令
重复触发营销
每个动作都应该有业务幂等键。
alarm_id = hash(tenant_id + device_id + alarm_type + window_start)
work_order_id = hash(alarm_id + action_type)
command_id = hash(device_id + command_type + command_version)
下游服务看到同一个幂等键,要能识别重复请求。
4. 设备控制要谨慎
从实时链路触发设备控制时,要特别注意安全。
比如:
检测到温度高 -> 打开风扇
检测到水质异常 -> 启动加药设备
检测到老人离床 -> 打开夜灯
检测到空气质量差 -> 打开新风
这些动作看起来智能,但也有风险。
如果传感器误报,或者规则配置错,可能造成反效果。
所以自动控制要设计保护机制:
动作白名单
阈值上下限
人工确认
灰度规则
最大触发频率
设备能力校验
反向恢复条件
安全熔断
一句话:
告警可以激进一点,控制要保守一点。
十二、实时链路的关键技术原则
下面这些原则,比选什么组件更重要。
1. 设备事件必须有唯一 ID
没有唯一 ID,就很难去重。
推荐:
event_id = tenant_id + device_id + seq + event_time + event_type
如果设备没有 seq,可以平台生成,但最好推动设备侧提供序列号。
2. 必须区分事件时间和接收时间
event_time:设备真实发生时间
ingest_time:平台接收时间
process_time:Flink 处理时间
sink_time:写入目标系统时间
这几个时间都要保留。
否则排查延迟时,你不知道慢在哪里。
3. 先保证单设备顺序,不追求全局顺序
全局顺序代价高,而且业务上大多不需要。
单设备顺序更重要。
4. 所有外部输出都要幂等
告警、工单、通知、命令、营销动作,都要幂等。
5. 规则配置要版本化
实时规则不能只有当前版本。
要记录:
规则 ID
规则版本
生效时间
失效时间
发布人
审批人
灰度范围
命中的数据
否则告警复盘时,你不知道当时到底是哪条规则触发的。
6. 原始事件必须留存
不要只存清洗后的数据。
原始事件用于:
故障排查
数据回放
协议解析修复
算法训练
审计追踪
客户争议处理
7. 迟到数据要有业务策略
不要简单丢弃,也不要一股脑修正所有结果。
要区分:
实时告警是否还触发
聚合指标是否修正
湖仓明细是否保留
是否进入补偿任务
是否标记 late
8. 死信队列必须有
解析失败、Schema 不兼容、字段越界、非法设备、异常 payload,都要进死信队列。
死信队列不是垃圾桶,它是数据质量入口。
9. 物模型要和主数据打通
设备数据不是孤立的。
实时计算经常需要关联:
设备主数据
产品型号
SKU 信息
客户项目
安装位置
空间层级
服务合同
责任人
规则配置
阈值配置
如果这些主数据不准确,实时规则也会错。
10. 实时链路要可观测
OpenTelemetry 是一个厂商中立的开源可观测性框架,用于生成、采集和导出 traces、metrics、logs 等遥测数据。 Prometheus 的告警体系则把告警规则和 Alertmanager 分开,Alertmanager 负责静默、抑制、聚合和通知。
IoT 实时链路至少要监控:
设备连接数
设备在线率
消息进入速率
MQ backlog / consumer lag
Flink 输入 QPS
Flink 输出 QPS
端到端延迟
Watermark 延迟
Checkpoint 时长和失败次数
反压情况
死信数量
异常设备 TopN
告警触发量
动作成功率
命令回执延迟
Flink 本身也提供反压监控,官方文档提到,如果任务出现 High back pressure,说明上游生产速度超过下游消费能力;Flink metrics 里 checkpointStartDelayNanos 等指标也可以提示反压或数据倾斜。
十三、一个端到端案例:水质监控实时链路
假设我们做一个智慧水生态场景。
设备包括:
PH 传感器
浊度传感器
余氯传感器
水温传感器
水泵控制器
加药设备
边缘网关
业务目标:
水质异常 30 秒内发现
连续异常 5 分钟触发 P1 告警
自动生成工单
必要时联动加药设备
报表展示各区域水质趋势
湖仓沉淀算法训练样本
1. 设备上报
{
"tenant_id": "water_001",
"product_id": "water_sensor_v2",
"device_id": "ph_10001",
"metric": "ph",
"value": 9.2,
"unit": "PH",
"event_time": 1778235330123,
"seq": 8891
}
2. 网关处理
认证设备
解析 payload
校验字段
转换单位
补齐租户、产品、项目、点位
写入 Kafka:iot.water.telemetry.raw
3. Flink 清洗
去重
过滤非法值
关联设备主数据
标记数据质量
写入标准明细流:iot.water.telemetry.dwd
4. Flink 窗口计算
按设备 1 分钟滚动窗口计算平均值
按站点 5 分钟滑动窗口计算异常持续时间
按区域 15 分钟窗口计算异常设备比例
5. 告警判断
单点 PH 超阈值:P3
连续 5 分钟超阈值:P1
同一站点多指标异常:P0 / P1
同一区域多设备同时异常:区域级事件
6. 结果落地
原始数据 -> 湖仓 ODS
标准明细 -> 湖仓 DWD
时序曲线 -> IoTDB
实时看板 -> ClickHouse / Doris
告警事件 -> Kafka + 告警服务
工单 -> 工单系统
设备控制 -> IoT Command Topic
7. 业务闭环
告警生成
-> 通知值班人员
-> 自动派单
-> 判断是否需要远程控制
-> 设备执行命令
-> 回执确认
-> 指标恢复
-> 告警关闭
-> 复盘规则准确率
这个案例里,实时链路的价值不是“算了一个窗口”,而是把设备、数据、规则、人和业务动作串起来。
十四、业内最佳实践:成熟 IoT 实时平台通常会这样做
1. 接入层和计算层解耦
设备接入网关只负责连接、认证、协议和基础校验,不要把大量业务规则塞进去。
2. 物模型先行
没有物模型,后续的数据契约、规则引擎、告警、报表、画像都会变成定制开发。
3. 数据契约版本化
每个事件都要有 Schema 版本。
每次变更都要做兼容性检查。
下游消费者要知道自己消费的是什么版本。
4. 原始数据和标准数据都要保留
原始数据用于追溯和重放。
标准数据用于分析和服务。
两者不要互相替代。
5. 实时链路和离线链路共用一套语义
实时指标和离线指标不要各算各的。
比如“设备在线率”,实时看板和日报口径必须一致,否则业务方会质疑整个平台。
6. 规则和模型分层
简单阈值用规则。
趋势判断用窗口。
事件序列用 CEP。
复杂异常用模型。
不要所有问题都上 AI,也不要所有问题都写死规则。
7. 告警要闭环
只发通知不算闭环。
必须有确认、派单、处理、恢复、关闭和复盘。
8. 多租户隔离
IoT 平台常常服务多个客户项目。
要隔离:
设备
数据
规则
告警
用户
权限
报表
API
模型
9. 边云协同
弱网和低延迟场景,要把一部分能力放到边缘。
但边缘规则要可管理、可下发、可回收、可审计。
10. 可观测性从第一天做
实时链路最怕“看起来没挂,但业务说没数据”。
必须能快速回答:
数据有没有进来?
卡在哪一层?
延迟是多少?
哪个 Topic 堵了?
哪个 Flink 算子反压?
哪个 Sink 写不动?
哪些设备异常?
哪些规则暴涨?
十五、常见坑:这些问题比技术选型更致命
坑 1:设备字段不标准,后面全靠人肉适配
一开始省了物模型,后面会在每个项目里还债。
坑 2:只存平台接收时间,不存设备事件时间
补传数据、弱网数据、乱序数据全都会算错。
坑 3:所有数据进一个 Topic
后续权限、消费、保留周期、性能调优都会很痛苦。
坑 4:Flink 只算窗口,不管状态和恢复
任务一重启,告警重复、状态丢失、数据不一致。
坑 5:告警不去重
业务方被告警轰炸后,会直接不看系统。
坑 6:实时结果直接写数据库,没有幂等
任务重放或失败恢复后,重复数据一堆。
坑 7:没有死信队列
解析失败的数据直接丢,后面没人知道发生过什么。
坑 8:规则没有版本
复盘时不知道当时哪条规则生效,也无法解释为什么触发。
坑 9:实时和离线口径不一致
看板一个数,日报一个数,业务方最后谁都不信。
坑 10:把 AI 当万能异常检测
AI 可以做异常识别,但前提是数据质量、标签、样本、反馈闭环都跟得上。否则模型只是一个更难解释的规则。
十六、对业界的影响:IoT 实时链路正在改变数据平台的形态
传统数据平台的核心是:
采集 -> 存储 -> 计算 -> 报表
IoT 实时平台的核心是:
感知 -> 判断 -> 动作 -> 反馈 -> 学习
这两个范式不一样。
传统数据平台偏“事后分析”。
IoT 实时平台偏“在线运营”。
这会带来几个行业变化。
1. 数据平台从报表中心变成业务操作系统
以前数据平台主要服务管理层和分析师。
现在 IoT 实时平台直接参与业务动作,比如告警、工单、设备控制、客户服务、风险干预。
这意味着数据平台不再只是“看数”,而是“干活”。
2. 设备厂商会越来越重视数据契约
设备厂商过去拼硬件参数。
未来还要拼数据标准、协议开放、模型兼容、事件质量、远程诊断能力。
谁的数据更标准,谁就更容易接入生态。
3. 行业平台会沉淀自己的物模型资产
智慧养老有养老物模型。
智慧水务有水质、水压、管网物模型。
智慧农业有土壤、气象、灌溉、病虫害物模型。
智慧美业有人、货、场、皮肤、设备、SKU 模型。
这些模型不是普通配置,而是行业 Know-how。
4. 实时数据会推动服务模式变化
企业可以从卖硬件,变成卖服务。
比如:
设备订阅服务
预测性维护
远程运维
按效果付费
安全监控服务
行业数据服务
AI 运营服务
麦肯锡曾预测,到 2030 年 IoT 的全球经济价值潜力可能达到 5.5 万亿到 12.6 万亿美元,前提之一就是企业能真正规模化捕获 IoT 价值,而不仅是做局部试点。
5. AI Agent 会进入物理世界
未来很多 Agent 不只是读文档、查数据库,而是会读设备状态、理解场景、调用工具、触发动作。
Gartner 在 2026 年数据与分析预测里提到,到 2029 年,AI Agent 从物理环境中生成的数据量可能会达到所有数字 AI 应用生成数据量的 10 倍。
这对 IoT 实时链路是巨大机会,也意味着更高要求:
Agent 能访问哪些设备数据?
能不能控制设备?
控制动作是否需要审批?
模型判断错了怎么办?
所有动作是否可追踪?
未来 IoT 实时链路会成为 Physical AI 和行业 Agent 的数据底座。
十七、商业价值:为什么老板愿意为 IoT 实时链路买单?
技术团队讲架构,业务团队听的是价值。
一条成熟的 IoT 实时链路,至少能产生 6 类商业价值。
1. 降低运维成本
设备离线、故障、异常提前发现,远程诊断、远程处理,减少现场巡检和人工排查。
2. 提升服务 SLA
养老、水务、工业、教育这些场景里,响应速度就是服务质量。实时链路能把“事后发现”变成“实时处理”。
3. 增强客户粘性
客户一旦依赖你的实时监控、告警、报表、工单和预测服务,就不只是买设备,而是在使用平台能力。
4. 形成数据产品
设备数据可以变成:
运营看板
客户报告
行业指数
风险评分
设备健康分
服务质量报告
预测性维护报告
这些都可以产品化。
5. 支撑 AI 和算法
没有高质量实时数据,AI 就没有可靠输入。
IoT 实时链路能持续沉淀:
异常样本
行为序列
设备状态
环境上下文
处理反馈
模型标签
这些是算法资产。
6. 支撑新商业模式
比如:
硬件 + SaaS
硬件 + 运维服务
数据订阅
行业智能服务
按设备规模收费
按告警处理量收费
按节能效果分成
IoT 实时链路做得好,平台就不只是成本中心,而是收入入口。
十八、未来潜力:IoT 实时链路会往哪里走?
1. 更强的边缘实时计算
不是所有数据都回云端算。
未来会有更多计算下沉到边缘:
视频分析
本地告警
低延迟控制
断网自治
本地模型推理
边缘特征计算
云端负责统一治理、模型训练、策略下发和全局分析。
2. 实时湖仓会成为标配
以前实时和离线是两套链路。
以后会越来越强调流批一体、实时入湖、实时特征、实时指标。
湖仓不只是存数据,而是承接:
明细留存
Schema 演进
数据治理
模型训练
回放补偿
跨引擎分析
3. 数字孪生会从展示走向控制
很多数字孪生项目停留在大屏展示。
未来更有价值的是:
孪生状态实时更新
孪生规则驱动控制
孪生模拟预测风险
孪生反馈优化设备策略
也就是从“看起来很酷”走向“真的能干活”。
4. IoT 数据治理会越来越重要
设备越多,数据越乱。
未来 IoT 平台竞争力会体现在:
物模型治理
数据契约治理
主数据治理
规则治理
告警治理
权限治理
血缘治理
质量治理
成本治理
谁能把数据治理好,谁就能把平台做大。
5. Agent 会成为 IoT 平台的新交互入口
以后用户可能不会再点复杂菜单,而是直接问:
昨天哪些养老房间夜间离床异常最多?
帮我查一下 3 号水厂 PH 波动原因。
这个设备为什么频繁离线?
给我生成本周设备健康报告。
把高风险告警按责任人分派出去。
Agent 背后调用的,就是实时链路、OLAP、时序库、湖仓、规则系统和工单系统。
所以未来的 IoT 实时链路,不只是给人看,也要给 Agent 用。
十九、落地路线:90 天怎么把一条 IoT 实时链路做起来?
第 1 阶段:0-30 天,先统一标准和入口
目标:别急着堆组件,先把数据进来的姿势统一。
要做:
盘点设备类型、协议、数据量、上报频率
梳理产品、设备、客户、项目、点位主数据
定义第一版物模型
定义事件 Schema 和数据契约
设计 Topic 规范
搭建接入网关和标准事件流
建立死信队列和基础监控
产出:
设备接入规范
物模型模板
事件 Schema
Topic 规划
标准事件样例
接入链路监控
第 2 阶段:30-60 天,跑通实时计算和告警 MVP
目标:让业务看到价值。
要做:
Flink 清洗标准事件
实现设备状态更新
实现 3-5 个核心实时窗口指标
实现核心告警规则
打通告警通知和工单
落时序库和 OLAP
建立延迟、反压、死信监控
产出:
实时设备状态
实时告警 MVP
设备曲线查询
核心运营看板
告警闭环流程
第 3 阶段:60-90 天,平台化和治理化
目标:从项目链路变成平台能力。
要做:
规则配置化
物模型版本化
数据契约兼容检查
多租户权限隔离
湖仓原始明细留存
迟到数据补偿机制
告警去重、合并、升级
规则命中分析和复盘
产出:
规则平台
物模型管理
数据契约管理
实时湖仓链路
告警治理能力
多租户数据隔离
90 天之后:做智能化和商业化
长期方向:
设备健康评分
预测性维护
异常检测模型
数字孪生
行业画像
Agent 查询和处置
客户级数据产品
按服务价值收费
二十、最后总结:IoT 实时链路的本质,是把物理世界变成可计算、可行动的系统
设计 IoT 实时链路,不要只盯着 Kafka、Flink、ClickHouse、IoTDB 这些组件。
组件只是手段。
真正要设计的是:
设备怎么接入
数据怎么标准化
事件怎么契约化
计算怎么实时化
存储怎么分层化
告警怎么闭环化
动作怎么安全化
资产怎么沉淀化
一句话总结:
IoT 实时链路不是“设备数据进来后算一下”,而是把物理世界的状态、事件和行为,转成平台可理解、可计算、可追踪、可决策、可行动的数据系统。
如果只做采集,它是管道。
如果只做报表,它是看板。
如果能从设备事件一路走到业务动作,再把结果沉淀成数据资产,它才是一个真正有商业价值的 IoT 实时平台。
附:架构师检查清单
| 模块 | 必查问题 |
|---|---|
| 设备接入 | 是否有设备身份、认证、限流、协议适配、补传机制? |
| 网关 | 是否完成解析、标准化、单位转换、时间戳修正? |
| 消息队列 | Topic 是否按数据类型拆分?是否支持保序、削峰、重放、死信? |
| 物模型 | 是否定义产品、设备、属性、事件、服务和版本? |
| 数据契约 | 是否有 Schema、必填字段、兼容规则、Owner、SLA? |
| Flink | 是否使用事件时间、水位线、状态、Checkpoint、迟到处理? |
| 存储 | 是否区分时序库、OLAP、湖仓和设备最新状态? |
| 告警 | 是否支持去重、合并、抑制、升级、恢复、闭环? |
| 动作 | 通知、工单、设备控制是否幂等、可追踪、可熔断? |
| 治理 | 是否有主数据、血缘、质量、权限、成本和审计? |
| 可观测 | 是否能看到端到端延迟、MQ lag、Flink 反压、死信、动作成功率? |
| 商业价值 | 是否能支撑运维降本、服务 SLA、数据产品、AI 和新商业模式? |
参考资料
- OASIS MQTT Version 5.0 标准:MQTT 是轻量级发布/订阅消息传输协议,适用于 M2M 和 IoT 受限环境。(OASIS Open)
- Apache Kafka 官方介绍:Kafka 是分布式事件流平台,用于高性能数据管道、流式分析、数据集成和关键业务应用。(Apache Kafka)
- Apache Flink 官方文档:Flink 是面向无界流和有界流的有状态计算引擎,支持事件时间、Exactly-once 状态一致性和迟到数据处理。(Flink)
- Apache Flink Event Time / Watermark 文档:Watermark 用于衡量事件时间进展。(Apache Nightlies)
- Apache Flink Window 和 Checkpoint 文档:窗口触发、Exactly-once、At-least-once 和 Checkpoint 配置。(Apache Nightlies)
- FlinkCEP 官方文档:用于在无界事件流中检测复杂事件模式。(Apache Nightlies)
- W3C Web of Things Thing Description 1.1:定义 Thing 的元数据和接口描述。(W3C)
- 阿里云 IoT 物模型文档:物模型包括属性、事件和服务。(阿里云帮助中心)
- CloudEvents 规范:用通用格式描述事件数据,提升跨服务、平台和系统的互操作性。(GitHub)
- AsyncAPI 规范:用于以机器可读方式描述消息驱动 API,并支持多种协议。(AsyncAPI)
- Confluent Schema Registry 文档:Schema 像 API 一样需要兼容性检查,避免破坏生产者和消费者契约。(Confluent 文档)
- Apache IoTDB 官方介绍:面向工业 IoT 的时序数据库,支持边云协同和 IoT 时序数据管理分析。(IoTDB Website)
- ClickHouse 官方介绍:面向 OLAP 的高性能列式 SQL 数据库,可用于实时分析报表。(ClickHouse)
- Apache Iceberg 官方文档:支持 Schema 演进和分区演进,避免昂贵的整表重写。(冰山)
- OpenTelemetry 官方文档:厂商中立的可观测性框架,用于 traces、metrics、logs。(OpenTelemetry)
- Prometheus Alerting 文档:Alertmanager 支持告警静默、抑制、聚合和通知。(prometheus.io)
- C-Life 开放平台和 IoT Cube 资料:涉及多协议、物模型、实时窗口分析、设备分析、场景联动和私有化 IoT 平台能力。(clife.cn)
- McKinsey IoT 价值研究:2030 年 IoT 全球经济价值潜力可能达到 5.5 万亿到 12.6 万亿美元。(McKinsey & Company)
- Gartner 2026 数据与分析预测:到 2029 年,AI Agent 从物理环境中生成的数据量可能显著超过数字 AI 应用。(gartner.com)