物联网设备一多,数据就像一锅粥,每个业务部门都想要自己那一份。AWS IoT Core 的规则引擎正好能帮你把这锅粥分好,让每碗都送到该去的地方。今天我们就用一个温度传感器的例子,把“多分支条件路由”这件事讲透。
规则引擎听起来很高大上,其实可以把它想象成一个“快递分拣台”:设备把数据放到一个主题(Topic)上,分拣台根据你写好的规则,把数据扔到不同的传输带上。传输带的尽头可能就是存储服务、告警服务,或者另一个主题。
在规则引擎里,有四个核心东西得认识一下。第一个是规则本身,它描述“在什么情况下做哪些事”。第二个是SQL语句,它用来从主题里挑数据、选字段、加过滤条件,跟数据库查询很像。第三个是动作,就是分拣后的出口,比如写进DynamoDB、调用Lambda、发到SNS。第四个是角色,也就是身份证,规则引擎要访问别的服务,必须用角色来证明自己有权限。
一、规则引擎到底是个啥?
规则引擎是 AWS IoT Core 自带的一项托管功能,不需要你维护任何服务器。只要设备往约定的主题上发消息,规则引擎就会按照你写的 SQL 去抓取消息,再交给后面的动作处理。这个过程是异步的,设备侧不会因为规则执行慢而卡住。
1.1 核心名词
- 规则(Rule):一条完整的处理逻辑,包括 SQL 和动作。
- SQL 语句:决定“拿哪些消息,取哪些字段,过滤哪些条件”。
- 动作(Action):表示“数据送到哪”,例如 SNS、S3、DynamoDB、Lambda、另一个主题等。
- IAM 角色(Role):规则引擎用来访问目标服务所必需的授权凭证。
二、什么时候需要“多分支”?
最常见的就是设备数据有紧急和普通之分。比如温度超过四十度,就需要马上报警;温度正常,存起来就行。还有一种情况是不同设备的型号不同,有的数据要送给 A 系统,有的要送到 B 系统。另外,有时候既要保存全量原始数据用于分析,又要抽取关键字段做实时业务,这也需要分流。
如果只有一台设备、一种数据格式、数据只会发给一个服务,那么根本不需要多分支。但真实项目中,设备种类多、业务部门多、数据用途多,这时候“多分支条件路由”就成了刚需。它能让一条数据流同时满足多个消费方,而不需要设备端重复上报。
三、动手前的准备
写规则之前,需要准备好 AWS 账号,并且创建一个 IoT 设备。设备要下载证书、安装 SDK,然后能往主题里发数据。为了方便演示,我们假设设备上报的数据长这样:一个 JSON 对象,里面有设备 ID、温度、湿度、时间戳。这个格式很重要,因为 SQL 语句要从 JSON 里取字段,所有字段都要在数据里真实存在。
例如设备会往 device/device1/data 这个主题发送:
{
"deviceId": "device1",
"temperature": 45,
"humidity": 30,
"timestamp": 1700000000
}
你需要在 AWS IoT 控制台注册这个设备,并记录它的证书和私钥。当然,规则引擎本身并不关心设备怎么连接,它只负责处理已经进入消息代理的数据。
四、先跑通一条最简单的规则
我们先从最简单的单规则开始。假设我想把设备上报的数据全部存到 DynamoDB,只需要一条规则。SQL 是 SELECT deviceId, temperature, humidity, timestamp FROM "device/+/data"。注意,主题筛选器可以用 + 和 # 通配符,+ 代表一层任意内容,这里用来匹配任意设备 ID。动作选用 DynamoDB 的插入操作,指定表名和角色。
下面是创建这条规则的命令行示例。技术栈是 AWS CLI 加 JSON 规则定义。首先我们把规则定义写到一个临时文件里,再调用 create-topic-rule 命令。
# 技术栈:AWS CLI + JSON 规则定义
# 生成一条最简单的规则:把设备消息写入 DynamoDB
cat > /tmp/rule_basic.json <<'EOF'
{
"sql": "SELECT deviceId, temperature, humidity, timestamp FROM \"device/+/data\"",
"actions": [
{
"dynamoDB": {
"tableName": "device_data",
"hashKeyField": "deviceId",
"hashKeyValue": "${deviceId}",
"rangeKeyField": "timestamp",
"rangeKeyValue": "${timestamp}",
"operation": "INSERT",
"roleArn": "arn:aws:iam::123456789012:role/iot-rule-role"
}
}
]
}
EOF
# 在 AWS 上创建这条规则
aws iot create-topic-rule \
--rule-name "save-all-device-data" \
--topic-rule-payload file:///tmp/rule_basic.json
如果你在控制台操作,可以在“规则”页面新建规则,把 SQL 粘贴进去,再选择动作。控制台还带一个“测试”按钮,可以模拟一条消息,验证 SQL 是否匹配。这对初学者很友好。
五、多分支条件路由的三种实现思路
多分支条件路由,说白了就是“让数据自己选路”。有三类常见做法,每一种都有适合的场景。
5.1 多规则 + WHERE 条件
最常见也最直观的做法,就是给每一条路单独建一条规则,用 WHERE 关键字卡住条件。比如设备上报到同一个主题,高温的数据走报警动作,低温的数据走存储动作。因为规则是独立执行的,所以多个规则可以同时作用在同一份数据上,不会互相干扰。这种做法的优点是清晰、好排查;缺点是规则数量会随着分支增多而变多,管理成本随之上升。
5.2 先 republish 再二次路由
再做复杂一点,可以用 republish 动作。republish 的意思是“重新发布”,先让一条规则把数据从一个主题转发到另一个主题,然后其他规则订阅那个新主题,继续往下走。这种设计适合做多级流水线,比如第一级先做格式转换,第二级再做路由。缺点是会增加一步转发延迟,调试时也要多看一条链路。
5.3 一条规则挂多个动作
这里要提醒一下,有的新手会以为“一个规则里加多个动作”就是条件路由。实际上,同一个规则里的多个动作,只要 SQL 匹配成功,所有动作都会执行。它适合做“全量同步发送”,比如一条数据同时存数据库和发日志,并不是按条件二选一。真想要条件分流,还是得靠多条规则加 WHERE,或者靠 republish 分级处理。
六、实战:温度数据三路分流
假设设备数据照常发到 device/+/data。我们想这样分流:
- 温度大于 40 度时,发一条 SNS 告警;
- 温度在 40 度或以下时,把数据写入 DynamoDB;
- 不管温度多少,所有原始数据都要放进 S3 做备份。
这三个分支可以同时存在,因为它们用的是同一条数据流。下面我们逐一创建规则。
6.1 创建规则一:高温告警
这条规则只关注高温数据,所以 SQL 里加上 WHERE temperature > 40。动作选择 SNS,消息会直接推到订阅者的邮箱或手机。
# 技术栈:AWS CLI + JSON 规则定义
# 规则一:温度大于 40 度时发 SNS 告警
cat > /tmp/rule_high_temp.json <<'EOF'
{
"sql": "SELECT deviceId, temperature, humidity, timestamp FROM \"device/+/data\" WHERE temperature > 40",
"actions": [
{
"sns": {
"targetArn": "arn:aws:sns:us-east-1:123456789012:iot-alert",
"roleArn": "arn:aws:iam::123456789012:role/iot-rule-role"
}
}
]
}
EOF
aws iot create-topic-rule \
--rule-name "high-temp-alert" \
--topic-rule-payload file:///tmp/rule_high_temp.json
6.2 创建规则二:正常温度入库
温度小于等于 40 度时,数据写入 DynamoDB。这里使用 INSERT 操作,主键是设备 ID 和时间戳。
# 技术栈:AWS CLI + JSON 规则定义
# 规则二:温度 <= 40 度时写入 DynamoDB
cat > /tmp/rule_normal_temp.json <<'EOF'
{
"sql": "SELECT deviceId, temperature, humidity, timestamp FROM \"device/+/data\" WHERE temperature <= 40",
"actions": [
{
"dynamoDB": {
"tableName": "normal_temperature_data",
"hashKeyField": "deviceId",
"hashKeyValue": "${deviceId}",
"rangeKeyField": "timestamp",
"rangeKeyValue": "${timestamp}",
"operation": "INSERT",
"roleArn": "arn:aws:iam::123456789012:role/iot-rule-role"
}
}
]
}
EOF
aws iot create-topic-rule \
--rule-name "normal-temp-to-db" \
--topic-rule-payload file:///tmp/rule_normal_temp.json
6.3 创建规则三:全量备份到 S3
这条规则不设置 WHERE 条件,任何从 device/+/data 来的消息都会触发。S3 的 key 用设备 ID 和时间戳做文件名,避免相互覆盖。
# 技术栈:AWS CLI + JSON 规则定义
# 规则三:所有数据都备份到 S3
cat > /tmp/rule_backup_s3.json <<'EOF'
{
"sql": "SELECT deviceId, temperature, humidity, timestamp FROM \"device/+/data\"",
"actions": [
{
"s3": {
"bucketName": "iot-device-backup",
"key": "device-data/${deviceId}/${timestamp}.json",
"roleArn": "arn:aws:iam::123456789012:role/iot-rule-role"
}
}
]
}
EOF
aws iot create-topic-rule \
--rule-name "backup-all-to-s3" \
--topic-rule-payload file:///tmp/rule_backup_s3.json
6.4 验证分流效果
创建好三条规则后,可以发布一条模拟数据。比如发布一条 45 度的高温数据,那么规则一和规则三会被触发,规则二不会。再发布一条 35 度的正常数据,规则二和规则三会被触发,规则一不会。
# 发布一条高温测试数据
aws iot-data publish \
--topic "device/device1/data" \
--payload '{"deviceId":"device1","temperature":45,"humidity":30,"timestamp":1700000001}'
# 发布一条正常温度测试数据
aws iot-data publish \
--topic "device/device1/data" \
--payload '{"deviceId":"device1","temperature":35,"humidity":60,"timestamp":1700000002}'
发布之后,你可以分别查看 SNS 收到的消息、DynamoDB 里的记录以及 S3 中的文件。如果某个规则没有触发,先去检查角色权限,再去检查 SQL 里的字段名和类型。特别是 temperature 字段,如果设备上报的是字符串 "45",比较运算时类型就可能对不上。
七、技术优缺点和注意事项
7.1 优点
规则引擎最大的优点是“托管”:你不必自己部署流处理框架,AWS 会处理底层扩展和运维。其次是 SQL 灵活,筛选、重命名字段都很方便。再就是和 AWS 服务集成度高,SNS、S3、DynamoDB、Lambda 都是开箱即用。
7.2 缺点
缺点是链路是异步的,调试不如同步调用直观。另外,如果规则数量非常多,在 AWS 控制台里管理会比较繁琐。还有一点,规则动作是“尽力投递”,极端情况下可能重复或者丢失,所以下游消费者要做幂等设计。
7.3 注意事项
- 规则角色必须包含对应动作的权限,比如写 DynamoDB 需要
dynamodb:PutItem,写 S3 需要s3:PutObject,发 SNS 需要sns:Publish。 - SQL 中 FROM 的主题筛选器要加双引号,并且注意转义。
- 如果使用
${...}做动作参数替换,要确保 SELECT 中选择了对应字段。 - 多条规则会同时执行,费用也会叠加,需要留意 IoT 规则的计算费用。
- 生产环境建议开启 CloudWatch 监控,观察每条规则的执行失败次数。
八、文章总结
多分支条件路由并不神秘,最可靠的办法就是“多个规则 + WHERE 条件”组合成一张网。规则引擎把设备数据从主题里接出来,每一个分支对着自己的 SQL 条件,各自去动作。必要时用 republish 做多级处理,也能实现更复杂的流水线。
只要把数据格式、SQL 条件和 IAM 权限理清楚,你就能让海量设备的数据按需分流,稳稳到达每一个目的地。
Comments