AWS IoT トピックペイロードによる Kinesis シャードの分離
IoT トピックのペイロードを顧客 ID ごとに異なる Kinesis シャードへルーティングし、後続処理でも顧客ごとの順序を保つ方法。
Kinesis のシャードは IoT トピックのペイロードによって分離できます。これは、異なる顧客のレコードを後続処理のために別々のシャードへ振り分けたい場合に役立ちます。以下の例では、customer_id によってレコードをルーティングしています。
前提条件
以下があらかじめマシンにインストールされている必要があります。
- AWS SAM CLI
- Python 3.x
構築
AWS IoT のトピックルールでは PartitionKey: ${customer_id}(37 行目)を指定しており、これによってレコードがどのようにシャードへ振り分けられるかが決まります。
AWSTemplateFormatVersion: '2010-09-09'Transform: AWS::Serverless-2016-10-31
Resources: Lambda: Type: AWS::Serverless::Function Properties: CodeUri: ./src/ Events: Kinesis: Type: Kinesis Properties: BatchSize: 100 BisectBatchOnFunctionError: true Enabled: true StartingPosition: LATEST Stream: !GetAtt Kinesis.Arn FunctionName: aws_iot_kinesis_partition_lambda Handler: lambda_function.lambda_handler Role: !GetAtt IamRole.Arn Runtime: python3.8
Kinesis: Type: AWS::Kinesis::Stream Properties: Name: aws_iot_kinesis_partition_stream RetentionPeriodHours: 24 ShardCount: 1
TopicRule: Type: AWS::IoT::TopicRule Properties: RuleName: aws_iot_kinesis_partition_topic_rule TopicRulePayload: Actions: - Kinesis: PartitionKey: ${customer_id} RoleArn: !GetAtt IamRole.Arn StreamName: aws_iot_kinesis_partition_stream AwsIotSqlVersion: 2016-03-23 RuleDisabled: false Sql: SELECT * FROM 'aws-iot-kinesis-partition-topic'
IamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole - Effect: Allow Principal: Service: iot.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - kinesis:GetShardIterator - kinesis:GetRecords - kinesis:DescribeStream - kinesis:PutRecord Resource: - !GetAtt Kinesis.Arn PolicyName: policy
LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: /aws/lambda/aws_iot_kinesis_partition_lambda RetentionInDays: 1ストリームされたレコードを処理する Lambda 関数は、短い Python スクリプトです。
import json
def lambda_handler(event, context): for record in event['Records']: print(json.dumps(record['kinesis']))SAM を使ってスタックをビルド・デプロイします。
sam buildsam deploy \ --stack-name aws-iot-kinesis-partition-lambda \ --capabilities CAPABILITY_NAMED_IAMテスト
テスト用のペイロードは、AWS IoT のトピックに直接送信できます。
aws iot-data publish \ --topic aws-iot-kinesis-partition-topic \ --payload '{"customer_id": 1, "message": "Hello from AWS IoT"}' \ --cli-binary-format raw-in-base64-outLambda のログを確認し、partitionKey がペイロード内の customer_id と一致していることを確認します。

後片付け
この例で作成したリソースは、以下のコマンドで削除します。
sam delete --stack-name aws-iot-kinesis-partition-lambdaまとめ
IoT トピックルールで PartitionKey: ${customer_id} を設定したことで、Lambda コンシューマー側に何のパーティショニングロジックを持たせることなく、同一顧客のレコードを同じ Kinesis シャードへルーティングできました。ルーティングはこの一つの式だけで完結しており、レコードが event['Records'] に到達する時点ですでに同じシャードへ届いています。だからこそ後続処理で顧客ごとの順序を維持でき、顧客のイベントを順番に処理する必要がある処理にとっては重要なポイントになります。ただし注意すべき点として、これは customer_id の値がある程度均等に分布している場合にのみ負荷を均等に分散できるという前提があります。パーティションキーを正しく設定していても、特定の顧客の量が突出して多ければ、そのトラフィックは一つのシャードに集中してしまいます。
Related posts
SiteWise Edge GatewayでOPC UAデータをKinesisにストリーミングする
SiteWise Edge Gatewayとカスタムのgreengrassコンポーネントを使って、OPC UAテレメトリをKinesis Data Streamsへ橋渡しします。
AWS IoT Core における Kinesis Firehose のレコードセパレーター設定
IoT Core のトピックルールにある Firehose アクションでレコードセパレーターを設定し、S3 に改行区切りでレコードを格納する方法。
Docker環境でGreengrassコンポーネントをビルド・デプロイする
Greengrass Core Dockerイメージを使って、AWS IoT Greengrassコンポーネントをローカルで開発します。
Kinesis Firehoseの動的パーティショニングでNDJSON処理を簡素化する
Kinesis Data Firehoseが動的パーティショニングをサポートしたことで、NDJSON(改行区切りJSON)への変換のためだけにLambda関数を用意する必要がなくなりました。
AthenaとKinesis Data FirehoseでS3のログをクエリする
Kinesis Data FirehoseでログをS3に流し込み、Athenaでクエリする。カスタムプレフィックスを使ってパーティションを自動登録させる方法。
