使用二进制负载 - Amazon IoT Core
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用二进制负载

如果您发送原始二进制负载,Amazon IoT Core 通过 S3 操作将其向下游路由到 Amazon S3 存储桶。然后,原始二进制负载编码为 base64 并附加到 JSON。当将消息负载作为原始二进制数据(而不是 JSON 对象)进行处理时,可以使用 * 运算符在 SELECT 子句中对其进行引用。

二进制负载示例

当您使用 * 将消息负载作为原始二进制数据进行引用时,您可以向规则添加数据。如果您有空的或 JSON 有效负载,生成的有效负载可以使用规则添加数据。下面显示了支持 SELECT 子句的示例。

  • 对于二进制有效负载,您可以将以下 SELECT 子句仅与 * 一起使用。

    • SELECT * FROM 'topic/subtopic'
    • SELECT * FROM 'topic/subtopic' WHERE timestamp() % 12 = 0
  • 您还可以添加数据并使用以下 SELECT 子句。

    • SELECT *, principal() as principal, timestamp() as time FROM 'topic/subtopic'
    • SELECT encode(*, 'base64') AS data, timestamp() AS ts FROM 'topic/subtopic'
  • 您还可以使用带二进制负载的 SELECT 子句。

    • 以下是指在 WHERE 子句中的 device_type

      SELECT * FROM 'topic/subtopic' WHERE device_type = 'thermostat'
    • 还支持以下内容。

      { "sql": "SELECT * FROM 'topic/subtopic'", "actions": [ { "republish": { "topic": "device/${device_id}" } } ] }

以下规则操作不支持二进制负载,因此您必须对它们进行解码。

  • 一些规则操作不支持二进制负载输入(例如,Lambda 操作),您必须解码二进制负载。如果 Lambda 规则操作是 base64 编码并在 JSON 负载中,则可以接收二进制数据。为此,您可以将规则更改如下:

    SELECT encode(*, 'base64') AS data FROM 'my_topic'
  • SQL 语句不支持字符串作为输入。要将字符串输入转换为 JSON,您可以运行以下命令。

    SELECT decode(encode(*, 'base64'), 'base64') AS payload FROM 'topic'

解码 protobuf 消息有效负载

协议缓冲区 (protobuf) 是一种开源数据格式,用于以紧凑的二进制形式序列化结构化数据。它用于通过网络传输数据或将数据存储在文件中。Protobuf 允许您以较小的数据包大小发送数据,并且速度比其他消息传递格式更快。Amazon IoT Core规则通过提供 decode(value, decodingScheme) SQL 函数来支持 protobuf,该函数允许您将 protobuf 编码的消息有效负载解码为 JSON 格式,并将它们路由到下游服务。本节详细介绍在Amazon IoT Core规则中配置 protobuf 解码的 step-by-step 过程。

先决条件

创建描述符文件

如果您已有描述符文件,可以跳过此步骤。描述符文件 (.desc) 是 .proto 文件的编译版本,它是一个文本文件,用于定义 protobuf 序列化中使用的数据结构和消息类型。要生成描述符文件,必须定义一个 .proto 文件,并使用 protoc 编译器对其进行编译。

  1. 创建定义消息类型的 .proto 文件。示例 .proto 文件可能如下所示:

    syntax = "proto3"; message Person { optional string name = 1; optional int32 id = 2; optional string email = 3; }

    在此示例 .proto 文件中,使用 proto3 语法并定义消息类型 PersonPerson 消息定义指定三个字段(名称、ID 和电子邮件)。有关 .proto 文件消息格式的更多信息,请参阅语言指南 (proto3)

  2. 使用 protoc 编译器编译 .proto 文件并生成一个描述符文件。创建描述符 (.desc) 文件的示例命令如下所示:

    protoc --descriptor_set_out=<FILENAME>.desc \ --proto_path=<PATH_TO_IMPORTS_DIRECTORY> \ --include_imports \ <PROTO_FILENAME>.proto

    此示例命令会生成一个描述符文件 <FILENAME>.desc,Amazon IoT Core 规则可以使用该文件来解码符合 <PROTO_FILENAME>.proto 中定义的数据结构的 protobuf 有效负载。

    • --descriptor_set_out

      指定应生成的描述符文件 (<FILENAME>.desc) 的名称。

    • --proto_path

      指定正在编译的文件所引用的任何导入的 .proto 文件的位置。如果您有多个位于不同位置的已导入 .proto 文件,可以多次指定此标志。

    • --include_imports

      指定还应编译任何已导入的 .proto 文件,并将其包含在 <FILENAME>.desc 描述符文件中。

    • <PROTO_FILENAME>.proto

      指定要编译的 .proto 文件的名称。

    有关 protoc 参考的更多信息,请参阅 API 参考

将描述符文件上传到 S3 存储桶

创建描述符文件 <FILENAME>.desc 后,使用 Amazon API、Amazon SDK 或 Amazon Web Services Management Console 将描述符文件 <FILENAME>.desc 上传到 Amazon S3 存储桶。

