MQTT发布字节数组时AWS Lambda未被调用的技术咨询
我来帮你分析下问题所在,以及如何调整让Lambda能正常处理字节数组的消息:
问题根源
AWS IoT规则的SQL查询默认是基于JSON格式的payload来匹配和解析的。当你发布字节数组(非JSON结构的二进制数据)时,IoT规则的SQL引擎无法将这个payload解析为JSON对象,所以不会触发后续的Lambda执行动作,这就是为什么你看不到CloudWatch日志的原因。
解决方案步骤
1. 修改IoT规则的SQL语句
你需要调整规则的查询语句,使用AWS IoT提供的decode函数来处理二进制/字节数组类型的payload。字节数组在IoT消息传输中通常是以Base64编码的形式传递的,所以我们可以用decode函数把它还原成原始的二进制数据或者字符串。
把原来的查询语句替换成:
select decode(*, 'base64') as payload from 'my_topic'
这个语句会将接收到的Base64编码的字节数组解码后,封装到payload字段中传递给Lambda。
2. 调整Lambda函数代码适配解码后的内容
修改后的Lambda需要从event.payload中获取解码后的字节数据,同时处理可能的类型转换(比如如果需要保存为文本,要转换成字符串)。另外,你代码里引入了zlib但没用到,如果你的字节数组是压缩过的(比如gzip),可以加入解压逻辑,这里先给出基础适配版本:
var AWS = require('aws-sdk'); var zlib = require('zlib'); var s3 = new AWS.S3(); exports.handler = (event, context, callback) => { console.log("Received event: ", JSON.stringify(event)); var bucketName = "otonomobucket"; var keyName = getKeyName("myData", Date.now()); // 从event.payload获取解码后的字节数组/内容 var content = event.payload; // 如果需要将字节数组转换为字符串(比如ASCII/UTF-8编码),可以用Buffer转换 // content = Buffer.from(content).toString('utf8'); console.log("Processed content: ", content); var params = { Bucket: bucketName, Key: keyName, Body: content // 直接传入字节数组或者转换后的字符串 }; s3.putObject(params, function (err, data) { if (err) { console.error("Error saving to S3: ", err); callback(err); // 抛出错误让Lambda记录日志 } else { console.log("Successfully saved object to " + bucketName + "/" + keyName); callback(null, "Success"); } }); }; function getKeyName(folder, filename) { return folder + '/' + filename + ".txt"; }
- 注意:如果你的字节数组是特定编码的二进制数据(比如图片、压缩包),直接传递
content到S3的Body即可,不需要转换为字符串;如果是文本类的字节数组,加上Buffer.from(content).toString('utf8')转换为可读字符串。
3. 验证IoT规则的权限配置
确保你的AWS IoT服务角色有调用目标Lambda函数的权限。可以检查IoT规则对应的角色是否包含lambda:InvokeFunction权限,目标Lambda的资源策略是否允许IoT服务调用它。
测试验证
修改完成后,重新发布字节数组到my_topic,然后查看CloudWatch日志,应该能看到Lambda被调用的记录,并且字节数据会被正确保存到S3中。
内容的提问来源于stack exchange,提问作者nnn