重要注意事项

  • 确保将描述符文件上传到您打算配置规则的同一 Amazon 区域中您的 Amazon Web Services 账户中的 Amazon S3 存储桶。

  • 确保您授予从 S3 读取 FileDescriptorSet 的 Amazon IoT Core 访问权限。如果您的 S3 存储桶已禁用服务器端加密 (SSE),或者 S3 存储桶已使用 Amazon S3 托管密钥 (SSE-S3) 加密,则不需要进行额外的策略配置。这可以通过示例存储桶策略来实现:

    { "Version": "2012-10-17", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": { "Service": "iot.amazonaws.com" }, "Action": "s3:Get*", "Resource": "arn:aws:s3:::<BUCKET NAME>/<FILENAME>.desc" } ] }
  • 如果您的 S3 存储桶是使用 Amazon Key Management Service 密钥 (SSE-KMS) 加密的,请确保在访问 S3 存储桶时授予使用该密钥的 Amazon IoT Core 权限,方法是将以下语句添加到您的密钥策略中:

    { "Sid": "Statement1", "Effect": "Allow", "Principal": { "Service": "iot.amazonaws.com" }, "Action": [ "kms:Decrypt", "kms:GenerateDataKey*", "kms:DescribeKey" ], "Resource": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab" }

在规则中配置 protobuf 解码

将描述符文件上传到 Amazon S3 存储桶后,配置一条规则,该规则可以使用 decode (value, decodingScheme) SQL 函数解码您的 protobuf 消息有效负载格式。详细的函数签名和示例可以在 SQL 参考的 decode (value, decodingScheme) SAmazon IoT QL 函数中找到。

以下是使用 decode (value, decodingScheme) 函数的 SQL 表达式示例:

SELECT VALUE decode(*, 'proto', '<BUCKET NAME>, '<FILENAME>.desc', '<PROTO_FILENAME>', '<PROTO_MESSAGE_TYPE>') FROM '<MY_TOPIC>'

在此示例表达式中:

  • 您可以使用 decode (value, decodingScheme) SQL 函数来解码引用的二进制消息有效负载*。这可以是二进制 protobuf 编码的有效负载,也可以是表示 base64 编码的 protobuf 有效载荷的 JSON 字符串。

  • 提供的消息有效负载使用中 PROTO_FILENAME.proto 定义的 Person 消息类型进行编码。

  • 名为的 Amazon S3 存储桶BUCKET NAME包含FILENAME.desc生成的自PROTO_FILENAME.proto

完成配置后,向 Amazon IoT Core 发布一条关于规则订阅的主题的消息。

限制

Amazon IoT Core 规则支持 protobuf,但存在以下限制:

  • 不支持在替换模板中解码 protobuf 消息有效负载。

  • 解码 protobuf 消息有效负载时,可以在单个 SQL 表达式中使用解码 SQL 函数最多 2 次。

  • 最大入站有效负载大小为 128 KiB(1KiB = 1024 字节),最大出站有效负载大小为 128 KiB,存储在 Amazon S3 存储桶中的 FileDescriptorSet 对象的最大大小为 32 KiB。

  • 不支持使用 SSE-C 加密进行加密的 Amazon S3 存储桶。

最佳实践

以下是一些最佳实践和故障排查提示。

  • 在 Amazon S3 存储桶中备份您的原型文件。

    备份您的原型文件是一种很好的做法,以防出现问题。例如,如果您在运行 protoc 时错误地修改了没有备份的原型文件,这可能会导致您的生产堆栈出现问题。有多种方法可以在 Amazon S3 存储桶中备份您的文件。例如,您可以在 S3 存储桶中使用版本控制。有关如何备份 Amazon S3 存储桶中的文件的更多信息,请参阅 Amazon S3 开发人员指南

  • 配置 Amazon IoT 日志记录以查看日志条目。

    配置Amazon IoT日志记录是一种很好的做法,这样您就可以查看您的账户的Amazon IoT日志 CloudWatch。当规则的 SQL 查询调用外部函数时,Amazon IoT Core 规则会生成一个带有 FunctionExecutioneventType 的日志条目,其中包含可帮助您排查故障的原因字段。可能的错误包括找不到 Amazon S3 对象,或者 protobuf 文件描述符无效。有关如何配置 Amazon IoT 日志记录和查看日志条目的更多信息,请参阅配置 Amazon IoT 日志记录规则引擎日志条目

  • 使用新的对象键更新 FileDescriptorSet,并更新规则中的对象键。

    您可以FileDescriptorSet通过将更新后的描述符文件上传到 Amazon S3 存储桶来更新。您对 FileDescriptorSet 的更新最多需要 15 分钟能够反映出来。为了避免这种延迟,FileDescriptorSet使用新的对象键上传更新后更新后更新后更新后更新规则中的此对象密钥是一种很好的做法。