

# 他の AWS サービスからのイベントを使用した Lambda の呼び出し
<a name="lambda-services"></a>

一部の AWS のサービスは、*トリガー*を使用して Lambda 関数を直接呼び出すことができます。これらのサービスはイベントを Lambda にプッシュし、指定されたイベントが発生すると即時に関数が呼び出されます。トリガーは、個別のイベントやリアルタイム処理に適しています。[Lambda コンソールを使用してトリガーを作成する](#lambda-invocation-trigger)と、コンソールは対応する AWS サービスと連携して、そのサービスでイベント通知を設定します。実際には、トリガーは Lambda ではなく、イベントを生成するサービスによって保存および管理されます。

イベントは JSON 形式で構造化されたデータです。JSON 構造は、それを生成するサービスとイベントタイプによって異なりますが、すべて関数がイベントを処理するために必要なデータを含んでいます。

関数には複数のトリガーを持つことができます。各トリガーは、関数を単独に呼び出すクライアントとして機能し、Lambda が関数に渡す各イベントには、1 つのトリガーからのデータしかありません。Lambda は、イベントドキュメントをオブジェクトに変換して関数ハンドラに渡します。

サービスに応じて、イベント駆動型呼び出しは[同期](invocation-sync.md)または[非同期](invocation-async.md)になります。
+ 同期呼び出しの場合、イベントを生成するサービスは、関数からのレスポンスを待機します。そのサービスは、関数がレスポンスで返す必要があるデータを定義します。サービスはエラー戦略を制御します (エラー発生時に再試行するかどうかなど)。
+ 非同期呼び出しの場合、Lambda は関数に渡す前に、イベントをキューに入れます。Lambda はイベントをキューに入れると、イベントを生成したサービスにすぐに成功レスポンスを送信します。関数がイベントを処理した後、Lambda はイベント生成サービスにレスポンスを返しません。

## トリガーの作成
<a name="lambda-invocation-trigger"></a>

トリガーを作成する最も簡単な方法は、Lambda コンソールを使用することです。コンソールを使用してトリガーを作成すると、Lambda によって、必要なアクセス許可が自動的に関数の[リソースベースのポリシー](access-control-resource-based.md)に追加されます。

**Lambda コンソールを使用してトリガーを作成するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. トリガーを作成する関数を選択します。

1. **[関数の概要]** ペインで、**[トリガーを追加]** を選択します。

1. 関数を呼び出す AWS サービスを選択します。

1. **トリガー設定** ペインにオプションを入力し、 **[追加]** を選択します。関数を呼び出すために選択した AWS のサービス に応じて、トリガー設定オプションは異なります。

## Lambda 関数を呼び出すことができるサービス
<a name="listing-of-services-and-links-to-more-information"></a>

次の表は、Lambda 関数を呼び出すことができるサービスをリストしています。


****  

| サービス | 呼び出し方法 | 
| --- | --- | 
|  [Amazon Managed Streaming for Apache Kafka](with-msk.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [セルフマネージド Apache Kafka](with-kafka.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Amazon API Gateway](services-apigateway.md)  |  イベント駆動型、同期呼び出し  | 
|  [AWS CloudFormation](services-cloudformation.md)  |  イベント駆動型、非同期呼び出し  | 
|  [Amazon CloudWatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#LambdaFunctionExample)  |  イベント駆動型;、非同期呼び出し  | 
|  [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-notify-lambda-cc.html)  |  イベント駆動型;、非同期呼び出し  | 
|  [AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html)  |  イベント駆動型;、非同期呼び出し  | 
|  [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-events.html)  |  イベント駆動型、同期呼び出し  | 
|  [AWS Config](governance-config.md)  |  イベント駆動型;、非同期呼び出し  | 
|  [Amazon Connect](https://docs.aws.amazon.com/connect/latest/adminguide/connect-lambda-functions.html)  |  イベント駆動型、同期呼び出し  | 
|  [ Amazon DocumentDB](with-documentdb.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Amazon DynamoDB](with-ddb.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Elastic Load Balancing (Application Load Balancer)](services-alb.md)  |  イベント駆動型、同期呼び出し  | 
|  [Amazon EventBridge (CloudWatch Events)](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html)  |  イベント駆動型、非同期呼び出し (イベントバス）、同期または非同期呼び出し (パイプとスケジュール）  | 
|  [AWS IoT](services-iot.md)  |  イベント駆動型、非同期呼び出し  | 
|  [Amazon Kinesis](with-kinesis.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/data-transformation.html)  |  イベント駆動型、同期呼び出し  | 
|  [Amazon Lex](https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html)  |  イベント駆動型、同期呼び出し  | 
|  [Amazon MQ](with-mq.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Amazon Simple Email Service](https://docs.aws.amazon.com/ses/latest/dg/receiving-email-action-lambda.html)  |  イベント駆動型、非同期呼び出し  | 
|  [Amazon Simple Notification Service](with-sns.md)  |  イベント駆動型、非同期呼び出し  | 
|  [Amazon Simple Queue Service](with-sqs.md)  |  [イベントソースマッピング](invocation-eventsourcemapping.md)  | 
|  [Amazon Simple Storage Service (Amazon S3)](with-s3.md)  |  イベント駆動型、非同期呼び出し  | 
|  [Amazon Simple Storage Service Batch](services-s3-batch.md)  |  イベント駆動型、同期呼び出し  | 
|  [Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_lambda.html)  |  シークレットローテーション  | 
|  [AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/connect-lambda.html)  |  イベント駆動型、同期または非同期呼び出し  | 
|  [Amazon VPC Lattice](https://docs.aws.amazon.com/vpc-lattice/latest/ug/lambda-functions.html)  |  イベント駆動型、同期呼び出し  | 

# Apache Kafka を用いた Lambda の使用
<a name="with-kafka-esm"></a>

Lambdaは、[Apache Kafka](https://kafka.apache.org/) を[イベントソースソース](invocation-eventsourcemapping.md)としてサポートしています。Apache Kafka は、高スループットのリアルタイムデータパイプラインおよびストリーミングアプリケーションを処理するために設計されたオープンソースのイベントストリーミングプラットフォームです。Apache Kafka で Lambda を使用する方法は、主に 2 つあります。
+ [Amazon MSK で Lambda を使用する](with-msk.md) – Amazon Managed Streaming for Apache Kafka (Amazon MSK) は、AWS によるフルマネージド型サービスです。Amazon MSK は、プロビジョニング、パッチ適用、スケーリングなど、Kafka インフラストラクチャ管理の自動化に役立ちます。
+ [セルフマネージド型の Apache Kafka で Lambda を使用する](with-kafka.md) – AWS の用語では、セルフマネージド型クラスターには、非 AWS ホスト型 Kafka クラスターも含まれます。例えば、[Confluent Cloud](https://www.confluent.io/confluent-cloud/) や [Redpanda](https://www.redpanda.com/) などの非 AWS 型クラウドプロバイダーでホストされている Kafka クラスターを使用して Lambda を引き続き使用できます。

Amazon MSK とセルフマネージド型 Apache Kafka のどちらを選択すべきかは、運用上のニーズおよび管理要件を考慮して決めてください。運用上のオーバーヘッドを最小限に抑えながら、スケーラブルで本稼働対応の Kafka のセットアップを AWS で迅速に管理したい場合は、Amazon MSK の使用が適しています。セキュリティ、モニタリング、高可用性を簡素化して、インフラストラクチャ管理よりもアプリケーション開発作業に注力できるからです。一方、セルフマネージド型 Apache Kafka は、オンプレミスクラスターを含む非 AWS ホスト型環境で実行されるユースケースに適しています。

**Topics**
+ [Amazon MSK で Lambda を使用する](with-msk.md)
+ [セルフマネージド型の Apache Kafka で Lambda を使用する](with-kafka.md)
+ [Lambda での Apache Kafka イベントポーラーのスケーリングモード](kafka-scaling-modes.md)
+ [Lambda での Apache Kafka ポーリングとストリームの開始位置](kafka-starting-positions.md)
+ [Lambda でのカスタマイズ可能なコンシューマーグループ ID](kafka-consumer-group-id.md)
+ [Amazon MSK およびセルフマネージド Apache Kafka イベントソースからのイベントのフィルタリング](kafka-filtering.md)
+ [Lambda での Kafka イベントソースとスキーマレジストリの使用](services-consume-kafka-events.md)
+ [Kafka イベントソースのための低レイテンシー処理](with-kafka-low-latency.md)
+ [Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)
+ [Amazon MSK とセルフマネージド Apache Kafka イベントソースの破棄されたバッチのキャプチャ](kafka-on-failure.md)
+ [Kafka トピックを障害発生時の送信先として使用する](kafka-on-failure-destination.md)
+ [Kafka イベントソースマッピングのログ記録](esm-logging.md)
+ [セルフマネージド Kafka イベントソースマッピングエラーのトラブルシューティング](with-kafka-troubleshoot.md)

# Amazon MSK で Lambda を使用する
<a name="with-msk"></a>

[Amazon Managed Streaming for Apache Kafka (Amazon MSK)](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) は、Apache Kafka を使用してストリーミングデータを処理するアプリケーションの構築および実行に使用できるフルマネージド型サービスです。Amazon MSK は、Kafka クラスターのセットアップ、スケーリング、管理を簡素化します。また、Amazon MSK を使用すると、AWS Identity and Access Management (IAM) を使って複数のアベイラビリティーゾーンやセキュリティ向けにより簡単にアプリケーションを設定することができます。

この章では、Amazon MSK クラスターを Lambda 関数のイベントソースとして使用する方法について説明します。Amazon MSK と Lambda を統合する一般的なプロセスには、次の手順が含まれます。

1. **[クラスターとネットワークのセットアップ](with-msk-cluster-network.md)** – まず、[Amazon MSK クラスター](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html)をセットアップします。これには、Lambda がクラスターにアクセスするための正しいネットワーク設定が含まれます。

1. **[イベントソースマッピングのセットアップ](with-msk-configure.md)** – 次に、Amazon MSK クラスターを関数に安全に接続するために Lambda が必要とする[イベントソースマッピング](invocation-eventsourcemapping.md)リソースを作成します。

1. **[関数とアクセス許可のセットアップ](with-msk-permissions.md)** – 最後に、関数を正しくセットアップし、[実行ロール](lambda-intro-execution-role.md)に必要なアクセス許可を付与します。

**注記**  
Amazon MSK イベントソースマッピングを Lambda または Amazon MSK コンソールから直接作成および管理できるようになりました。どちらのコンソールにも、より合理化された設定プロセスに必要な Lambda 実行ロールのアクセス許可の設定を自動的に処理するオプションがあります。

Amazon MSK クラスターとの Lambda 統合を設定する方法の例については、「[チュートリアル: Amazon MSK イベントソースマッピングを使用して Lambda 関数を呼び出す](services-msk-tutorial.md)」、「AWS コンピューティングブログ」の「[Amazon MSK を AWS Lambda のイベントソースとして使用する](https://aws.amazon.com/blogs/compute/using-amazon-msk-as-an-event-source-for-aws-lambda/)」、および「Amazon MSK Labs」の「[Amazon MSK Lambda 統合](https://amazonmsk-labs.workshop.aws/en/msklambda.html)」を参照してください。

**Topics**
+ [イベントの例](#msk-sample-event)
+ [Amazon MSK クラスターおよび Amazon VPC ネットワークの Lambda 向け設定](with-msk-cluster-network.md)
+ [Amazon MSK イベントソースマッピングの Lambda アクセス許可の設定](with-msk-permissions.md)
+ [Lambda での Amazon MSK イベントソースの設定](with-msk-configure.md)
+ [チュートリアル: Amazon MSK イベントソースマッピングを使用して Lambda 関数を呼び出す](services-msk-tutorial.md)

## イベントの例
<a name="msk-sample-event"></a>

Lambda は、関数を呼び出すとき、イベントパラメータ内のメッセージのバッチを送信します。イベントペイロードにはメッセージの配列が含まれています。各配列項目には、Amazon MSK トピックとパーティション識別子の詳細が、タイムスタンプおよび base64 でエンコードされたメッセージとともに含まれています。

```
{
   "eventSource":"aws:kafka",
   "eventSourceArn":"arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/751d2973-a626-431c-9d4e-d7975eb44dd7-2",
   "bootstrapServers":"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092",
   "records":{
      "mytopic-0":[
         {
            "topic":"mytopic",
            "partition":0,
            "offset":15,
            "timestamp":1545084650987,
            "timestampType":"CREATE_TIME",
            "key":"abcDEFghiJKLmnoPQRstuVWXyz1234==",
            "value":"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
            "headers":[
               {
                  "headerKey":[
                     104,
                     101,
                     97,
                     100,
                     101,
                     114,
                     86,
                     97,
                     108,
                     117,
                     101
                  ]
               }
            ]
         }
      ]
   }
}
```

# Amazon MSK クラスターおよび Amazon VPC ネットワークの Lambda 向け設定
<a name="with-msk-cluster-network"></a>

AWS Lambda 関数を Amazon MSK クラスターに接続するには、クラスターおよびクラスターが存在する [Amazon 仮想プライベートクラウド (VPC)](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) を正しく設定する必要があります。このページでは、クラスターおよび VPC を設定する方法について説明します。クラスターおよび VPC が既に正しく設定されている場合、「[Lambda での Amazon MSK イベントソースの設定](with-msk-configure.md)」を参照してイベントソースマッピングを設定します。

**Topics**
+ [Lambda と MSK の統合におけるネットワーク設定要件の概要](#msk-network-requirements)
+ [MSK イベントソース向け NAT ゲートウェイの設定](#msk-nat-gateway)
+ [MSK イベントソースの AWS PrivateLink エンドポイントの設定](#msk-vpc-privatelink)

## Lambda と MSK の統合におけるネットワーク設定要件の概要
<a name="msk-network-requirements"></a>

Lambda と MSK の統合に必要なネットワーク設定は、アプリケーションのネットワークアーキテクチャによって異なります。この統合には、Amazon MSK クラスター、Lambda 関数、Lambda イベントソースマッピングの 3 つの主要リソースが関与しています。これらのリソースはそれぞれ異なる VPC に存在します。
+ Amazon MSK クラスターは通常、管理する VPC のプライベートサブネットに存在します。
+ Lambda 関数は、Lambda が所有する AWS マネージド VPC に存在します。
+ Lambda イベントソースマッピングは、関数を含む VPC とは別に、Lambda が所有する別の AWS マネージド VPC に存在します。

[イベントソースマッピング](invocation-eventsourcemapping.md)は、MSK クラスターと Lambda 関数間の中間リソースです。イベントソースマッピングは 2 つのプライマリジョブ機能を果たします。まず、MSK クラスターに新しいメッセージをポーリングします。次に、これらのメッセージを使用して Lambda 関数を呼び出します。これらの 3 つのリソースはそれぞれ異なる VPC に存在するため、ポーリングおよび呼び出しのオペレーションの両方にクロス VPC ネットワークコールが必要となります。

次の図で示すように、イベントソースマッピングのネットワーク設定要件は、[プロビジョニングモード](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)とオンデマンドモードのいずれを使用するかによって異なります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/MSK-esm-network-overview.png)


Lambda イベントソースマッピングが MSK クラスターに新しいメッセージをポーリングする方法は、どちらのモードでも同じです。イベントソースマッピングと MSK クラスター間の接続を確立するため、Lambda はプライベートサブネットに[ハイパープレーン ENI](configuration-vpc.md#configuration-vpc-enis) (または、利用可能な場合は既存の ENI を再利用) を作成し、セキュリティで保護された接続を確立します。この図にあるように、ハイパープレーン ENI は Lambda 関数ではなく、MSK クラスターのサブネットおよびセキュリティグループ設定を使用します。

クラスターからのメッセージのポーリング後に Lambda が関数を呼び出す方法はモードごとに異なります。
+ プロビジョニングモードでは、Lambda はイベントソースマッピング VPC と関数 VPC 間の接続を自動的に処理します。したがって、関数を正常に呼び出すための追加のネットワークコンポーネントは不要です。
+ オンデマンドモードでは、Lambda イベントソースマッピングは、カスタマーマネージド型 VPC を経由するパスを介して関数を呼び出します。そのため、VPC のパブリックサブネットに [NAT ゲートウェイ](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)を設定するか、あるいは Lambda、[AWS Security Token Service (STS)](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html)、および (必要に応じて) [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) へのアクセスを提供する VPC のプライベートサブネットに [AWS PrivateLink](https://docs.aws.amazon.com/vpc/latest/privatelink/what-is-privatelink.html) エンドポイントを設定する必要があります。これらのオプションのどちらかを正しく設定することで、関数の呼び出しに必要な VPC と Lambda マネージドランタイム VPC 間の接続が可能になります。

NAT ゲートウェイは、プライベートサブネットのリソースがパブリックインターネットにアクセスできるようにします。この設定を使用した場合、トラフィックは Lambda 関数の呼び出し前にインターネットを経由します。一方、AWS PrivateLink エンドポイントはパブリックインターネットを経由しないので、プライベートサブネットから AWS サービスやその他のプライベート VPC リソースに安全に接続できます。これらのリソースの設定方法の詳細については、「[MSK イベントソース向け NAT ゲートウェイの設定](#msk-nat-gateway)」または「[MSK イベントソースの AWS PrivateLink エンドポイントの設定](#msk-vpc-privatelink)」を参照してください。

ここまでの説明は、MSK クラスターが VPC 内のプライベートサブネットに存在することを前提としており、これがより一般的なケースです。ただし、MSK クラスターが VPC 内のパブリックサブネットにあっても安全な接続を有効にするには、AWS PrivateLink エンドポイントを設定する必要があります。次の表は、MSK クラスターおよび Lambda イベントソースマッピングの設定方法に応じたネットワーク設定の要件をまとめたものです。


| MSK クラスターの場所 (カスタマーマネージド型 VPC 内) | Lambda イベントソースマッピングのスケーリングモード | 必要なネットワーク設定 | 
| --- | --- | --- | 
|  プライベートサブネット  |  オンデマンドモード  |  Lambda、AWS STS、および (必要に応じて) Secrets Manager へのアクセスを有効にする NAT ゲートウェイ (VPC のパブリックサブネット内) または AWS PrivateLink エンドポイント (VPC のプライベートサブネット内)。  | 
|  [Public subnet] (パブリックサブネット)  |  オンデマンドモード  |  Lambda、AWS STS、および (必要に応じて) Secrets Manager へのアクセスを有効にする AWS PrivateLink エンドポイント (VPC のパブリックサブネット内)。  | 
|  プライベートサブネット  |  プロビジョンドモード  |  なし  | 
|  [Public subnet] (パブリックサブネット)  |  プロビジョンドモード  |  なし  | 

さらに、MSK クラスターに関連付けられたセキュリティグループは、正しいポート経由でのトラフィックを許可する必要があります。次のセキュリティグループのルールが設定されていることを確認してください。
+ **インバウンドルール** – デフォルトのブローカーポートですべてのトラフィックを許可します。MSK が使用するポートは、クラスターの認証タイプによって異なります。IAM 認証の場合は `9098`、SASL/SCRAM の場合は `9096`、TLS の場合は `9094` を使用します。または、自己参照セキュリティグループルールを使用して、同じセキュリティグループ内のインスタンスからのアクセスを許可することもできます。
+ **アウトバウンドルール** – 関数が他の AWS サービスと通信する必要がある場合、外部の送信先の場合はポート `443` ですべてのトラフィックを許可します。逆に他の AWS サービスと通信する必要がない場合は、自己参照セキュリティグループのルールを使用してブローカーへのアクセスを制限することもできます。
+ **Amazon VPC エンドポイントのインバウンドルール** – Amazon VPC エンドポイントを使用している場合、そのエンドポイントに関連付けられたセキュリティグループは、クラスターのセキュリティグループからポート `443` でインバウンドトラフィックを許可する必要があります。

## MSK イベントソース向け NAT ゲートウェイの設定
<a name="msk-nat-gateway"></a>

イベントソースマッピングがクラスターからメッセージをポーリングできるように NAT ゲートウェイを設定し、VPC を経由するパスを介して関数を呼び出すことができます。この操作は、イベントソースマッピングがオンデマンドモードを使用しており、かつクラスターが VPC のプライベートサブネット内に存在する場合にのみ必要となります。クラスターが VPC のパブリックサブネットに存在するか、またはイベントソースマッピングがプロビジョニングモードを使用している場合、NAT ゲートウェイを設定する必要はありません。

[NAT ゲートウェイ](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)は、プライベートサブネットのリソースがパブリックインターネットにアクセスできるようにします。Lambda へのプライベート接続が必要な場合は、「[MSK イベントソースの AWS PrivateLink エンドポイントの設定](#msk-vpc-privatelink)」を参照してください。

NAT ゲートウェイを設定したら、適切なルートテーブルを設定する必要があります。これにより、プライベートサブネットからのトラフィックを NAT ゲートウェイ経由でパブリックインターネットにルーティングできるようになります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/MSK-NAT-Gateway.png)


次の手順では、コンソールを使用して NAT ゲートウェイを設定する方法について説明します。必要に応じて、各アベイラビリティーゾーン (AZ) にこの手順を繰り返します。

**NAT ゲートウェイと適切なルーティングを設定する方法 (コンソール)**

1. 次の点に注意して、「[NAT ゲートウェイを作成する](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-working-with.html)」の手順を実行してください。
   + NAT ゲートウェイは常にパブリックサブネットに存在する必要があります。[パブリック接続](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)で NAT ゲートウェイを作成します。
   + MSK クラスターが複数の AZ 間でレプリケートされている場合、それぞれの AZ に 1 つの NAT ゲートウェイを作成します。つまり、各 AZ に、クラスターを含むプライベートサブネット 1 つと NAT ゲートウェイを含むパブリックサブネット 1 つが VPC に必要です。例えば 3 つの AZ でセットアップする場合、3 つのプライベートサブネット、3 つのパブリックサブネット、3 つの NAT ゲートウェイが必要になります。

1. NAT ゲートウェイを作成したら、[Amazon VPC コンソール](https://console.aws.amazon.com/vpc/)を開き、左側のメニューで **[ルートテーブル]** を選択します。

1. [**ルートテーブルの作成**] を選択します。

1. このルートテーブルは、MSK クラスターを含む VPC に関連付けます。必要に応じて、ルートテーブルの名前を入力します。

1. [**ルートテーブルの作成**] を選択します。

1. 先ほど作成したルートテーブルを選択します。

1. **[サブネットの関連付け]** タブで、**[サブネットの関連付けの編集]** を選択します。
   + ルートテーブルを、MSK クラスターを含むプライベートサブネットに関連付けます。

1. [**Export routes**] (ルートのエクスポート) を選択します。

1. **[ルートの追加]** を選択します。

   1. [**Destination**] で、[`0.0.0.0/0`] を選択します。

   1. **[ターゲット]** に **[NAT ゲートウェイ]** を選択します。

   1. 検索ボックスで、手順 1 で作成した NAT ゲートウェイを選択します。これは、MSK クラスターを含むプライベートサブネット (手順 6 でこのルートテーブルに関連付けられたプライベートサブネット) と同じ AZ 内の NAT ゲートウェイである必要があります。

1. **[Save changes]** (変更の保存) をクリックします。

## MSK イベントソースの AWS PrivateLink エンドポイントの設定
<a name="msk-vpc-privatelink"></a>

クラスターからメッセージをポーリングし、VPC を経由するパスを介して関数を呼び出す AWS PrivateLink エンドポイントを設定します。これらのエンドポイントにより、MSK クラスターが次の内容にアクセスできるようにします。
+ Lambda サービス
+ [AWS Security Token Service (STS)](https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html)
+ 必要に応じて、[AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) サービス。これは、クラスター認証に必要なシークレットが Secrets Manager に保存されている場合に必要になります。

PrivateLink エンドポイントの設定は、イベントソースマッピングがオンデマンドモードを使用している場合にのみ必要です。イベントソースマッピングがプロビジョニングモードを使用している場合、Lambda がユーザーに代わって必要な接続を確立します。

PrivateLink エンドポイントを使用すると、AWS PrivateLink を経由して AWS サービスへの安全なプライベートアクセスが可能になります。MSK クラスターにパブリックインターネットへのアクセスを許可するように NAT ゲートウェイを設定するには、「[MSK イベントソース向け NAT ゲートウェイの設定](#msk-nat-gateway)」を参照してください。

VPC エンドポイントを設定すると、MSK クラスターに対して Lambda、STS、および (必要に応じて) Secrets Manager への直接かつプライベートのアクセス権が付与されます。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/MSK-PrivateLink-Endpoints.png)


次の手順では、コンソールを使用して PrivateLink エンドポイントを設定する方法について説明します。必要に応じて、各エンドポイント (Lambda、STS、Secrets Manager) にこの手順を繰り返します。

**VPC PrivateLink エンドポイントを設定する方法 (コンソール)**

1. [Amazon VPC コンソール](https://console.aws.amazon.com/vpc/)を開き、左側のメニューで **[エンドポイント]** を選択します。

1. **エンドポイントの作成** を選択します。

1. 必要に応じて、エンドポイントの名前を入力します。

1. **[タイプ]** には **[AWS サービス]** を選択します。

1. **[サービス]** で、サービスの名前を入力します。例えば、Lambda に接続するエンドポイントを作成するには、検索ボックスに「`lambda`」と入力します。

1. 結果には、現在のリージョンのサービスエンドポイントが表示されます。例えば、米国東部 (バージニア北部) リージョンでは、「`com.amazonaws.us-east-2.lambda`」が表示されます。このサービスを選択します。

1. **[ネットワーク設定]** で、MSK クラスターを含む VPC を選択します。

1. **[サブネット]** で、MSK クラスターが存在する AZ を選択します。
   + 各 AZ の **[サブネット ID]** で、MSK クラスターを含むプライベートサブネットを選択します。

1. **[セキュリティグループ]** で、MSK クラスターに関連付けられたセキュリティグループを選択します。

1. **エンドポイントの作成** を選択します。

デフォルトでは、Amazon VPC エンドポイントには、リソースへの広範なアクセスを許可するオープンな IAM ポリシーが適用されています。そのエンドポイントを使用して必要なアクションを実行するためのベストプラクティスは、これらのポリシーを制限することです。例えば、Secrets Manager エンドポイントの場合、関数の実行ロールのみがシークレットにアクセスできるようにポリシーを変更できます。

**Example VPC エンドポイントポリシー - Secrets Manager エンドポイント**  

```
{
    "Statement": [
        {
            "Action": "secretsmanager:GetSecretValue",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws::iam::123456789012:role/my-role"
                ]
            },
            "Resource": "arn:aws::secretsmanager:us-west-2:123456789012:secret:my-secret"
        }
    ]
}
```

AWS STS および Lambda エンドポイントの場合、呼び出し元プリンシパルを Lambda サービスプリンシパルのみに制限できます。ただし、これらのポリシーには必ず `"Resource": "*"` を使用してください。

**Example VPC エンドポイントポリシー - AWS STS エンドポイント**  

```
{
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "lambda.amazonaws.com"
                ]
            },
            "Resource": "*"
        }
    ]
}
```

**Example VPC エンドポイントポリシー – Lambda エンドポイント**  

```
{
    "Statement": [
        {
            "Action": "lambda:InvokeFunction",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "lambda.amazonaws.com"
                ]
            },
            "Resource": "*"
        }
    ]
}
```

# Amazon MSK イベントソースマッピングの Lambda アクセス許可の設定
<a name="with-msk-permissions"></a>

Amazon MSK クラスターにアクセスするには、関数とイベントソースマッピングはさまざまな Amazon MSK API アクションを実行するアクセス許可を必要とします。これらのアクセス許可を、関数の[実行ロール](lambda-intro-execution-role.md)に追加します。アクセスを必要とするユーザーがいる場合、そのユーザーまたはロールのアイデンティティポリシーに必要なアクセス許可を追加します。

[AWSLambdaMSKExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaMSKExecutionRole.html) マネージドポリシーには、Amazon MSK Lambda イベントソースマッピングに必要な最小限のアクセス許可が含まれています。アクセス許可プロセスを簡素化するには、次の操作を行います。
+ [AWSLambdaMSKExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaMSKExecutionRole.html) マネージドポリシーを実行ロールにアタッチします。
+ Lambda コンソールでアクセス許可を生成できるようにします。[コンソールで Amazon MSK イベントソースマッピングを作成する](msk-esm-create.md#msk-console)と、Lambda は実行ロールを評価し、アクセス許可がない場合に警告します。**[アクセス許可の生成]** を選択して、実行ロールを自動的に更新します。これは、実行ロールポリシーを手動で作成または変更した場合、またはポリシーが複数のロールにアタッチされている場合、機能しません。[障害発生時の送信先](kafka-on-failure.md)や [AWS Glue スキーマレジストリ](services-consume-kafka-events.md)などの高度な機能を使用する場合、実行ロールに追加のアクセス許可が必要になる場合があります。

**Topics**
+ [必要なアクセス許可](#msk-required-permissions)
+ [オプションのアクセス許可](#msk-optional-permissions)

## 必要なアクセス許可
<a name="msk-required-permissions"></a>

Lambda 関数の実行ロールには、Amazon MSK イベントソースマッピングに必要な以下のアクセス許可が必要です。これらのアクセス許可は、[AWSLambdaMSKExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaMSKExecutionRole.html) マネージドポリシーに含まれています。

### CloudWatch Logs のアクセス許可
<a name="msk-basic-permissions"></a>

次のアクセス許可により、Lambda は Amazon CloudWatch Logs にログを作成して保存できます。
+ [logs:CreateLogGroup](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html)
+ [logs:CreateLogStream](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogStream.html)
+ [logs:PutLogEvents](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html)

### MSK クラスターのアクセス許可
<a name="msk-cluster-permissions"></a>

次のアクセス許可により、Lambda はユーザーに代わって Amazon MSK クラスターにアクセスできます。
+ [kafka:DescribeCluster](https://docs.aws.amazon.com/msk/1.0/apireference/clusters-clusterarn.html)
+ [kafka:DescribeClusterV2](https://docs.aws.amazon.com/MSK/2.0/APIReference/v2-clusters-clusterarn.html)
+ [kafka:GetBootstrapBrokers](https://docs.aws.amazon.com/msk/1.0/apireference/clusters-clusterarn-bootstrap-brokers.html)

[kafka:DescribeCluster](https://docs.aws.amazon.com/msk/1.0/apireference/clusters-clusterarn.html) の代わりに [kafka:DescribeClusterV2](https://docs.aws.amazon.com/MSK/2.0/APIReference/v2-clusters-clusterarn.html) を使用することをお勧めします。v2 アクセス許可は、プロビジョニングされた Amazon MSK クラスターとサーバーレス Amazon MSK クラスターの両方で機能します。ポリシーでは、これらのアクセス許可のいずれかのみが必要です。

### VPC アクセス許可
<a name="msk-vpc-permissions"></a>

次のアクセス許可により、Lambda は Amazon MSK クラスターに接続するときにネットワークインターフェイスを作成および管理できます。
+ [ec2:CreateNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
+ [ec2:DescribeNetworkInterfaces](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
+ [ ec2:DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
+ [ ec2:DeleteNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
+ [ ec2:DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
+ [ ec2:DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)

## オプションのアクセス許可
<a name="msk-optional-permissions"></a>

 Lambda 関数には、以下を実行する許可も必要になる場合があります。
+ クロスアカウント Amazon MSK クラスターにアクセスする。クロスアカウントイベントソースマッピングの場合は、実行ロールに [kafka:DescribeVpcConnection](https://docs.aws.amazon.com/msk/1.0/apireference/vpc-connection-arn.html) が必要です。クロスアカウントイベントソースマッピングを作成する IAM プリンシパルには、[kafka:ListVpcConnections](https://docs.aws.amazon.com/msk/1.0/apireference/vpc-connections.html) が必要です。
+ [SASL/SCRAM 認証](msk-cluster-auth.md#msk-sasl-scram)を使用している場合で、SCRAM シークレットにアクセスする場合。これにより、関数はユーザー名とパスワードを使用して Kafka に接続できます。
+ SASL/SCRAM または [mTLS 認証](msk-cluster-auth.md#msk-mtls)を使用している場合で、Secrets Manager のシークレットを記述する場合。これにより、関数は安全な接続に必要な認証情報または証明書を取得できます。
+ AWS Secrets Manager シークレットが AWS KMS カスタマーマネージドキーで暗号化されている場合で、AWS KMS カスタマーマネージドキーにアクセスする場合。
+ 認証付きのスキーマレジストリを使用している場合で、スキーマレジストリシークレットにアクセスする場合。
  + AWS Glue Glue スキーマレジストリの場合、関数には `glue:GetRegistry` と `glue:GetSchemaVersion` のアクセス許可が必要です。これにより、関数は AWS Glue に保存されているメッセージ形式のルールを検索して使用できます。
  + `BASIC_AUTH` または `CLIENT_CERTIFICATE_TLS_AUTH` を使用した [Confluent スキーマレジストリ](https://docs.confluent.io/platform/current/schema-registry/security/index.html)の場合: 関数には、認証情報を含むシークレットに対する `secretsmanager:GetSecretValue` アクセス許可が必要です。これにより、関数は Confluent スキーマレジストリにアクセスするために必要なユーザー名/パスワードまたは証明書を取得できます。
  + プライベート CA 証明書の場合: 関数には、証明書を含むシークレットに対する secretsmanager:GetSecretValue アクセス許可が必要です。これにより、関数はカスタム証明書を使用するスキーマレジストリの ID を検証できます。
+ イベントソースマッピングに IAM 認証を使用している場合で、Kafka クラスターコンシューマーグループにアクセスし、トピックからメッセージをポーリングする場合。

 この対象となるのは以下のアクセス許可です。
+ [kafka:ListScramSecrets](https://docs.aws.amazon.com/msk/1.0/apireference/clusters-clusterarn-scram-secrets.html) - Kafka 認証用の SCRAM シークレットのリストを許可します
+ [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html) - Secrets Manager からのシークレットの取得を有効にします
+ [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) - AWS KMS を使用して暗号化されたデータの復号を許可します
+ [glue:GetRegistry](https://docs.aws.amazon.com/glue/latest/webapi/API_GetRegistry.html) - AWS Glue スキーマレジストリへのアクセスを許可します
+ [glue:GetSchemaVersion](https://docs.aws.amazon.com/glue/latest/webapi/API_GetSchemaVersion.html) - AWS Glue スキーマレジストリから特定のスキーマバージョンを取得できるようにします
+ [kafka-cluster:Connect](https://docs.aws.amazon.com/service-authorization/latest/reference/list_apachekafkaapisforamazonmskclusters.html) – クラスターに接続して認証するためのアクセス許可を付与
+ [kafka-cluster:AlterGroup](https://docs.aws.amazon.com/service-authorization/latest/reference/list_apachekafkaapisforamazonmskclusters.html) – Apache Kafka の READ GROUP ACL に相当する、クラスター上のグループに参加させるためのアクセス許可を付与
+ [kafka-cluster:DescribeGroup](https://docs.aws.amazon.com/service-authorization/latest/reference/list_apachekafkaapisforamazonmskclusters.html) – Apache Kafka の DESCRIBE GROUP ACL に相当する、クラスター上のグループを記述するためのアクセス許可を付与
+ [kafka-cluster:DescribeTopic](https://docs.aws.amazon.com/service-authorization/latest/reference/list_apachekafkaapisforamazonmskclusters.html) – Apache Kafka の DESCRIBE TOPIC ACL に相当する、クラスター上のトピックを記述するためのアクセス許可を付与
+ [kafka-cluster:ReadData](https://docs.aws.amazon.com/service-authorization/latest/reference/list_apachekafkaapisforamazonmskclusters.html) – Apache Kafka の READ TOPIC ACL に相当する、クラスター上のトピックからデータを読み取るためのアクセス許可を付与

 さらに、失敗した呼び出しのレコードを障害発生時の送信先に送信する場合、送信先タイプに応じて次のアクセス許可が必要です。
+ Amazon SQS 送信先の場合: [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) - Amazon SQS キューへのメッセージの送信を許可します
+ Amazon SNS 送信先の場合: [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html) - Amazon SNS トピックへのメッセージの発行を許可します
+ Amazon S3 バケット送信先の場合: [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) および [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucket.html) - Amazon S3 バケット内のオブジェクトの書き込みと一覧表示を有効にします

認証および承認エラーをトラブルシューティングするには、「[セルフマネージド Kafka イベントソースマッピングエラーのトラブルシューティング](with-kafka-troubleshoot.md)」を参照してください。

# Lambda での Amazon MSK イベントソースの設定
<a name="with-msk-configure"></a>

Amazon MSK クラスターを Lambda 関数のイベントソースとして使用するには、2 つのリソースを接続する[イベントソースマッピング](invocation-eventsourcemapping.md)を作成します。このページでは、Amazon MSK 用にイベントソースマッピングを作成する方法について説明します。

このページの説明は、MSK クラスターおよびそのクラスターが存在する [Amazon 仮想プライベートクラウド (VPC)](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) を正しく設定済みであることを前提としています。クラスターまたは VPC をセットアップする必要がある場合は、「[Amazon MSK クラスターおよび Amazon VPC ネットワークの Lambda 向け設定](with-msk-cluster-network.md)」を参照してください。エラー処理の再試行動作を設定するには、「[Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)」を参照してください。

**Topics**
+ [イベントソースとしての Amazon MSK クラスターの使用](#msk-esm-overview)
+ [Lambda での Amazon MSK クラスターの認証方法の設定](msk-cluster-auth.md)
+ [Amazon MSK イベントソース向け Lambda イベントソースマッピング作成](msk-esm-create.md)
+ [Lambda でのクロスアカウントのイベントソースマッピングの作成](msk-cross-account.md)
+ [Lambda のすべての Amazon MSK イベントソースの設定パラメータ](msk-esm-parameters.md)

## イベントソースとしての Amazon MSK クラスターの使用
<a name="msk-esm-overview"></a>

Apache Kafka クラスターまたは Amazon MSK クラスターを Lambda 関数のトリガーとして追加すると、クラスターは[イベントソース](invocation-eventsourcemapping.md)として使用されます。

Lambda は、ユーザーが指定した[開始位置](kafka-starting-positions.md)に基づいて、[CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) リクエストで `Topics` として指定した Kafka トピックからイベントデータを読み取ります。処理が成功すると、Kafka トピックは Kafka クラスターにコミットされます。

Lambda は、Kafka トピックの各パーティションのメッセージを順番に読み込みます。1 つの Lambda ペイロードに、複数のパーティションからのメッセージを含めることができます。利用可能なレコードが増えると、Lambda は [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) リクエストで指定した BatchSize 値に基づいて、関数がトピックに追いつくまでバッチ単位でレコードの処理を継続します。

Lambda は各バッチを処理した後、そのバッチ内のメッセージのオフセットをコミットします。関数がバッチ内のいずれかのメッセージに対してエラーを返すと、Lambda は、処理が成功するかメッセージが期限切れになるまでメッセージのバッチ全体を再試行します。すべての再試行が失敗したレコードを、障害発生時の送信先に送信して、後で処理することができます。

**注記**  
Lambda 関数の最大タイムアウト制限は通常 15 分ですが、Amazon MSK、自己管理型 Apache Kafka、Amazon DocumentDB、および ActiveMQ と RabbitMQ 向け Amazon MQ のイベントソースマッピングでは、最大タイムアウト制限が 14 分の関数のみがサポートされます。

# Lambda での Amazon MSK クラスターの認証方法の設定
<a name="msk-cluster-auth"></a>

Lambda は、Amazon MSK クラスターへのアクセス、レコードの取得、その他のタスクの実行を行うための許可を必要とします。Amazon MSK は、MSK クラスターに対する認証方法をいくつかサポートしています。

**Topics**
+ [非認証アクセス](#msk-unauthenticated)
+ [SASL/SCRAM 認証](#msk-sasl-scram)
+ [相互 TLS 認証](#msk-mtls)
+ [IAM 認証](#msk-iam-auth)
+ [Lambda でのブートストラップブローカーの選択方法](#msk-bootstrap-brokers)

## 非認証アクセス
<a name="msk-unauthenticated"></a>

インターネット経由でクラスターにアクセスするクライアントがない場合は、非認証アクセスを使用できます。

## SASL/SCRAM 認証
<a name="msk-sasl-scram"></a>

Lambda は、SHA-512 ハッシュ関数および Transport Layer Security (TLS) 暗号化を使用する [Simple Authentication and Security Layer/Salted Challenge Response Authentication Mechanism (SASL/SCRAM)](https://docs.aws.amazon.com/msk/latest/developerguide/msk-password-tutorial.html) 認証をサポートしています。Lambda がクラスターに接続できるようにするには、認証情報 (ユーザー名およびパスワード) を Secrets Manager のシークレットに保存し、イベントソースマッピングの設定時にこのシークレットを参照します。

Secrets Manager の使用に関する詳細については、「*Amazon Managed Streaming for Apache Kafka デベロッパーガイド*」の「[Secrets Manager を使用したサインイン認証](https://docs.aws.amazon.com/msk/latest/developerguide/msk-password.html)」を参照してください。

**注記**  
Amazon MSK は SASL/PLAIN 認証をサポートしません。

## 相互 TLS 認証
<a name="msk-mtls"></a>

相互 TLS (mTLS) は、クライアントとサーバー間に双方向認証を提供します。サーバーがクライアントを認証できるよう、クライアントはサーバーに証明書を送信します。また、クライアントがサーバーを認証できるよう、サーバーもクライアントに証明書を送信します。

Amazon MSK と Lambda の統合の場合、MSK クラスターはサーバーとして機能し、Lambda はクライアントとして機能します。
+ Lambda が MSK クラスターを認証するためには、Secrets Manager でクライアント証明書をシークレットとして設定し、イベントソースマッピング設定でこの証明書を参照します。クライアント証明書は、 サーバーのトラストストア内の認証局 (CA) によって署名される必要があります。
+ MSK クラスターは Lambda にもサーバー証明書を送信します。サーバー証明書は、AWS トラストストア内の認証局 (CA) によって署名される必要があります。

Amazon MSK は自己署名サーバー証明書をサポートしていません。Amazon MSK のすべてのブローカーは、デフォルトで Lambda が信頼する [Amazon Trust Services CA](https://www.amazontrust.com/repository/) によって署名された[パブリック証明書](https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html)を使用します。

### mTLS シークレットの設定
<a name="mtls-auth-secret"></a>

CLIENT\$1CERTICATE\$1TLS\$1AUTH シークレットは、証明書フィールドとプライベートキーフィールドを必要とします。暗号化されたプライベートキーの場合、シークレットはプライベートキーのパスワードを必要とします。証明書とプライベートキーは、どちらも PEM 形式である必要があります。

**注記**  
Lambda は、[PBES1](https://datatracker.ietf.org/doc/html/rfc2898/#section-6.1) (PBES2 ではありません) プライベートキー暗号化アルゴリズムをサポートします。

証明書フィールドには、クライアント証明書で始まり、その後に中間証明書が続き、ルート証明書で終わる証明書のリストが含まれている必要があります。各証明書は、以下の構造を使用した新しい行で始める必要があります。

```
-----BEGIN CERTIFICATE-----  
        <certificate contents>
-----END CERTIFICATE-----
```

Secrets Manager は最大 65,536 バイトのシークレットをサポートします。これは、長い証明書チェーンにも十分な領域です。

プライベートキーは、以下の構造を使用した [PKCS \$18](https://datatracker.ietf.org/doc/html/rfc5208) 形式にする必要があります。

```
-----BEGIN PRIVATE KEY-----  
         <private key contents>
-----END PRIVATE KEY-----
```

暗号化されたプライベートキーには、以下の構造を使用します。

```
-----BEGIN ENCRYPTED PRIVATE KEY-----  
          <private key contents>
-----END ENCRYPTED PRIVATE KEY-----
```

以下は、暗号化されたプライベートキーを使用する mTLS 認証のシークレットの内容を示す例です。暗号化されたプライベートキーの場合は、シークレットにプライベートキーのパスワードを含めます。

```
{
 "privateKeyPassword": "testpassword",
 "certificate": "-----BEGIN CERTIFICATE-----
MIIE5DCCAsygAwIBAgIRAPJdwaFaNRrytHBto0j5BA0wDQYJKoZIhvcNAQELBQAw
...
j0Lh4/+1HfgyE2KlmII36dg4IMzNjAFEBZiCRoPimO40s1cRqtFHXoal0QQbIlxk
cmUuiAii9R0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFgjCCA2qgAwIBAgIQdjNZd6uFf9hbNC5RdfmHrzANBgkqhkiG9w0BAQsFADBb
...
rQoiowbbk5wXCheYSANQIfTZ6weQTgiCHCCbuuMKNVS95FkXm0vqVD/YpXKwA/no
c8PH3PSoAaRwMMgOSA2ALJvbRz8mpg==
-----END CERTIFICATE-----",
 "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFKzBVBgkqhkiG9w0BBQ0wSDAnBgkqhkiG9w0BBQwwGgQUiAFcK5hT/X7Kjmgp
...
QrSekqF+kWzmB6nAfSzgO9IaoAaytLvNgGTckWeUkWn/V0Ck+LdGUXzAC4RxZnoQ
zp2mwJn2NYB7AZ7+imp0azDZb+8YG2aUCiyqb6PnnA==
-----END ENCRYPTED PRIVATE KEY-----"
}
```

Amazon MSK 用の mTLS およびクライアント証明書の生成手順に関する詳細については、「*Amazon Managed Streaming for Apache Kafka デベロッパーガイド*」の「[Amazon MSK の相互 TLS クライアント認証](https://docs.aws.amazon.com/msk/latest/developerguide/msk-authentication.html)」を参照してください。

## IAM 認証
<a name="msk-iam-auth"></a>

AWS Identity and Access Management (IAM) を使用して、MSK クラスターに接続するクライアントのアイデンティを認証することができます。IAM 認証を使用すると、Lambda は関数の[実行ロール](lambda-intro-execution-role.md)のアクセス許可に依存してクラスターへの接続、レコードの取得、その他の必要なアクションを実行します。必要なアクセス許可を含むサンプルポリシーについては、「*Amazon Managed Streaming for Apache Kafka デベロッパーガイド*」の「[IAM ロールの認可ポリシーを作成する](https://docs.aws.amazon.com/msk/latest/developerguide/create-iam-access-control-policies.html)」を参照してください。

MSK クラスターで IAM 認証がアクティブで、シークレットを指定しない場合、Lambda はデフォルトで自動的に IAM 認証を使用します。

Amazon MSK での IAM 認証の詳細については、「[IAM アクセスコントロール](https://docs.aws.amazon.com/msk/latest/developerguide/iam-access-control.html)」を参照してください。

## Lambda でのブートストラップブローカーの選択方法
<a name="msk-bootstrap-brokers"></a>

Lambda は、クラスターで使用可能な認証方法、および認証用のシークレットが提供されているかどうかに基づき、[ブートストラップブローカー](https://docs.aws.amazon.com/msk/latest/developerguide/msk-get-bootstrap-brokers.html)を選択します。mTLS または SASL/SCRAM のシークレットを指定すると、Lambda は自動的にその認証方法を選択します。シークレットを指定しない場合、Lambda は、クラスターでアクティブ化されている中で、最も強力な認証方法を選択します。以下は、Lambda によるブローカー選択の優先度を、最も強力な認証から弱い認証の順に示したものです。
+ mTLS (mTLS 用のシークレットを提供)
+ SASL/SCRAM (SASL/SCRAM 用のシークレットを提供)
+ SASL IAM (シークレットが提供されておらず、IAM 認証がアクティブ)
+ 非認証の TLS (シークレットが提供されておらず、IAM 認証も非アクティブ)
+ プレーンテキスト (シークレットが提供されておらず、IAM 認証と非認証 TLS の両方が非アクティブ)

**注記**  
Lambda から最も安全なブローカータイプへの接続ができない場合でも、Lambda は別の (安全性の低い) ブローカータイプへの接続を試行しません。安全性の低いブローカータイプを Lambda に選択させたい場合は、クラスターが使用している、より強力な認証方法をすべて無効にします。

# Amazon MSK イベントソース向け Lambda イベントソースマッピング作成
<a name="msk-esm-create"></a>

イベントソースマッピングの作成には、Lambda コンソール、[AWS Command Line Interface (CLI)](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)、[AWS SDK](https://aws.amazon.com/getting-started/tools-sdks/) のいずれかを使用できます。

**注記**  
イベントソースマッピングを作成すると、Lambda は MSK クラスターを含むプライベートサブネットに[ハイパープレーン ENI](configuration-vpc.md#configuration-vpc-enis) を作成し、これにより Lambda からの安全な接続を確立します。このハイパープレーン ENI は Lambda 関数ではなく、MSK クラスターのサブネットおよびセキュリティグループ設定を使用します。

次のコンソールの手順で、Lambda 関数のトリガーとして Amazon MSK クラスターを追加します。内部でイベントソースマッピングリソースが作成されます。

**Amazon MSK トリガーを Lambda 関数 (コンソール) に追加するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. Amazon MSK トリガーを追加する Lambda 関数の名前を選択します。

1. **[関数の概要]** で **[トリガーを追加]** をクリックします。

1. **[トリガー設定]** で **[MSK]** を選択します。

1. Kafka クラスターの詳細を指定するには、次の手順を実行してください。

   1. [**MSK cluster**] (MSK クラスター) で、クラスターを選択します。

   1. **[トピック名]**に、メッセージを使用する Kafka トピックの名前を入力します。

   1. **[コンシューマーグループ ID]** に、参加する Kafka コンシューマーグループの ID を入力します (該当する場合)。詳細については、「[Lambda でのカスタマイズ可能なコンシューマーグループ ID](kafka-consumer-group-id.md)」を参照してください。

1. **[クラスター認証]** で必要な設定を行います。クラスター認証の詳細については、「[Lambda での Amazon MSK クラスターの認証方法の設定](msk-cluster-auth.md)」を参照してください。
   + 接続の確立時に Lambda で MSK クラスターに対する認証を実行させたい場合、**[認証の使用]** をオンに切り替えます。認証の使用をお勧めします。
   + 認証を使用する場合、**[認証方法]** で使用する認証方法を選択します。
   + 認証を使用する場合、**[Secrets Manager キー]** で、クラスターへのアクセスに必要な認証情報を含む Secrets Manager キーを選択します。

1. **[イベントポーラー設定]** で、必要な設定を行います。
   + **[トリガーを有効にする]** を選択し、作成直後にトリガーが有効化されるようにします。
   + イベントソースマッピングに **[プロビジョニングモードの設定]** を行うかどうかを選択します。詳細については、「[Lambda での Apache Kafka イベントポーラーのスケーリングモード](kafka-scaling-modes.md)」を参照してください。
     + プロビジョンドモードを設定する場合は、**[最小イベントポーラー]** の値、**[最大イベントポーラー]** の値、PollerGroupName のオプションの値を入力して、同じイベントソース VPC 内の複数の ESM のグループ化を指定します。
   + **[開始位置]** で、Lambda がストリームからの読み取りを開始する方法を選択します。詳細については、「[Lambda での Apache Kafka ポーリングとストリームの開始位置](kafka-starting-positions.md)」を参照してください。

1. **[バッチ処理]** で必要な設定を行います。バッチ処理の詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

   1. [**Batch size**] (バッチサイズ) で、単一バッチで取得されるメッセージの最大数を設定します。

   1. **[バッチウィンドウ]** に、Lambda が関数呼び出し前にレコード収集に費やすことのできる最大時間 (秒) を入力します。

1. **[フィルタリング]**で必要な設定を行います。のフィルタリングについての詳細は「[Amazon MSK およびセルフマネージド Apache Kafka イベントソースからのイベントのフィルタリング](kafka-filtering.md)」を参照してください。
   + **[フィルター条件]** にフィルター条件定義を追加して、イベントを処理するかどうかを決定します。

1. **[障害処理]** で必要な設定を行います。障害処理の詳細については、「[Amazon MSK とセルフマネージド Apache Kafka イベントソースの破棄されたバッチのキャプチャ](kafka-on-failure.md)」を参照してください。
   + **[障害発生時の宛先]** には、障害発生時の送信先の ARN を指定します。

1. **[タグ]** には、このイベントソースマッピングに関連付けるタグを入力します。

1. トリガーを追加するには、[**Add**] (追加) を選択します。

[create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドと一緒に AWS CLI を使用してイベントソースマッピングを作成することもできます。次の例では、`LATEST` メッセージを開始点として Lambda 関数の `my-msk-function` を `AWSKafkaTopic` トピックにマッピングするイベントソースマッピングを作成します。このコマンドは [SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトも使用して、クラスターに接続するときに [SASL/SCRAM](msk-cluster-auth.md#msk-sasl-scram) 認証を使用するように Lambda に指示します。

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:cluster/my-cluster/fc2f5bdf-fd1b-45ad-85dd-15b4a5a6247e-2 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function
  --source-access-configurations '[{"Type": "SASL_SCRAM_512_AUTH","URI": "arn:aws:secretsmanager:us-east-1:111122223333:secret:my-secret"}]'
```

クラスターが [mTLS 認証](msk-cluster-auth.md#msk-mtls)を使用する場合、`CLIENT_CERTIFICATE_TLS_AUTH` および Secrets Manager のキー ARN を指定する [SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトを含める必要があります。これは次のコマンドで示されます。

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:cluster/my-cluster/fc2f5bdf-fd1b-45ad-85dd-15b4a5a6247e-2 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function
  --source-access-configurations '[{"Type": "CLIENT_CERTIFICATE_TLS_AUTH","URI": "arn:aws:secretsmanager:us-east-1:111122223333:secret:my-secret"}]'
```

クラスターが [IAM 認証](msk-cluster-auth.md#msk-iam-auth)を使用する場合、[SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトは不要です。これは次のコマンドで示されます。

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:cluster/my-cluster/fc2f5bdf-fd1b-45ad-85dd-15b4a5a6247e-2 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function
```

# Lambda でのクロスアカウントのイベントソースマッピングの作成
<a name="msk-cross-account"></a>

[マルチ VPC プライベート接続](https://docs.aws.amazon.com/msk/latest/developerguide/aws-access-mult-vpc.html)を使用して、Lambda 関数を別の AWS アカウントのプロビジョニングされた MSK クラスターに接続できます。マルチ VPC 接続は AWS PrivateLink を使用して、すべてのトラフィックを AWS ネットワーク内に保持します。

**注記**  
サーバーレス MSK クラスターにはクロスアカウントイベントソースマッピングを作成できません。

クロスアカウントイベントソースマッピングを作成するには、まず [MSK クラスターのマルチ VPC 接続を設定する](https://docs.aws.amazon.com/msk/latest/developerguide/aws-access-mult-vpc.html#mvpc-cluster-owner-action-turn-on)必要があります。イベントソースマッピングを作成するときは、以下の例に示すように、クラスター ARN の代わりにマネージド VPC 接続 ARN を使用します。[CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) オペレーションは、MSK クラスターが使用する認証タイプによっても異なります。

**Example — IAM 認証を使用するクラスターのクロスアカウントイベントソースマッピングを作成します。**  
クラスターが [IAM ロールベースの認証](msk-cluster-auth.md#msk-iam-auth)を使用する場合、[SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトは必要ありません。例:  

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:vpc-connection/444455556666/my-cluster-name/51jn98b4-0a61-46cc-b0a6-61g9a3d797d5-7 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function
```

**Example — SASL/SCRAM 認証を使用するクラスターのクロスアカウントイベントソースマッピングを作成します。**  
クラスターが [SASL/SCRAM 認証](msk-cluster-auth.md#msk-sasl-scram)を使用する場合は、`SASL_SCRAM_512_AUTH` および Secrets Manager のシークレット ARN を指定する [SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトを含める必要があります。  
SASL/SCRAM 認証でクロスアカウントの Amazon MSK イベントソースマッピングにシークレットを使用する方法は 2 つあります。  
+ Lambda 関数アカウントにシークレットを作成し、クラスターシークレットと同期します。2 つのシークレットを同期させる[ローテーションを作成](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html)します。このオプションでは、関数アカウントからシークレットを制御できます。
+ MSK クラスターに関連付けられているシークレットを使用してください。このシークレットは、Lambda 関数アカウントへのクロスアカウントアクセスを許可する必要があります。詳細については、「[別のアカウントのユーザーの AWS Secrets Manager シークレットに対するアクセス許可](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_examples_cross.html)」を参照してください。

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:vpc-connection/444455556666/my-cluster-name/51jn98b4-0a61-46cc-b0a6-61g9a3d797d5-7 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function \
  --source-access-configurations '[{"Type": "SASL_SCRAM_512_AUTH","URI": "arn:aws:secretsmanager:us-east-1:444455556666:secret:my-secret"}]'
```

**Example — mTLS 認証を使用するクラスターのクロスアカウントイベントソースマッピングを作成します。**  
クラスターが [mTLS 認証](msk-cluster-auth.md#msk-mtls)を使用する場合は、`CLIENT_CERTIFICATE_TLS_AUTH` および Secrets Manager のシークレット ARN を指定する [SourceAccessConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_SourceAccessConfiguration.html) オブジェクトを含める必要があります。シークレットは、クラスターアカウントまたは Lambda 関数アカウントに保存できます。  

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:vpc-connection/444455556666/my-cluster-name/51jn98b4-0a61-46cc-b0a6-61g9a3d797d5-7 \
  --topics AWSKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function \
  --source-access-configurations '[{"Type": "CLIENT_CERTIFICATE_TLS_AUTH","URI": "arn:aws:secretsmanager:us-east-1:444455556666:secret:my-secret"}]'
```

# Lambda のすべての Amazon MSK イベントソースの設定パラメータ
<a name="msk-esm-parameters"></a>

すべての Lambda イベントソースタイプは、同じ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションを共有しています。ただし、次のテーブルで示されるように、Amazon MSK に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | 注意事項 | 
| --- | --- | --- | --- | 
|  AmazonManagedKafkaEventSourceConfig  |  N  |  ConsumerGroupID フィールドを含み、デフォルトでは一意の値になっています。  |  作成時にのみ設定可能  | 
|  BatchSize  |  N  |  100  |  最大: 10,000  | 
|  DestinationConfig  |  N  |  該当なし  |  [Amazon MSK とセルフマネージド Apache Kafka イベントソースの破棄されたバッチのキャプチャ](kafka-on-failure.md)  | 
|  有効  |  N  |  正  |    | 
|  BisectBatchOnFunctionError  |  N  |  誤  |  [Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)  | 
|  FunctionResponseTypes  |  N  |  該当なし  |  [Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)  | 
|  MaximumRecordAgeInSeconds  |  N  |  -1 (無制限)  |  [Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)  | 
|  MaximumRetryAttempts  |  N  |  -1 (無制限)  |  [Kafka イベントソースのエラー処理コントロールの設定](kafka-retry-configurations.md)  | 
|  EventSourceArn  |  Y  | 該当なし |  作成時にのみ設定可能  | 
|  FilterCriteria  |  N  |  該当なし  |  [Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)  | 
|  FunctionName  |  Y  |  該当なし  |    | 
|  KMSKeyArn  |  N  |  該当なし  |  [フィルター条件の暗号化](invocation-eventfiltering.md#filter-criteria-encryption)  | 
|  MaximumBatchingWindowInSeconds  |  N  |  500 ミリ秒  |  [バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)  | 
|  ProvisionedPollersConfig  |  N  |  `MinimumPollers`: 指定しない場合のデフォルト値は 1 `MaximumPollers`: 指定しない場合のデフォルト値は 200 `PollerGroupName`: 該当なし  |  [プロビジョニングモード](kafka-scaling-modes.md#kafka-provisioned-mode)  | 
|  SourceAccessConfigurations  |  N  |  認証情報なし  |  イベントソース用の、SASL/SCRAM あるいは CLIENT\$1CERTIFICATE\$1TLS\$1AUTH (MutualTLS) の認証情報  | 
|  StartingPosition  |  Y  | 該当なし |  AT\$1TIMESTAMP、TRIM\$1HORIZON、または LATEST 作成時にのみ設定可能  | 
|  StartingPositionTimestamp  |  N  |  該当なし  |  StartingPosition が AT\$1TIMESTAMP に設定されている場合にのみ必要  | 
|  タグ  |  N  |  該当なし  |  [イベントソースマッピングでのタグの使用](tags-esm.md)  | 
|  トピック  |  Y  | 該当なし |  カフカのトピック名 作成時にのみ設定可能  | 

**注記**  
`PollerGroupName` を指定すると、同じ Amazon VPC 内の複数の ESM イベントポーラーユニット (EPU) 容量を共有できます。このオプションを使用して、ESM プロビジョンドモードコストを最適化できます。ESM グループ化の要件:  
ESM は同じ Amazon VPC 内にある必要があります
ポーラーグループあたり最大 100 ESM
グループ内のすべての ESM の合計最大ポーラー数は 2,000 を超えることはできません
`PollerGroupName` を更新して ESM を別のグループに移動するか、`PollerGroupName` を空の文字列 ("") に設定して ESM をグループから削除できます。

# チュートリアル: Amazon MSK イベントソースマッピングを使用して Lambda 関数を呼び出す
<a name="services-msk-tutorial"></a>

本チュートリアルでは、次の手順を実行します。
+ 既存の Amazon MSK クラスターと同じ AWS アカウントに Lambda 関数を作成します。
+ Amazon MSK と通信するように Lambda のネットワークと認証を設定します。
+ Lambda Amazon MSK イベントソースマッピングを設定します。これにより、イベントがトピックに出現したときに Lambda 関数が実行されます。

これらのステップを完了したら、イベントが Amazon MSK に送信されたときに、独自のカスタム Lambda コードを使用してそれらのイベントを自動的に処理するための Lambda 関数を設定できるようになります。

 **この機能で何ができますか?**

**ソリューションの例: MSK イベントソースマッピングを使用して、ライブスコアを顧客に配信します。**

次のシナリオを考えてみましょう。あなたの会社は、顧客がスポーツの試合などのライブイベントに関する情報を表示できるウェブアプリケーションをホストしています。試合の情報更新は、Amazon MSK の Kafka トピックを通じてチームに提供されます。MSK トピックから取得した更新情報を使用して、開発中のアプリケーション内で顧客にライブイベントの更新ビューを提供するソリューションを設計する必要があります。次の設計アプローチを決定しました。クライアントアプリケーションは、AWS でホストされているサーバーレスバックエンドと通信します。クライアントは、Amazon API Gateway WebSocket API を使用して WebSocket セッション経由で接続します。

このソリューションでは、MSK イベントを読み取り、いくつかのカスタムロジックを実行してアプリケーションレイヤーのイベントを準備し、その情報を API Gateway API に転送するコンポーネントが必要です。このコンポーネントは、Lambda 関数でカスタムロジックを指定し、それを AWS Lambda Amazon MSK イベントソースマッピングで呼び出すことで、AWS Lambda を使用して実装できます。

Amazon API Gateway WebSocket API を使用したソリューションの実装の詳細については、API Gateway ドキュメントの「[WebSocket API のチュートリアル](https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-chat-app.html)」を参照してください。

## 前提条件
<a name="w2aad101c23c15c35c19"></a>

以下の事前設定されたリソースを持つ AWS アカウント。

**これらの前提条件を満たすには、Amazon MSK ドキュメントの「[Getting started using Amazon MSK](https://docs.aws.amazon.com//msk/latest/developerguide/getting-started.html)」を参照してください。**
+ Amazon MSK クラスター 「*Amazon MSK の使用を開始する*」の「[Amazon MSK クラスターを作成する](https://docs.aws.amazon.com//msk/latest/developerguide/create-cluster.html)」を参照してください。
+ 以下の設定を行います。
  + クラスターのセキュリティ設定で **[IAM ロールベースの認証]** が **[有効]** になっていることを確認します。これにより、必要な Amazon MSK リソースにのみアクセスするように Lambda 関数を制限することで、セキュリティが向上します。これは、新しい Amazon MSK クラスターではデフォルトで有効になっています。
  + クラスターネットワーク設定で **[パブリックアクセス]** がオフになっていることを確認します。Amazon MSK クラスターのインターネットへのアクセスを制限すると、データを処理する仲介者の数が制限されることでセキュリティが向上します。これは、新しい Amazon MSK クラスターではデフォルトで有効になっています。
+ このソリューションに使用する Amazon MSK クラスターの Kafka トピック。「*Amazon MSK の使用を開始する*」の「[トピックの作成](https://docs.aws.amazon.com//msk/latest/developerguide/create-topic.html)」を参照してください。
+ Kafka クラスターから情報を取得し、テスト用に Kafka イベントをトピックに送信するように設定された Kafka 管理ホスト。例えば、Kafka 管理 CLI と Amazon MSK IAM ライブラリがインストールされた Amazon EC2 インスタンスなどです。「*Amazon MSK の使用を開始する*」の「[クライアントマシンを作成する](https://docs.aws.amazon.com//msk/latest/developerguide/create-client-machine.html)」を参照してください。

これらのリソースを設定したら、AWS アカウントから次の情報を収集して、続行する準備ができていることを確認します。
+ Amazon MSK クラスターの名前。この情報は、Amazon MSK コンソールで確認できます。
+ クラスター UUID。Amazon MSK クラスターの ARN の一部であり、Amazon MSK コンソールで確認できます。この情報を確認するには、Amazon MSK ドキュメントの「[クラスターの一覧表示](https://docs.aws.amazon.com/msk/latest/developerguide/msk-list-clusters.html)」の手順に従います。
+ Amazon MSK クラスターに関連付けられているセキュリティグループ。この情報は、Amazon MSK コンソールで確認できます。次のステップでは、これらを *clusterSecurityGroups* と呼びます。
+ Amazon MSK クラスターを含む Amazon VPC の ID。この情報を見つけるには、Amazon MSK コンソールで Amazon MSK クラスターに関連付けられたサブネットを特定し、Amazon VPC コンソールでそのサブネットに関連付けられた Amazon VPC を特定します。
+ ソリューションで使用される Kafka トピックの名前。この情報を確認するには、Kafka 管理ホストから Kafka `topics` CLI を使用して Amazon MSK クラスターを呼び出します。トピック CLI の詳細については、Kafka ドキュメントの「[Adding and removing topics](https://kafka.apache.org/documentation/#basic_ops_add_topic)」を参照してください。
+ Kafka トピックのコンシューマーグループの名前。Lambda 関数での使用に適しています。このグループは Lambda によって自動的に作成できるため、Kafka CLI で作成する必要はありません。コンシューマーグループを管理する必要がある場合、コンシューマーグループ CLI の詳細については、Kafka ドキュメントの「[Managing Consumer Groups](https://kafka.apache.org/documentation/#basic_ops_consumer_group)」を参照してください。

AWS アカウントに次のアクセス許可が必要です。
+ Lambda 関数を作成および管理するためのアクセス許可。
+ IAM ポリシーを作成し、それを Lambda 関数に関連付けるためのアクセス許可。
+ Amazon MSK クラスターをホストする Amazon VPC で Amazon VPC エンドポイントを作成し、ネットワーク設定を変更するためのアクセス許可。

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## Amazon MSK と通信するように Lambda のネットワーク接続を設定する
<a name="w2aad101c23c15c35c21"></a>

 AWS PrivateLink を使用して Lambda と Amazon MSK を接続します。これを行うには、Amazon VPC コンソールでインターフェイス Amazon VPC エンドポイントを作成します。ネットワーク設定の詳細については、「[Amazon MSK クラスターおよび Amazon VPC ネットワークの Lambda 向け設定](with-msk-cluster-network.md)」を参照してください。

Amazon MSK イベントソースマッピングが Lambda 関数に代わって実行される際には、Lambda 関数の実行ロールを引き受けます。この IAM ロールは、マッピングに対して、IAM で保護されたリソース (Amazon MSK クラスターなど) へのアクセスを許可します。コンポーネントは実行ロールを共有しますが、次の図に示すように、Amazon MSK マッピングと Lambda 関数には、それぞれのタスクに対して個別の接続要件があります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/msk_tut_network.png)


イベントソースマッピングは、Amazon MSK クラスターセキュリティグループに属します。このネットワークステップでは、Amazon MSK クラスター VPC から Amazon VPC エンドポイントを作成して、イベントソースマッピングを Lambda および STS サービスに接続します。Amazon MSK クラスターセキュリティグループからのトラフィックを受け入れるように、これらのエンドポイントを保護します。次に、Amazon MSK クラスターのセキュリティグループを調整して、イベントソースマッピングが Amazon MSK クラスターと通信できるようにします。

 AWS マネジメントコンソールを使用して、次の手順を設定できます。

**Lambda と Amazon MSK を接続するようにインターフェイス Amazon VPC エンドポイントを設定するには**

1. インターフェイス Amazon VPC エンドポイントのセキュリティグループ *endpointSecurityGroup* を作成します。これにより、*clusterSecurityGroups* からのポート 443 でのインバウンド TCP トラフィックが許可されます。Amazon EC2 ドキュメントの「[セキュリティグループの作成](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/working-with-security-groups.html#creating-security-group)」の手順に従って、セキュリティグループを作成します。次に、Amazon EC2 ドキュメントの「[セキュリティグループへのルールの追加](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/working-with-security-groups.html#adding-security-group-rule)」の手順に従って、適切なルールを追加します。

   **次の情報を使用してセキュリティグループを作成します。**

   インバウンドルールを追加する際に、*clusterSecurityGroups* 内のセキュリティグループごとにルールを作成します。各ルールは、次のように作成します。
   + **[タイプ]** で **[HTTPS]** を選択します。
   + **[ソース]** で *clusterSecurityGroups* のいずれかを選択します。

1.  Lambda サービスを Amazon MSK クラスターを含む Amazon VPC に接続するエンドポイントを作成します。「[インターフェイスエンドポイントの作成](https://docs.aws.amazon.com//vpc/latest/privatelink/create-interface-endpoint.html)」の手順に従います。

   **次の情報を使用してインターフェイスエンドポイントを作成します。**
   + **[サービス名]** で `com.amazonaws.regionName.lambda` を選択します。ここで、*regionName* が Lambda 関数をホストします。
   + **[VPC]** で、Amazon MSK クラスターを含む Amazon VPC を選択します。
   + **[セキュリティグループ]** で、前に作成した *endpointSecurityGroup* を選択します。
   + **[サブネット]** で、Amazon MSK クラスターをホストするサブネットを選択します。
   + **[ポリシー]** で、次のポリシードキュメントを指定します。これにより、Lambda サービスプリンシパルが `lambda:InvokeFunction` アクションに使用するためにエンドポイントを保護します。

     ```
     {
         "Statement": [
             {
                 "Action": "lambda:InvokeFunction",
                 "Effect": "Allow",
                 "Principal": {
                     "Service": [
                         "lambda.amazonaws.com"
                     ]
                 },
                 "Resource": "*"
             }
         ]
     }
     ```
   + **[DNS 名を有効化]** が設定されたままであることを確認します。

1.  AWS STS サービスを Amazon MSK クラスターを含む Amazon VPC に接続するエンドポイントを作成します。「[インターフェイスエンドポイントの作成](https://docs.aws.amazon.com//vpc/latest/privatelink/create-interface-endpoint.html)」の手順に従います。

   **次の情報を使用してインターフェイスエンドポイントを作成します。**
   + **[サービス名]** で AWS STS を選択します。
   + **[VPC]** で、Amazon MSK クラスターを含む Amazon VPC を選択します。
   + **[セキュリティグループ]** で *endpointSecurityGroup* を選択します。
   + **[サブネット]** で、Amazon MSK クラスターをホストするサブネットを選択します。
   + **[ポリシー]** で、次のポリシードキュメントを指定します。これにより、Lambda サービスプリンシパルが `sts:AssumeRole` アクションに使用するためにエンドポイントを保護します。

     ```
     {
         "Statement": [
             {
                 "Action": "sts:AssumeRole",
                 "Effect": "Allow",
                 "Principal": {
                     "Service": [
                         "lambda.amazonaws.com"
                     ]
                 },
                 "Resource": "*"
             }
         ]
     }
     ```
   + **[DNS 名を有効化]** が設定されたままであることを確認します。

1. Amazon MSK クラスターに関連付けられている各セキュリティグループに対して、つまり *clusterSecurityGroups* で、次のことを許可します。
   + すべての *clusterSecurityGroups* に対して、ポート 9098 でのすべてのインバウンドおよびアウトバウンド TCP トラフィックを許可します。これには、clusterSecurityGroups 内でのトラフィックも含まれます。
   + ポート 443 でのすべてのアウトバウンド TCP トラフィックを許可します。

   このトラフィックの一部は、デフォルトのセキュリティグループルールで許可されているため、クラスターが単一のセキュリティグループにアタッチされており、そのグループにデフォルトのルールがある場合は、追加のルールは必要ありません。セキュリティグループルールを調整するには、Amazon EC2 ドキュメントの「[セキュリティグループへのルールの追加](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/working-with-security-groups.html#adding-security-group-rule)」の手順に従います。

   **次の情報を使用して、セキュリティグループにルールを追加します。**
   + ポート 9098 のインバウンドルールまたはアウトバウンドルールごとに、以下を指定します。
     + [**タイプ**] で、[**カスタム TCP**] を選択します。
     + **[ポート範囲]** で 9098 を指定します。
     + **[ソース]** で *clusterSecurityGroups* のいずれかを指定します。
   + ポート 443 のインバウンドルールごとに、**[タイプ]** で **[HTTPS]** を選択します。

## Lambda が Amazon MSK トピックから読み取るための IAM ロールを作成する
<a name="w2aad101c23c15c35c23"></a>

Lambda が Amazon MSK トピックから読み取るための認証要件を特定し、ポリシーで定義します。ロール *lambdaAuthRole* を作成します。このロールは、Lambda がこれらのアクセス許可を使用することを承認します。`kafka-cluster` IAM アクションを使用して Amazon MSK クラスターに対するアクションを承認します。次に、Lambda が Amazon MSK クラスターを検出して接続するために必要な Amazon MSK の `kafka` アクションと Amazon EC2 アクションを実行すること、および Lambda が実行した内容をログに記録できるように CloudWatch アクションを実行することを承認します。

**Lambda が Amazon MSK から読み取るための認証要件を記述するには**

1. IAM ポリシードキュメント (JSON ドキュメント) である *clusterAuthPolicy* を作成します。これにより、Lambda は Kafka コンシューマーグループを使用して、Amazon MSK クラスター内の Kafka トピックからデータを読み取ることができるようになります。Lambda では、読み取り時に Kafka コンシューマーグループを設定する必要があります。

   前提条件に合わせて次のテンプレートを変更します。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "kafka-cluster:Connect",
                   "kafka-cluster:DescribeGroup",
                   "kafka-cluster:AlterGroup",
                   "kafka-cluster:DescribeTopic",
                   "kafka-cluster:ReadData",
                   "kafka-cluster:DescribeClusterDynamicConfiguration"
               ],
               "Resource": [
                   "arn:aws:kafka:us-east-1:111122223333:cluster/mskClusterName/cluster-uuid",
                   "arn:aws:kafka:us-east-1:111122223333:topic/mskClusterName/cluster-uuid/mskTopicName",
                   "arn:aws:kafka:us-east-1:111122223333:group/mskClusterName/cluster-uuid/mskGroupName"
               ]
           }
       ]
   }
   ```

------

   詳細については、「[Amazon MSK イベントソースマッピングの Lambda アクセス許可の設定](with-msk-permissions.md)」を参照してください。ポリシーは、次のように作成します。
   + *us-east-1* と *111122223333* を Amazon MSK クラスターの AWS リージョン と AWS アカウント に置き換えます。
   + *mskClusterName* には、Amazon MSK クラスターの名前を指定します。
   + *cluster-uuid* には、Amazon MSK クラスターの ARN 内の UUID を指定します。
   + *mskTopicName* には、Kafka トピックの名前を指定します。
   + *mskGroupName* には、Kafka コンシューマーグループの名前を指定します。

1. Lambda が Amazon MSK クラスターを検出して接続し、それらのイベントをログに記録するために必要となる、Amazon MSK、Amazon EC2、および CloudWatch のアクセス許可を特定します。

   `AWSLambdaMSKExecutionRole` マネージドポリシーは、必要なアクセス許可を許容的に定義します。これは、次の手順で使用します。

   本番環境で `AWSLambdaMSKExecutionRole` を評価し、最小特権の原則に基づいて実行ロールポリシーを制限します。その後、ロールに対して、このマネージドポリシーを置き換えるポリシーを作成します。

IAM ポリシー言語の詳細については、[IAM ドキュメント](https://docs.aws.amazon.com//iam/)を参照してください。

ポリシードキュメントを作成したので、IAM ポリシーを作成してロールにアタッチすることができます。これを行うには、コンソールを使用して次の手順を実行します。

**ポリシードキュメントから IAM ポリシーを作成するには**

1. AWS マネジメントコンソールにサインインして、IAM コンソール ([https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)) を開きます

1. 左側のナビゲーションペインで、**[ポリシー]** を選択します。

1. [**Create policy**] (ポリシーの作成) を選択します。

1. [**ポリシーエディタ**] セクションで、[**JSON**] オプションを選択します。

1. *clusterAuthPolicy* を貼り付けます。

1. ポリシーにアクセス権限を追加し終えたら、[**次へ**] を選択します。

1. [**確認と作成**] ページで、作成するポリシーの [**ポリシー名**] と [**説明**] (オプション) を入力します。**このポリシーで定義されているアクセス許可** を確認して、ポリシーによって付与されたアクセス許可を確認します。

1. **ポリシーを作成** をクリックして、新しいポリシーを保存します。

詳細については、IAM ドキュメントの「[IAM ポリシーの作成](https://docs.aws.amazon.com//IAM/latest/UserGuide/access_policies_create.html)」を参照してください。

適切な IAM ポリシーを作成したので、ロールを作成してそれらのポリシーをアタッチします。これを行うには、コンソールを使用して次の手順を実行します。

**IAM コンソールで実行ロールを作成するには**

1. IAM コンソールの [[Roles (ロール)] ページ](https://console.aws.amazon.com/iam/home#/roles)を開きます。

1. [**ロールの作成**] を選択してください。

1. **[信頼されたエンティティタイプ]** から、**[AWS サービス]** を選択します。

1. [**ユースケース**] で、**Lambda** を選択します。

1. [**次へ**] を選択します。

1. 次のポリシーを指定します。
   + *clusterAuthPolicy*
   + `AWSLambdaMSKExecutionRole`

1. [**次へ**] を選択します。

1. **[ロール名]** に *lambdaAuthRole* と入力し、**[ロールの作成]** を選択します。

詳細については、「[実行ロールを使用した Lambda 関数のアクセス許可の定義](lambda-intro-execution-role.md)」を参照してください。

## Amazon MSK トピックから読み取る Lambda 関数を作成する
<a name="w2aad101c23c15c35c25"></a>

IAM ロールを使用するように設定された Lambda 関数を作成します。コンソールを使用して Lambda 関数を作成できます。

**認証設定を使用して Lambda 関数を作成するには**

1.  Lambda コンソールを開き、ヘッダーから **[関数の作成]** を選択します。

1. **[一から作成]** を選択します。

1. **[関数名]** で、任意の適切な名前を指定します。

1. **[ランタイム]** で、**[最新のサポート対象]** バージョンの `Node.js` を選択すると、このチュートリアルで提供されるコードを使用できます。

1. **[デフォルトの実行ロールの変更]** を選択します。

1. **[既存のロールを使用]** を選択します。

1. **[既存のロール]** で、*lambdaAuthRole* を選択します。

本番環境では、通常、Lambda 関数が Amazon MSK のイベントを適切に処理できるようにするために、実行ロールにさらにポリシーを追加する必要があります。ロールにポリシーを追加する方法の詳細については、IAM ドキュメントの「[ID アクセス許可の追加または削除](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html#add-policies-console)」を参照してください。

## Lambda 関数へのイベントソースマッピングを作成する
<a name="w2aad101c23c15c35c27"></a>

Amazon MSK イベントソースマッピングは、該当する Amazon MSK イベントが発生したときに Lambda を呼び出すために必要な情報を Lambda サービスに提供します。コンソールを使用して Amazon MSK マッピングを作成できます。Lambda トリガーを作成すると、イベントソースマッピングは自動的に設定されます。

**Lambda トリガー (およびイベントソースマッピング) を作成するには**

1. Lambda 関数の概要ページに移動します。

1. 関数の概要セクションで、左下の **[トリガーの追加]** を選択します。

1. **[ソースの選択]** ドロップダウンで、**[Amazon MSK]** を選択します。

1. **[認証]** を設定しないでください。

1. **[MSK クラスター]** で、クラスターの名前を選択します。

1. **[バッチサイズ]** で、1 を入力します。これは、この機能のテストを容易にするためのステップであり、本番環境で理想的な値ではありません。

1. **[トピック名]** で、Kafka トピックの名前を指定します。

1. **[コンシューマーグループ ID]** で、Kafka コンシューマーグループの ID を指定します。

## ストリーミングデータを読み取るために Lambda 関数を更新する
<a name="w2aad101c23c15c35c29"></a>

 Lambda は、イベントメソッドパラメータを使用して Kafka イベントに関する情報を提供します。Amazon MSK イベントの構造の例については、「[イベントの例](with-msk.md#msk-sample-event)」を参照してください。Lambda によって転送された Amazon MSK イベントを解釈する方法を理解したら、これらのイベントによって提供される情報を使用するように Lambda 関数コードを変更できます。

 テスト目的で Lambda Amazon MSK イベントの内容をログに記録するには、Lambda 関数に次のコードを指定します。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での Amazon MSK イベントの消費。  

```
using System.Text;
using Amazon.Lambda.Core;
using Amazon.Lambda.KafkaEvents;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace MSKLambda;

public class Function
{
    
    
    /// <param name="input">The event for the Lambda function handler to process.</param>
    /// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
    /// <returns></returns>
    public void FunctionHandler(KafkaEvent evnt, ILambdaContext context)
    {

        foreach (var record in evnt.Records)
        {
            Console.WriteLine("Key:" + record.Key); 
            foreach (var eventRecord in record.Value)
            {
                var valueBytes = eventRecord.Value.ToArray();    
                var valueText = Encoding.UTF8.GetString(valueBytes);
                
                Console.WriteLine("Message:" + valueText);
            }
        }
    }
    

}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda での Amazon MSK イベントの消費。  

```
package main

import (
	"encoding/base64"
	"fmt"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(event events.KafkaEvent) {
	for key, records := range event.Records {
		fmt.Println("Key:", key)

		for _, record := range records {
			fmt.Println("Record:", record)

			decodedValue, _ := base64.StdEncoding.DecodeString(record.Value)
			message := string(decodedValue)
			fmt.Println("Message:", message)
		}
	}
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での Amazon MSK イベントの消費。  

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.KafkaEvent;
import com.amazonaws.services.lambda.runtime.events.KafkaEvent.KafkaEventRecord;

import java.util.Base64;
import java.util.Map;

public class Example implements RequestHandler<KafkaEvent, Void> {

    @Override
    public Void handleRequest(KafkaEvent event, Context context) {
        for (Map.Entry<String, java.util.List<KafkaEventRecord>> entry : event.getRecords().entrySet()) {
            String key = entry.getKey();
            System.out.println("Key: " + key);

            for (KafkaEventRecord record : entry.getValue()) {
                System.out.println("Record: " + record);

                byte[] value = Base64.getDecoder().decode(record.getValue());
                String message = new String(value);
                System.out.println("Message: " + message);
            }
        }

        return null;
    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での Amazon MSK イベントの消費。  

```
exports.handler = async (event) => {
    // Iterate through keys
    for (let key in event.records) {
      console.log('Key: ', key)
      // Iterate through records
      event.records[key].map((record) => {
        console.log('Record: ', record)
        // Decode base64
        const msg = Buffer.from(record.value, 'base64').toString()
        console.log('Message:', msg)
      }) 
    }
}
```
TypeScript を使用した Lambda での Amazon MSK イベントの消費。  

```
import { MSKEvent, Context } from "aws-lambda";
import { Buffer } from "buffer";
import { Logger } from "@aws-lambda-powertools/logger";

const logger = new Logger({
  logLevel: "INFO",
  serviceName: "msk-handler-sample",
});

export const handler = async (
  event: MSKEvent,
  context: Context
): Promise<void> => {
  for (const [topic, topicRecords] of Object.entries(event.records)) {
    logger.info(`Processing key: ${topic}`);

    // Process each record in the partition
    for (const record of topicRecords) {
      try {
        // Decode the message value from base64
        const decodedMessage = Buffer.from(record.value, 'base64').toString();

        logger.info({
          message: decodedMessage
        });
      }
      catch (error) {
        logger.error('Error processing event', { error });
        throw error;
      }
    };
  }
}
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での Amazon MSK イベントの消費。  

```
<?php
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\Kafka\KafkaEvent;
use Bref\Event\Handler as StdHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler implements StdHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws JsonException
     * @throws \Bref\Event\InvalidLambdaEvent
     */
    public function handle(mixed $event, Context $context): void
    {
        $kafkaEvent = new KafkaEvent($event);
        $this->logger->info("Processing records");
        $records = $kafkaEvent->getRecords();

        foreach ($records as $record) {
            try {
                $key = $record->getKey();
                $this->logger->info("Key: $key");

                $values = $record->getValue();
                $this->logger->info(json_encode($values));

                foreach ($values as $value) {
                    $this->logger->info("Value: $value");
                }
                
            } catch (Exception $e) {
                $this->logger->error($e->getMessage());
            }
        }
        $totalRecords = count($records);
        $this->logger->info("Successfully processed $totalRecords records");
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda での Amazon MSK イベントの消費。  

```
import base64

def lambda_handler(event, context):
    # Iterate through keys
    for key in event['records']:
        print('Key:', key)
        # Iterate through records
        for record in event['records'][key]:
            print('Record:', record)
            # Decode base64
            msg = base64.b64decode(record['value']).decode('utf-8')
            print('Message:', msg)
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda での Amazon MSK イベントの消費。  

```
require 'base64'

def lambda_handler(event:, context:)
  # Iterate through keys
  event['records'].each do |key, records|
    puts "Key: #{key}"

    # Iterate through records
    records.each do |record|
      puts "Record: #{record}"

      # Decode base64
      msg = Base64.decode64(record['value'])
      puts "Message: #{msg}"
    end
  end
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-msk-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用した Lambda での Amazon MSK イベントの消費。  

```
use aws_lambda_events::event::kafka::KafkaEvent;
use lambda_runtime::{run, service_fn, tracing, Error, LambdaEvent};
use base64::prelude::*;
use serde_json::{Value};
use tracing::{info};

/// Pre-Requisites:
/// 1. Install Cargo Lambda - see https://www.cargo-lambda.info/guide/getting-started.html
/// 2. Add packages tracing, tracing-subscriber, serde_json, base64
///
/// This is the main body for the function.
/// Write your code inside it.
/// There are some code example in the following URLs:
/// - https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples
/// - https://github.com/aws-samples/serverless-rust-demo/

async fn function_handler(event: LambdaEvent<KafkaEvent>) -> Result<Value, Error> {

    let payload = event.payload.records;

    for (_name, records) in payload.iter() {

        for record in records {

         let record_text = record.value.as_ref().ok_or("Value is None")?;
         info!("Record: {}", &record_text);

         // perform Base64 decoding
         let record_bytes = BASE64_STANDARD.decode(record_text)?;
         let message = std::str::from_utf8(&record_bytes)?;
         
         info!("Message: {}", message);
        }

    }

    Ok(().into())
}

#[tokio::main]
async fn main() -> Result<(), Error> {

    // required to enable CloudWatch error logging by the runtime
    tracing::init_default_subscriber();
    info!("Setup CW subscriber!");

    run(service_fn(function_handler)).await
}
```

------

コンソールを使用して Lambda に関数コードを指定できます。

**コンソールのコードエディタを使用して関数コードを更新するには**

1. Lambda コンソールの「[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)」を開き、関数を選択します。

1. **[コード]** タブを選択します。

1. **[コードソース]** ペインでソースコードファイルを選択し、統合コードエディタで編集します。

1. **[DEPLOY]** セクションで、**[デプロイ]** を選択して関数のコードを更新します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

## Lambda 関数をテストして、Amazon MSK トピックに接続されていることを確認します。
<a name="w2aad101c23c15c35c31"></a>

CloudWatch イベントログを調べることで、Lambda がイベントソースによって呼び出されているかどうかを確認できるようになりました。

**Lambda 関数が呼び出されているかどうかを確認するには**

1. Kafka 管理ホストを使用し、`kafka-console-producer` CLI を使用して Kafka イベントを生成します。詳細については、Kafka ドキュメントの「[Write some events into the topic](https://kafka.apache.org/documentation/#quickstart_send)」を参照してください。前のステップで定義したイベントソースマッピングのバッチサイズで定義されたバッチを埋めるのに十分なイベントを送信してください。そうしないと、Lambda は追加の情報が呼び出されるまで待機します。

1. 関数が実行されると、Lambda はその結果を CloudWatch に書き込みます。コンソールで、Lambda 関数の詳細ページに移動します。

1. [**Configuration (設定)**] タブを選択します。

1. サイドバーから、**[モニタリングおよび運用ツール]** を選択します。

1. **[ロギング設定]** で **[CloudWatch ロググループ]** を特定します。ロググループは `/aws/lambda` で始まります。ロググループへのリンクを選択します。

1. CloudWatch コンソールの **[ログイベント]** で、Lambda がログストリームに送信したログイベントがないかを調べます。次の図のように、Kafka イベントからのメッセージを含むログイベントがあるかどうかを確認します。存在する場合は、Lambda イベントソースマッピングを使用して Lambda 関数を Amazon MSK に正常に接続できています。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/msk_tut_log.png)

# セルフマネージド型の Apache Kafka で Lambda を使用する
<a name="with-kafka"></a>

このトピックでは、セルフマネージド型の Kafka クラスターで Lambda を使用する方法を説明します。AWS の用語集では、セルフマネージド型クラスターには、非 AWS のホストされた Kafka クラスターが含まれています。例えば、お使いの Kafka クラスターを、[Confluent Cloud](https://www.confluent.io/confluent-cloud/) または [Redpanda](https://www.redpanda.com/) などのクラウドプロバイダーでホストすることが可能です。

この章では、セルフマネージド Apache Kafka クラスターを Lambda 関数のイベントソースとして使用する方法について説明します。セルフマネージド Apache Kafka と Lambda を統合する一般的なプロセスには、次の手順が含まれます。

1. **[クラスターとネットワークのセットアップ](with-kafka-cluster-network.md)** – まず、Lambda がクラスターにアクセスできるように、適切なネットワーク設定でセルフマネージド Apache Kafka クラスターを設定します。

1. **[イベントソースマッピングのセットアップ](with-kafka-configure.md)** – 次に、Apache Kafka クラスターを関数に安全に接続するために Lambda が必要とする[イベントソースマッピング](invocation-eventsourcemapping.md)リソースを作成します。

1. **[関数とアクセス許可のセットアップ](with-kafka-permissions.md)** – 最後に、関数を正しくセットアップし、[実行ロール](lambda-intro-execution-role.md)に必要なアクセス許可を付与します。

イベントソースとしての Apache Kafka は、Amazon Simple Queue Service (Amazon SQS) または Amazon Kinesis を使用する場合と同様に動作します。Lambda は、イベントソースからの新しいメッセージを内部的にポーリングした後、ターゲットの Lambda 関数を同期的に呼び出します。Lambda はメッセージをバッチで読み込み、それらをイベントペイロードとして関数に提供します。最大バッチサイズは設定可能です (デフォルトでは 100 メッセージ)。詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

セルフマネージド Apache Kafka イベントソースマッピングのスループットを最適化するには、プロビジョンドモードを設定します。プロビジョンドモードでは、イベントソースマッピングに割り当てられるイベントポーラーの最小数と最大数を定義できます。これにより、イベントソースマッピングが予期しないメッセージスパイクを処理する能力を向上させることができます。詳細については、「[プロビジョンドモード](kafka-scaling-modes.md#kafka-provisioned-mode)」を参照してください。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

Kafka ベースのイベントソースの場合、Lambda はバッチ処理ウィンドウやバッチサイズなどの制御パラメータの処理をサポートします。詳しくは、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

セルフマネージド型 Kafka をイベントソースとして使用する方法の例については、AWS Compute Blog の [Using self-hosted Apache Kafka as an event source for AWS Lambda](https://aws.amazon.com/blogs/compute/using-self-hosted-apache-kafka-as-an-event-source-for-aws-lambda/) を参照してください。

**Topics**
+ [イベントの例](#smaa-sample-event)
+ [Lambda 用のセルフマネージド Apache Kafka クラスターとネットワークの設定](with-kafka-cluster-network.md)
+ [Lambda 実行ロールのアクセス許可の設定](with-kafka-permissions.md)
+ [Lambda 用のセルフマネージド Apache Kafka をイベントソースの設定](with-kafka-configure.md)

## イベントの例
<a name="smaa-sample-event"></a>

Lambda は、Lambda 関数を呼び出すとき、イベントパラメータ内のメッセージのバッチを送信します。イベントペイロードにはメッセージの配列が含まれています。各配列項目には、Kafka トピックと Kafka パーティション識別子の詳細が、タイムスタンプおよび base64 でエンコードされたメッセージとともに含まれています。

```
{
   "eventSource": "SelfManagedKafka",
   "bootstrapServers":"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092",
   "records":{
      "mytopic-0":[
         {
            "topic":"mytopic",
            "partition":0,
            "offset":15,
            "timestamp":1545084650987,
            "timestampType":"CREATE_TIME",
            "key":"abcDEFghiJKLmnoPQRstuVWXyz1234==",
            "value":"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
            "headers":[
               {
                  "headerKey":[
                     104,
                     101,
                     97,
                     100,
                     101,
                     114,
                     86,
                     97,
                     108,
                     117,
                     101
                  ]
               }
            ]
         }
      ]
   }
}
```

# Lambda 用のセルフマネージド Apache Kafka クラスターとネットワークの設定
<a name="with-kafka-cluster-network"></a>

Lambda 関数をセルフマネージド Apache Kafka クラスターに接続するには、クラスターとクラスターが存在するネットワークを正しく設定する必要があります。このページでは、クラスターおよびネットワークを設定する方法について説明します。クラスターおよびネットワークが既に正しく設定されている場合、「[Lambda 用のセルフマネージド Apache Kafka をイベントソースの設定](with-kafka-configure.md)」を参照してイベントソースマッピングを設定します。

**Topics**
+ [セルフマネージド Apache Kafka クラスターのセットアップ](#kafka-cluster-setup)
+ [ネットワークセキュリティを設定する](#services-kafka-vpc-config)

## セルフマネージド Apache Kafka クラスターのセットアップ
<a name="kafka-cluster-setup"></a>

[Confluent Cloud](https://www.confluent.io/confluent-cloud/) や [Redpanda](https://www.redpanda.com/) などのクラウドプロバイダーでセルフマネージド Apache Kafka クラスターをホストすることも、独自のインフラストラクチャで実行することもできます。クラスターが正しく設定され、Lambda イベントソースマッピングが接続するネットワークからアクセス可能であることを確認します。

## ネットワークセキュリティを設定する
<a name="services-kafka-vpc-config"></a>

イベントソースマッピングを通じて Lambda にセルフマネージド Apache Kafka へのフルアクセスを許可するには、クラスターがパブリックエンドポイント (パブリック IP アドレス) を使用するか、クラスターを作成した Amazon VPC へのアクセスを提供する必要があります。

Lambda でセルフマネージド Apache Kafka を使用する場合は、関数に Amazon VPC 内のリソースへのアクセスを付与する [AWS PrivateLink VPC エンドポイント](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html)を作成します。

**注記**  
イベントポーラーにデフォルト (オンデマンド) モードを使用するイベントソースマッピングを持つ関数には、AWS PrivateLink VPC エンドポイントが必要です。イベントソースマッピングが[プロビジョンドモード](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)を使用している場合は、AWS PrivateLink VPC エンドポイントを設定する必要はありません。

エンドポイントを作成して、次のリソースへのアクセスを提供します。
+  Lambda — Lambda サービスプリンシパルのエンドポイントを作成します。
+  AWS STS — サービスプリンシパルがユーザーに代わってロールを引き受けるために、AWS STS のエンドポイントを作成します。
+  Secrets Manager — クラスターが Secrets Manager を使用して認証情報を保存する場合は、Secrets Manager のエンドポイントを作成します。

または、Amazon VPC の各パブリックサブネットに NAT ゲートウェイを設定します。詳細については、「[VPC に接続された Lambda 関数にインターネットアクセスを有効にする](configuration-vpc-internet.md)」を参照してください。

セルフマネージド Apache Kafka のイベントソースマッピングを作成すると、Lambda は Amazon VPC に設定されたサブネットおよびセキュリティグループに Elastic Network Interface (ENI) が既に存在するかどうかを確認します。Lambda が既存の ENI を検出した場合、再利用しようとします。それ以外の場合、Lambda は新しい ENI を作成し、イベントソースに接続して関数を呼び出します。

**注記**  
Lambda 関数は、Lambda サービスが所有する VPC 内で常に実行されます。関数の VPC 設定はイベントソースマッピングに影響しません。Lambda がイベントソースに接続する方法を判定するのは、イベントソースのネットワーク設定のみです。

クラスターを含む Amazon VPC のセキュリティグループを設定します。デフォルトでは、セルフマネージド Apache Kafka はポート: `9092` を使用します。
+ インバウンドルール – イベントソースに関連付けられたセキュリティグループに対してデフォルトのブローカーポート上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、同じセキュリティグループ内のインスタンスからのアクセスを許可することもできます。
+ アウトバウンドルール – 関数が AWS サービスと通信する必要がある場合、外部送信先のポート `443` 上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、他の AWS サービスと通信する必要がない場合は、ブローカーへのアクセスを制限することもできます。
+ Amazon VPC エンドポイントのインバウンドルール – Amazon VPC エンドポイントを使用している場合、Amazon VPC エンドポイントに関連付けられたセキュリティグループは、クラスターセキュリティグループからポート `443` でインバウンドトラフィックを許可する必要があります。

クラスターが認証を使用する場合、Secrets Manager エンドポイントのエンドポイントポリシーを制限することもできます。Secrets Manager API を呼び出す場合、Lambda は Lambda サービスプリンシパルではなく、関数ロールを使用します。

**Example VPC エンドポイントポリシー – Secrets Manager エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "secretsmanager:GetSecretValue",
              "Effect": "Allow",
              "Principal": {
                  "AWS": [
                      "arn:aws::iam::123456789012:role/my-role"
                  ]
              },
              "Resource": "arn:aws::secretsmanager:us-west-2:123456789012:secret:my-secret"
          }
      ]
  }
```

Amazon VPC エンドポイントを使用する場合、AWS は API コールをルーティングし、エンドポイントの Elastic Network Interface (ENI) を使用して関数を呼び出します。Lambda サービスプリンシパルは、これらの ENI を使用するすべてのロールおよび関数に対して `lambda:InvokeFunction` を呼び出す必要があります。

デフォルトでは、Amazon VPC エンドポイントには、リソースへの広範なアクセスを許可するオープンな IAM ポリシーが適用されています。そのエンドポイントを使用して必要なアクションを実行するためのベストプラクティスは、これらのポリシーを制限することです。イベントソースマッピングが Lambda 関数を呼び出せるようにするには、VPC エンドポイントポリシーで、Lambda サービスプリンシパルが `sts:AssumeRole` および `lambda:InvokeFunction` を呼び出すことを許可する必要があります。組織内で発生する API コールのみを許可するように VPC エンドポイントポリシーを制限すると、イベントソースマッピングが正しく機能しなくなるため、これらのポリシーには `"Resource": "*"` が必要です。

次の VPC エンドポイントポリシーの例では、AWS STS および Lambda エンドポイントに Lambda サービスプリンシパルの必要なアクセスを付与する方法について示しています。

**Example VPC エンドポイントポリシー - AWS STS エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
    }
```

**Example VPC エンドポイントポリシー – Lambda エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "lambda:InvokeFunction",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
  }
```

# Lambda 実行ロールのアクセス許可の設定
<a name="with-kafka-permissions"></a>

[セルフマネージド Kafka クラスターへのアクセス](kafka-cluster-auth.md)に加えて、Lambda 関数にはさまざまな API アクションを実行するための許可が必要です。これらの許可は、関数の[実行ロール](lambda-intro-execution-role.md)に追加します。ユーザーが API アクションのいずれかにアクセスする必要がある場合は、AWS Identity and Access Management (IAM) ユーザーまたはロールのアイデンティティポリシーに必要な許可を追加します。

**Topics**
+ [Lambda 関数に必要なアクセス許可](#smaa-api-actions-required)
+ [Lambda 関数のオプションのアクセス許可](#smaa-api-actions-optional)
+ [実行ロールへのアクセス許可の追加](#smaa-permissions-add-policy)
+ [IAM ポリシーを使用したユーザーアクセスの許可](#smaa-permissions-add-users)

## Lambda 関数に必要なアクセス許可
<a name="smaa-api-actions-required"></a>

Amazon CloudWatch Logs のロググループでログを作成して保存するには、Lambda 関数の実行ロールに以下の許可が必要です。
+ [logs:CreateLogGroup](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html)
+ [logs:CreateLogStream](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogStream.html)
+ [logs:PutLogEvents](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html)

## Lambda 関数のオプションのアクセス許可
<a name="smaa-api-actions-optional"></a>

Lambda 関数には、以下を実行する許可も必要になる場合があります。
+ Secrets Manager シークレットを記述する。
+ AWS Key Management Service (AWS KMS) カスタマー管理のキーにアクセスする。
+ Amazon VPC にアクセスする。
+ 失敗した呼び出しのレコードを送信先に送信します。

### Secrets Manager と AWS KMS 許可
<a name="smaa-api-actions-secrets"></a>

Kafka ブローカーに設定しているアクセスコントロールのタイプに応じて、Lambda 関数には Secrets Manager シークレットにアクセスするための許可、または AWS KMS カスタマーマネージドキーを復号化するための許可が必要になる場合があります。それらのリソースにアクセスするには、関数の実行ロールに次のアクセス許可が必要です。
+ [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)
+ [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)

### VPC アクセス許可
<a name="smaa-api-actions-vpc"></a>

セルフマネージド Apache Kafka クラスターにアクセスできるのが VPC 内のユーザーのみである場合、Lambda 関数には Amazon VPC リソースにアクセスするための許可が必要です。これらのリソースには、VPC、サブネット、セキュリティグループ、ネットワークインターフェイスが含まれます。それらのリソースにアクセスするには、関数の実行ロールに次のアクセス許可が必要です。
+ [ec2:CreateNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
+ [ec2:DescribeNetworkInterfaces](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
+ [ ec2:DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
+ [ ec2:DeleteNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
+ [ ec2:DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
+ [ ec2:DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)

## 実行ロールへのアクセス許可の追加
<a name="smaa-permissions-add-policy"></a>

セルフマネージド型 Apache Kafka クラスターが使用するその他の AWS サービスにアクセスするために、Lambda は、関数の[実行ロール](lambda-intro-execution-role.md)で定義されたアクセス許可ポリシーを使用します。

デフォルトでは、Lambda は、セルフマネージド型 Apache Kafka クラスターに対して、必須のまたはオプションのアクションを実行することはできません。こうしたアクションは、実行ロールの [IAM 信頼ポリシー](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-trust-policy.html)で作成および定義する必要があります。この例では、Lambda に Amazon VPC リソースへのアクセスを許可する、ポリシーの作成方法を紹介します。

------
#### [ JSON ]

****  

```
{
        "Version":"2012-10-17",		 	 	 
        "Statement":[
           {
              "Effect":"Allow",
              "Action":[
                 "ec2:CreateNetworkInterface",
                 "ec2:DescribeNetworkInterfaces",
                 "ec2:DescribeVpcs",
                 "ec2:DeleteNetworkInterface",
                 "ec2:DescribeSubnets",
                 "ec2:DescribeSecurityGroups"
              ],
              "Resource":"*"
           }
        ]
     }
```

------

## IAM ポリシーを使用したユーザーアクセスの許可
<a name="smaa-permissions-add-users"></a>

デフォルトでは、ユーザーおよびロールには[イベントソースの API オペレーション](invocation-eventsourcemapping.md#event-source-mapping-api)を実行するアクセス許可がありません。組織またはアカウント内のユーザーにアクセス権を付与するには、アイデンティティベースのポリシーを作成または更新します。詳細については、「*IAM ユーザーガイド*」の「[ポリシーを使用した AWS リソースへのアクセス制御](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_controlling.html)」を参照してください。

認証および承認エラーをトラブルシューティングするには、「[セルフマネージド Kafka イベントソースマッピングエラーのトラブルシューティング](with-kafka-troubleshoot.md)」を参照してください。

# Lambda 用のセルフマネージド Apache Kafka をイベントソースの設定
<a name="with-kafka-configure"></a>

セルフマネージド Apache Kafka クラスターを Lambda 関数のイベントソースとして使用するには、2 つのリソースを接続する[イベントソースマッピング](invocation-eventsourcemapping.md)を作成します。このページでは、セルフマネージド Apache Kafka 用にイベントソースマッピングを作成する方法について説明します。

このページの説明は、Kafka クラスターおよびそのクラスターが存在するネットワークを正しく設定済みであることを前提としています。クラスターまたはネットワークをセットアップする必要がある場合は、「[Lambda 用のセルフマネージド Apache Kafka クラスターとネットワークの設定](with-kafka-cluster-network.md)」を参照してください。

**Topics**
+ [イベントソースとしてセルフマネージド Apache Kafka クラスターを使用する](#kafka-esm-overview)
+ [Lambda でのクラスターの認証方法の設定](kafka-cluster-auth.md)
+ [セルフマネージド Apache Kafka イベントソース用に Lambda イベントソースマッピングを作成する](kafka-esm-create.md)
+ [Lambda の全セルフマネージド Apache Kafka イベントソース設定パラメータ](kafka-esm-parameters.md)

## イベントソースとしてセルフマネージド Apache Kafka クラスターを使用する
<a name="kafka-esm-overview"></a>

Apache Kafka クラスターまたは Amazon MSK クラスターを Lambda 関数のトリガーとして追加すると、クラスターは[イベントソース](invocation-eventsourcemapping.md)として使用されます。

Lambda は、ユーザーが指定した[開始位置](kafka-starting-positions.md)に基づいて、[CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) リクエストで `Topics` として指定した Kafka トピックからイベントデータを読み取ります。処理が成功すると、Kafka トピックは Kafka クラスターにコミットされます。

Lambda は、Kafka トピックの各パーティションのメッセージを順番に読み込みます。1 つの Lambda ペイロードに、複数のパーティションからのメッセージを含めることができます。利用可能なレコードが増えると、Lambda は [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) リクエストで指定した BatchSize 値に基づいて、関数がトピックに追いつくまでバッチ単位でレコードの処理を継続します。

Lambda は各バッチを処理した後、そのバッチ内のメッセージのオフセットをコミットします。関数がバッチ内のいずれかのメッセージに対してエラーを返すと、Lambda は、処理が成功するかメッセージが期限切れになるまでメッセージのバッチ全体を再試行します。すべての再試行が失敗したレコードを、障害発生時の送信先に送信して、後で処理することができます。

**注記**  
Lambda 関数の最大タイムアウト制限は通常 15 分ですが、Amazon MSK、自己管理型 Apache Kafka、Amazon DocumentDB、および ActiveMQ と RabbitMQ 向け Amazon MQ のイベントソースマッピングでは、最大タイムアウト制限が 14 分の関数のみがサポートされます。

# Lambda でのクラスターの認証方法の設定
<a name="kafka-cluster-auth"></a>

Lambda は、セルフマネージド型 Apache Kafka クラスターで認証するための方法をいくつかサポートしています。これらのサポートされる認証方法のいずれかを使用するように、Kafka クラスターを設定しておいてください。Kafka セキュリティの詳細については、Kafka ドキュメントの「[セキュリティ](http://kafka.apache.org/documentation.html#security)」セクションを参照してください。

## SASL/SCRAM 認証
<a name="smaa-auth-sasl"></a>

Lambda は、Transport Layer Security (TLS) 暗号化 (`SASL_SSL`) を使用した Simple Authentication and Security Layer/Salted Challenge Response Authentication Mechanism (SASL/SCRAM) 認証をサポートしています。Lambda は、暗号化された認証情報を送信してクラスターで認証します。Lambda は plaintext の SASL/PLAIN (`SASL_PLAINTEXT`) をサポートしません。SASL/SCRAM 認証の詳細については、「[RFC 5802](https://tools.ietf.org/html/rfc5802)」を参照してください。

Lambda は SASL/PLAIN 認証もサポートします。このメカニズムはクリアテキスト認証情報を使用するので、この認証情報が保護されることを確実にするためにも、サーバーへの接続には TLS 暗号化を使用する必要があります。

SASL 認証の場合は、サインイン認証情報をシークレットとして AWS Secrets Manager に保存します。Secrets Manager の使用の詳細については、「*AWS Secrets Manager ユーザーガイド*」の「[AWS Secrets Manager シークレットの作成](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)」を参照してください。

**重要**  
認証に Secrets Manager を使用するには、シークレットを Lambda 関数と同じ AWS リージョンに保存する必要があります。

## 相互 TLS 認証
<a name="smaa-auth-mtls"></a>

相互 TLS (mTLS) は、クライアントとサーバー間の双方向認証を提供します。クライアントは、サーバーによるクライアントの検証のためにサーバーに証明書を送信し、サーバーは、クライアントによるサーバーの検証のためにクライアントに証明書を送信します。

セルフマネージド Apache Kafka では、Lambda がクライアントとして機能します。Kafka ブローカーで Lambda を認証するように、クライアント証明書を (Secrets Manager のシークレットとして) 設定します。クライアント証明書は、サーバーのトラストストア内の CA によって署名される必要があります。

Kafka クラスターは、Lambda で Kafka ブローカーを認証するために Lambda にサーバー証明書を送信します。サーバー証明書は、パブリック CA 証明書またはプライベート CA/自己署名証明書にすることができます。パブリック CA 証明書は、Lambda トラストストア内の認証局 (CA) によって署名される必要があります。プライベート CA/自己署名証明書の場合は、サーバルート CA 証明書を (Secrets Manager のシークレットとして) 設定します。Lambda はルート証明書を使用して Kafka ブローカーを検証します。

mTLS の詳細については、「[Introducing mutual TLS authentication for Amazon MSK as an event source](https://aws.amazon.com/blogs/compute/introducing-mutual-tls-authentication-for-amazon-msk-as-an-event-source)」(イベントソースとしての Amazon MSK のための相互 TLS の紹介) を参照してください。

## クライアント証明書シークレットの設定
<a name="smaa-auth-secret"></a>

CLIENT\$1CERTICATE\$1TLS\$1AUTH シークレットは、証明書フィールドとプライベートキーフィールドを必要とします。暗号化されたプライベートキーの場合、シークレットはプライベートキーのパスワードを必要とします。証明書とプライベートキーは、どちらも PEM 形式である必要があります。

**注記**  
Lambda は、[PBES1](https://datatracker.ietf.org/doc/html/rfc2898/#section-6.1) (PBES2 ではありません) プライベートキー暗号化アルゴリズムをサポートします。

証明書フィールドには、クライアント証明書で始まり、その後に中間証明書が続き、ルート証明書で終わる証明書のリストが含まれている必要があります。各証明書は、以下の構造を使用した新しい行で始める必要があります。

```
-----BEGIN CERTIFICATE-----  
            <certificate contents>
-----END CERTIFICATE-----
```

Secrets Manager は最大 65,536 バイトのシークレットをサポートします。これは、長い証明書チェーンにも十分な領域です。

プライベートキーは、以下の構造を使用した [PKCS \$18](https://datatracker.ietf.org/doc/html/rfc5208) 形式にする必要があります。

```
-----BEGIN PRIVATE KEY-----  
             <private key contents>
-----END PRIVATE KEY-----
```

暗号化されたプライベートキーには、以下の構造を使用します。

```
-----BEGIN ENCRYPTED PRIVATE KEY-----  
              <private key contents>
-----END ENCRYPTED PRIVATE KEY-----
```

以下は、暗号化されたプライベートキーを使用する mTLS 認証のシークレットの内容を示す例です。暗号化されたプライベートキーの場合は、シークレットにプライベートキーのパスワードを含めます。

```
{"privateKeyPassword":"testpassword",
"certificate":"-----BEGIN CERTIFICATE-----
MIIE5DCCAsygAwIBAgIRAPJdwaFaNRrytHBto0j5BA0wDQYJKoZIhvcNAQELBQAw
...
j0Lh4/+1HfgyE2KlmII36dg4IMzNjAFEBZiCRoPimO40s1cRqtFHXoal0QQbIlxk
cmUuiAii9R0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFgjCCA2qgAwIBAgIQdjNZd6uFf9hbNC5RdfmHrzANBgkqhkiG9w0BAQsFADBb
...
rQoiowbbk5wXCheYSANQIfTZ6weQTgiCHCCbuuMKNVS95FkXm0vqVD/YpXKwA/no
c8PH3PSoAaRwMMgOSA2ALJvbRz8mpg==
-----END CERTIFICATE-----",
"privateKey":"-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFKzBVBgkqhkiG9w0BBQ0wSDAnBgkqhkiG9w0BBQwwGgQUiAFcK5hT/X7Kjmgp
...
QrSekqF+kWzmB6nAfSzgO9IaoAaytLvNgGTckWeUkWn/V0Ck+LdGUXzAC4RxZnoQ
zp2mwJn2NYB7AZ7+imp0azDZb+8YG2aUCiyqb6PnnA==
-----END ENCRYPTED PRIVATE KEY-----"
}
```

## サーバルート CA 証明書シークレットの設定
<a name="smaa-auth-ca-cert"></a>

このシークレットは、Kafka ブローカーがプライベート CA によって署名された証明書で TLS 暗号化を使用する場合に作成します。TLS 暗号化は、VPC、SASL/SCRAM、SASL/PLAIN、または mTLS 認証に使用できます。

サーバールート CA 証明書シークレットには、PEM 形式の Kafka ブローカーのルート CA 証明書が含まれるフィールドが必要です。以下は、このシークレットの構造を示す例です。

```
{"certificate":"-----BEGIN CERTIFICATE-----
MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dG...
-----END CERTIFICATE-----"
}
```

# セルフマネージド Apache Kafka イベントソース用に Lambda イベントソースマッピングを作成する
<a name="kafka-esm-create"></a>

イベントソースマッピングの作成には、Lambda コンソール、[AWS Command Line Interface (CLI)](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)、[AWS SDK](https://aws.amazon.com/getting-started/tools-sdks/) のいずれかを使用できます。

次のコンソールの手順で、Lambda 関数のトリガーとしてセルフマネージド Apache Kafka クラスターを追加します。内部でイベントソースマッピングリソースが作成されます。

## 前提条件
<a name="kafka-esm-prereqs"></a>
+ セルフマネージド型 Apache Kafka クラスター。Lambda は、Apache Kafka バージョン 0.10.1.0 以降をサポートしています。
+ セルフマネージド Kafka クラスターが使用する AWS リソースにアクセスするための許可を持つ[実行ロール](lambda-intro-execution-role.md)。

## セルフマネージド型 Kafka クラスターを追加する (コンソール)
<a name="kafka-esm-console"></a>

セルフマネージド型 Apache Kafka クラスターと Kafka トピックを Lambda 関数のトリガーとして追加するには、次の手順を実行します。

**Apache Kafka トリガーを Lambda 関数に追加するには (コンソール)**

1. Lambda コンソールの [[Functions] (関数) ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. Lambda 関数の名前を選択します。

1. [**機能の概要**] で、[**トリガーを追加**] を選択します。

1. [**Trigger configuration**] (トリガー設定) で次の操作を実行します。

   1. **Apache Kafka** のトリガータイプを選択します。

   1. [**Bootstrap servers**] (ブートストラップサーバー) に、クラスター内の Kafka ブローカーのホストおよびポートのペアアドレスを入力し、[**Add**] (追加) を選択します。クラスター内の各 Kafka ブローカーで上記を繰り返します。

   1. [**Topic name**] (トピック名) に、クラスター内のレコードの保存に使用する Kafka トピックの名前を入力します。

   1. プロビジョンドモードを設定する場合は、**[最小イベントポーラー]** の値、**[最大イベントポーラー]** の値、PollerGroupName のオプションの値を入力して、同じイベントソース VPC 内の複数の ESM のグループ化を指定します。

   1. (オプション) [**Batch size**] (バッチサイズ) に、単一のバッチで取得できるメッセージの最大数を入力します。

   1. **バッチウィンドウ** では、Lambda が関数を呼び出すまで費やすレコード収集の最大時間 (秒) を入力します。

   1. (オプション) **コンシューマーグループ ID** で、参加する Kafka コンシューマーグループの ID を入力します。

   1. (オプション) **[開始位置]** で、**[最新]** を選択して最新のレコードからストリームの読み取りを開始するか、**[水平トリム]** を選択して使用可能な最も以前のレコードから開始するか、または **[タイムスタンプ時点]** を選択して読み取りを開始するタイムスタンプを指定します。

   1. (オプション) **[VPC]** で、Kafka クラスターに Amazon VPC を選択します。次に、**[VPC subnets]** (VPC サブネット) と **[VPC security groups]** (VPC セキュリティグループ) を選択します。

      VPC 内のユーザーのみがブローカーにアクセスする場合、この設定は必須です。

      

   1. (オプション) **[Authentication]** (認証) で **[Add]** (追加) をクリックしてから、以下を実行します。

      1. クラスター内の Kafka ブローカーのアクセスまたは認証プロトコルを選択します。
         + Kafka ブローカーが SASL/PLAIN 認証を使用する場合は、**[BASIC\$1AUTH]** を選択します。
         + ブローカーが SASL/SCRAM 認証を使用する場合は、**[SASL\$1SCRAM]** プロトコルのいずれかを選択します。
         + mTLS 認証を設定している場合は、**[CLIENT\$1CERTIFICATE\$1TLS\$1AUTH]** プロトコルを選択します。

      1. SASL/SCRAM または mTLS 認証の場合は、Kafka クラスターの認証情報が含まれる Secrets Manager シークレットキーを選択します。

   1. (オプション) Kafka ブローカーがプライベート CA によって署名された証明書を使用する場合、**[Encryption]** (暗号化) には Kafka ブローカーが TLS 暗号化に使用するルート CA 証明書が含まれる Secrets Manager シークレットを選択します。

      この設定は、SASL/SCRAM または SASL/PLAIN の TLS 暗号化、および mTLS 認証に適用されます。

   1. テスト用に無効状態のトリガーを作成する (推奨) には、[**Enable trigger**] (トリガーを有効にする) を解除します。または、トリガーをすぐに有効にするには、[**Enable trigger**] (トリガーを有効にする) を選択します。

1. トリガーを追加するには、[**Add**] (追加) を選択します。

## セルフマネージド型 Kafka クラスターを追加する (AWS CLI)
<a name="kafka-esm-cli"></a>

Lambda 関数のセルフマネージド型 Apache Kafka トリガーを作成および表示するには、次の AWS CLI コマンドの例を使用します。

### SASL/SCRAM を使用する
<a name="kafka-esm-cli-create"></a>

Kafka ユーザーがインターネット経由で Kafka ブローカーにアクセスする場合は、SASL/SCRAM 認証用に作成した Secrets Manager シークレットを指定します。次の例では、[create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) AWS CLI コマンドを使用して、`my-kafka-function` という名前の Lambda 関数を `AWSKafkaTopic` という名前の Kafka トピックにマッピングします。

```
aws lambda create-event-source-mapping \ 
  --topics AWSKafkaTopic \
  --source-access-configuration Type=SASL_SCRAM_512_AUTH,URI=arn:aws:secretsmanager:us-east-1:111122223333:secret:MyBrokerSecretName \
  --function-name arn:aws:lambda:us-east-1:111122223333:function:my-kafka-function \
  --self-managed-event-source '{"Endpoints":{"KAFKA_BOOTSTRAP_SERVERS":["abc3.xyz.com:9092", "abc2.xyz.com:9092"]}}'
```

### VPC の使用
<a name="kafka-esm-cli-create-vpc"></a>

Kafka ブローカーにアクセスするのが VPC 内の Kafka ユーザーのみである場合、VPC、サブネット、および VPC セキュリティグループを指定する必要があります。次の例では、[create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) AWS CLI コマンドを使用して、`my-kafka-function` という名前の Lambda 関数を `AWSKafkaTopic` という名前の Kafka トピックにマッピングします。

```
aws lambda create-event-source-mapping \ 
  --topics AWSKafkaTopic \
  --source-access-configuration '[{"Type": "VPC_SUBNET", "URI": "subnet:subnet-0011001100"}, {"Type": "VPC_SUBNET", "URI": "subnet:subnet-0022002200"}, {"Type": "VPC_SECURITY_GROUP", "URI": "security_group:sg-0123456789"}]' \
  --function-name arn:aws:lambda:us-east-1:111122223333:function:my-kafka-function \
  --self-managed-event-source '{"Endpoints":{"KAFKA_BOOTSTRAP_SERVERS":["abc3.xyz.com:9092", "abc2.xyz.com:9092"]}}'
```

### AWS CLI を使用したステータスの表示
<a name="kafka-esm-cli-view"></a>

次の例では、[get-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html) AWS CLI コマンドを使用して、作成したイベントソースマッピングのステータスを記述します。

```
aws lambda get-event-source-mapping
              --uuid dh38738e-992b-343a-1077-3478934hjkfd7
```

# Lambda の全セルフマネージド Apache Kafka イベントソース設定パラメータ
<a name="kafka-esm-parameters"></a>

すべての Lambda イベントソースタイプは、同じ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションを共有しています。ただし、次のテーブルで示されるように、セルフマネージド Apache Kafka に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | メモ | 
| --- | --- | --- | --- | 
|  BatchSize  |  N  |  100  |  最大: 10,000  | 
|  DestinationConfig  |  いいえ  |  該当なし  |  [Amazon MSK とセルフマネージド Apache Kafka イベントソースの破棄されたバッチのキャプチャ](kafka-on-failure.md)  | 
|  有効  |  いいえ  |  正  |  | 
|  FilterCriteria  |  いいえ  |  該当なし  |  [Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)  | 
|  FunctionName  |  はい  |  該当なし  |    | 
|  KMSKeyArn  |  いいえ  |  該当なし  |  [フィルター条件の暗号化](invocation-eventfiltering.md#filter-criteria-encryption)  | 
|  MaximumBatchingWindowInSeconds  |  いいえ  |  500 ミリ秒  |  [バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)  | 
|  ProvisionedPollersConfig  |  いいえ  |  `MinimumPollers`: 指定しない場合のデフォルト値は 1 `MaximumPollers`: 指定しない場合のデフォルト値は 200 `PollerGroupName`: 該当なし  |  [プロビジョニングモード](kafka-scaling-modes.md#kafka-provisioned-mode)  | 
|  SelfManagedEventSource  |  はい  | 該当なし |  Kafka ブローカー一覧 作成時にのみ設定可能  | 
|  SelfManagedKafkaEventSourceConfig  |  いいえ  |  ConsumerGroupID フィールドを含み、デフォルトでは一意の値になっています。  |  作成時にのみ設定可能  | 
|  SourceAccessConfigurations  |  N  |  認証情報なし  |  クラスターの VPC 情報または認証情報   SASL\$1PLAIN は、BASIC\$1AUTH に設定  | 
|  StartingPosition  |  はい  |  該当なし  |  AT\$1TIMESTAMP、TRIM\$1HORIZON、または LATEST 作成時にのみ設定可能  | 
|  StartingPositionTimestamp  |  いいえ  |  該当なし  |  StartingPosition が AT\$1TIMESTAMP に設定されている場合にのみ必要  | 
|  タグ  |  いいえ  |  該当なし  |  [イベントソースマッピングでのタグの使用](tags-esm.md)  | 
|  トピック  |  はい  |  該当なし  |  トピック名 作成時にのみ設定可能  | 

**注記**  
`PollerGroupName` を指定すると、同じ Amazon VPC 内の複数の ESM イベントポーラーユニット (EPU) 容量を共有できます。このオプションを使用して、ESM プロビジョンドモードコストを最適化できます。ESM グループ化の要件:  
ESM は同じ Amazon VPC 内にある必要があります
ポーラーグループあたり最大 100 ESM
グループ内のすべての ESM の合計最大ポーラー数は 2,000 を超えることはできません
`PollerGroupName` を更新して ESM を別のグループに移動するか、`PollerGroupName` を空の文字列 ("") に設定して ESM をグループから削除できます。

# Lambda での Apache Kafka イベントポーラーのスケーリングモード
<a name="kafka-scaling-modes"></a>

Amazon MSK およびセルフマネージド Apache Kafka イベントソースマッピングのイベントポーラースケーリングについて、2 つのモードのいずれかを選択できます。
+ [オンデマンドモード (デフォルト)](#kafka-default-mode)
+ [プロビジョニングモード](#kafka-provisioned-mode)

## オンデマンドモード (デフォルト)
<a name="kafka-default-mode"></a>

初めて Kafka イベントソースを作成すると、Lambda は Kafka トピック内のすべてのパーティションを処理するために、デフォルトの数のイベントポーラーを割り当てます。Lambda は、メッセージ負荷に基づいて[イベントポーラー](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)の数を自動的にスケールアップまたはスケールダウンします。

Lambda は、1 分間隔でトピック内のすべてのパーティションのオフセットラグを評価します。オフセットラグが大きすぎる場合、パーティションは Lambda で処理できる速度よりも速くメッセージを受信します。必要に応じて、Lambda はトピックのイベントポーラーを追加または削除します。イベントポーラーを追加または削除するこの自動スケーリングプロセスは、評価から 3 分以内に実行されます。

ターゲットの Lambda 関数がスロットリングされると、Lambda はイベントポーラーの数を減らします。このアクションにより、イベントポーラーが関数から取得するメッセージ、および関数に送信するメッセージの数が減ることで、関数に対する負荷が軽減されます。

## プロビジョニングモード
<a name="kafka-provisioned-mode"></a>

イベントソースマッピングのスループットを微調整する必要があるワークロードでは、プロビジョンドモードを使用できます。プロビジョンドモードでは、プロビジョニングされたイベントポーラーの最小数と最大数を定義します。これらのプロビジョニングされたイベントポーラーは、イベントソースマッピング専用であり、応答性の高い自動スケーリングによって予期しないメッセージスパイクを処理できます。パフォーマンス要件が厳しい Kafka ワークロードには、プロビジョンドモードを使用することをお勧めします。

Lambda では、イベントポーラーは、イベントソースタイプによって異なるスループット機能を備えたコンピューティングユニットです。Amazon MSK およびセルフマネージド Apache Kafka の場合、各イベントポーラーは最大 5 MB/秒のスループットまたは最大 5 個の同時呼び出しを処理できます。例えば、イベントソースが 1 MB の平均ペイロードを生成し、関数の平均時間が 1 秒の場合、単一の Kafka イベントポーラーは 5 MB/秒のスループットと 5 個の同時 Lambda 呼び出しをサポートできます (ペイロード変換がないと仮定)。Amazon SQS の場合、各イベントポーラーは最大 1 MB/秒のスループットまたは最大 10 個の同時呼び出しを処理できます。プロビジョンドモードを使用すると、イベントポーラーの使用状況に基づいて追加コストが発生します。料金の詳細については、「[AWS Lambda の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。

**注記**  
プロビジョンドモードを使用する場合は、AWS PrivateLink VPC エンドポイントを作成したり、関連するアクセス許可をネットワーク設定の一部として付与したりする必要はありません。

プロビジョンドモードでは、イベントポーラーの最小数 (`MinimumPollers`) の許容値の範囲は 1～200 です。イベントポーラーの最大数 (`MaximumPollers`) の許容値の範囲は 1～2,000 です。`MaximumPollers` は `MinimumPollers` 以上である必要があります。また、パーティション内での順序付き処理を維持するために、Lambda は `MaximumPollers` をトピック内のパーティション数に制限します。

イベントポーラーの最小数および最大数に適切な値を選択する方の詳細については、「[ベストプラクティス](#kafka-provisioned-mode-bp)」を参照してください。

Kafka イベントソースマッピングのプロビジョンドモードを設定するには、コンソールまたは Lambda API を使用できます。

**既存のイベントソースマッピングに対してプロビジョンドモードを設定する手順 (コンソール)**

1. Lambda コンソールの「[関数](https://console.aws.amazon.com/lambda/home#/functions)」ページを開きます。

1. プロビジョンドモードを設定するイベントソースマッピングを持つ関数を選択します。

1. **[設定]** タブを選択し、**[トリガー]** を選択します。

1. プロビジョンドモードを設定するイベントソースマッピングを選択し、**[編集]** を選択します。

1. **[プロビジョニングモード]** で、**[設定]** を選択します。
   + **[最小イベントポーラー数]** に、1～200 の値を入力します。値を指定しない場合、Lambda はデフォルト値 1 を選択します。
   + **[最大イベントポーラー数]** に、1～2,000 の値を入力します。この値は、**[最小イベントポーラー数]** の値以上である必要があります。値を指定しない場合、Lambda はデフォルト値 200 を選択します。

1. **[保存]** を選択します。

[EventSourceMappingConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_EventSourceMappingConfiguration.html) の [ProvisionedPollerConfig](https://docs.aws.amazon.com/lambda/latest/api/API_ProvisionedPollerConfig.html) オブジェクトを使用して、プログラムでプロビジョンドモードを設定できます。例えば、次の [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) CLI コマンドは、`MinimumPollers` 値を 5、`MaximumPollers` 値を 100 に設定します。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{"MinimumPollers": 5, "MaximumPollers": 100}'
```

プロビジョニングモードを設定すると、`ProvisionedPollers` メトリクスをモニタリングすることで、ワークロードのイベントポーラーの使用状況を確認できます。詳細については、「[イベントソースマッピングメトリクス](monitoring-metrics-types.md#event-source-mapping-metrics)」を参照してください。

プロビジョンドモードを無効にしてデフォルト (オンデマンド) モードに戻すには、次の [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) CLI コマンドを使用できます。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{}'
```

## 高度なエラー処理とパフォーマンス機能
<a name="services-kafka-advanced-features"></a>

プロビジョンドモードが有効になっている Kafka イベントソースマッピングでは、エラー処理とパフォーマンスを向上させる追加機能を設定できます。
+ [再試行設定](kafka-retry-configurations.md) – 最大再試行回数、レコード経過時間制限、バッチ分割、部分的なバッチレスポンスを使用して、Lambda が失敗したレコードを処理する方法を制御します。
+ [Kafka の障害発生時の送信先](kafka-on-failure-destination.md) – 失敗したレコードを Kafka トピックに送信し、後で処理または分析します。

## プロビジョンドモードを使用する際のベストプラクティスと考慮事項
<a name="kafka-provisioned-mode-bp"></a>

イベントソースマッピングの最小および最大イベントポーラー数の最適な設定は、アプリケーションのパフォーマンス要件によって異なります。パフォーマンスプロファイルのベースラインを確立する際には、最初はデフォルトの最小イベントポーラー数から始めることをお勧めします。観測されたメッセージ処理パターンと望ましいパフォーマンスプロファイルに基づいて設定を調整します。

トラフィックの急増が発生しやすく、厳格なパフォーマンス要件があるワークロードの場合、メッセージの突然の急増を処理できるように、最小イベントポーラーを増やします。必要な最小イベントポーラー数を決定するには、ワークロードの 1 秒あたりのメッセージ数と平均ペイロードサイズを考慮し、1 つのイベントポーラーのスループットキャパシティ (最大 5 MBps) を参考にします。

パーティション内での順序付き処理を維持するために、Lambda は最大イベントポーラー数をトピック内のパーティション数に制限します。さらに、イベントソースマッピングがスケーリングできる最大イベントポーラー数は、関数の同時実行設定によって異なります。

プロビジョンドモードを有効にする際には、ネットワーク設定を更新して AWS PrivateLink VPC エンドポイントと関連するアクセス許可を削除します。

## プロビジョンドモードのコスト最適化
<a name="kafka-cost-optimization"></a>

### プロビジョンドモードの料金
<a name="kafka-provisioned-pricing"></a>

プロビジョンドモードは、プロビジョニングされた最小イベントポーラーと、自動スケーリング中に消費されたイベントポーラーに基づいて課金されます。料金は、Event Poller Unit (EPU) と呼ばれる請求単位を使用して計算されます。Event-Poller-Unit-hours で測定される、使用された EPU の数と期間に対して料金が発生します。プロビジョンドモードは、パフォーマンス重視のアプリケーション用に 1 つの ESM で使用することも、同じ VPC 内で複数の ESM をグループ化して EPU の容量とコストを共有することもできます。プロビジョンドモードのコストを最適化するのに役立つ 2 つの機能について詳しく説明します。料金の詳細については、「[AWS Lamdba の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。

### EPU 使用率の向上
<a name="kafka-enhanced-epu-utilization"></a>

各 EPU は、イベントポーリング用に最大 20 MB/秒のスループットキャパシティをサポートし、デフォルトの 10 個のイベントポーラーをサポートします。最小ポーラーと最大ポーラーを設定して Kafka ESM のプロビジョンドモードを作成すると、デフォルトで EPU あたり 10 個のイベントポーラーに基づき、最小ポーラー数を使用して EPU をプロビジョニングします。ただし、各イベントポーラーは、最大 5 MB/秒のスループット容量をサポートするように個別にスケーリングできます。特定の EPU でイベントポーラーの密度を低くする必要がありますが、EPU のスケーリングをトリガーできます。EPU に割り当てられるイベントポーラーの数は、各イベントポーラーが消費するコンピューティング容量によって異なります。EPU 使用率を高めるこのアプローチにより、さまざまなスループット要件を持つイベントポーラーは EPU 容量を効果的に活用できるようになり、すべての ESM のコスト削減が実現します。

### ESM のグループ化
<a name="kafka-esm-grouping-cost"></a>

プロビジョンドモードのコストをさらに最適化するには、複数の Kafka ESM をグループ化して EPU 容量を共有できます。ESM グループ化と EPU 使用率の拡張を使用すると、単一 ESM モードの実行と比較して、低スループットワークロードのプロビジョンドモードのコストを最大 90% 削減できます。1 つ未満の EPU 容量を必要とするすべての ESM は、ESM グループ化の恩恵を受けます。このような ESM では通常、スループットのニーズをサポートするために必要になる最小限のイベントポーラーはほとんどありません。この機能を使用すると、すべての Kafka ワークロードにプロビジョンドモードを採用でき、スキーマ検証、Avro/Protobuf イベントのフィルタリング、低レイテンシー呼び出し、プロビジョンドモードでしか利用できない拡張エラー処理などの機能を利用できます。

同じ Amazon VPC 内の複数の ESM に対して同じ値で `PollerGroupName` パラメータを設定すると、それらの ESM、それぞれが専用 EPU 容量を必要とするのではなく、EPU リソースを共有します。ポーラーグループごとに最大 100 ESM をグループ化でき、グループ内のすべての ESM における合計最大ポーラー数は 2,000 を超えることはできません。

#### ESM グループを設定するには (コンソール)
<a name="kafka-esm-grouping-console-cost"></a>

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. **[設定]** を選択し、**[トリガー]** を選択します。

1. 新しい Kafka イベントソースマッピングを作成するとき、または既存のマッピングを編集するときは、**[プロビジョンドモード]** で **[設定]** を選択します。

1. **[最小イベントポーラー数]** に、1～200 の値を入力します。

1. **[最大イベントポーラー数]** に、1～2,000 の値を入力します。

1. **[Poller グループ名]**には、グループの識別子を入力します。グループ化する他の ESM には同じ名前を使用します。

1. **[保存]** を選択します。

#### ESM グループを設定するには (AWS CLI)
<a name="kafka-esm-grouping-cli-cost"></a>

次の例では、`production-app-group` という名前のポーラーグループを持つ ESM を作成します。

```
aws lambda create-event-source-mapping \
  --function-name myFunction1 \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/MyCluster/abcd1234 \
  --topics topic1 \
  --starting-position LATEST \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "production-app-group"
  }'
```

同じグループに別の ESM を追加するには (EPU 容量を共有)、同じ PollerGroupName を使用します。

```
aws lambda create-event-source-mapping \
  --function-name myFunction2 \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/MyCluster/abcd1234 \
  --topics topic2 \
  --starting-position LATEST \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "production-app-group"
  }'
```

**注記**  
`PollerGroupName` を更新して ESM を別のグループに移動するか、`PollerGroupName` に空の文字列 ("") を渡すことで ESM をグループから削除できます。

```
# Move ESM to a different group
aws lambda update-event-source-mapping \
  --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": "new-group-name"
  }'

# Remove ESM from group (use dedicated resources)
aws lambda update-event-source-mapping \
  --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
  --provisioned-poller-config '{
    "MinimumPollers": 1, 
    "MaximumPollers": 10, 
    "PollerGroupName": ""
  }'
```

#### グループ化の実施に関する考慮事項
<a name="kafka-grouping-strategy-considerations"></a>
+ **アプリケーションの境界** – コスト配分と管理の向上のために、同じアプリケーションまたはサービスに属する ESM をグループ化します。`app-name-environment` のような命名規則を使用することを検討してください (例: `order-processor-prod`)。
+ **トラフィックパターン** – リソースの競合につながる可能性があるため、高いスループットと急激なトラフィックパターンのある ESM をグループ化することは避けてください。
+ **ブラスト半径** – 共有インフラストラクチャで問題が発生した場合の影響を考慮してください。同じグループ内のすべての ESM は、共有リソースの制限の影響を受けます。ミッションクリティカルなワークロードでは、個別のグループまたは専用の ESM を使用できます。

#### コスト最適化の例
<a name="kafka-cost-optimization-example"></a>

それぞれが 1 つのイベントポーラーで設定され、スループットが 2 MB/秒未満の ESM が 10 個あるシナリオを考えてみましょう。

**グループ化なし:**
+ 各 ESM には専用の EPU が必要です
+ 必要な EPU の合計: 10
+ EPU あたりのコスト: 米国東部 (バージニア北部) では 0.185 USD/時間
+ 毎月の EPU コスト (720 時間): 10 × 720 × 0.185 USD = 1,332 USD

**グループ化の場合:**
+ 10 ESM すべてが EPU 容量を共有
+ 10 個のイベントポーラーを 1 EPU に収容 (EPU サポートごとに新しい 10 個のポーラーを使用)
+ 必要な EPU の合計: 1
+ 毎月の EPU コスト (720 時間): 1 × 720 × 0.185 USD = 133.20 USD
+ **コスト削減: 90%** (1 か月あたり 1,198.80 USD の削減)

# Lambda での Apache Kafka ポーリングとストリームの開始位置
<a name="kafka-starting-positions"></a>

[ StartingPosition パラメータ](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-StartingPosition)は、Amazon MSK またはセルフマネージド Apache Kafka ストリームからメッセージの読み取りを開始するタイミングを Lambda に指示します。選択できるオプションは 3 つあります。
+ **最新** – Lambda は Kafka トピックの最新レコードの直後から読み取りを開始します。
+ **水平線トリミング** – Lambda は Kafka トピック内のトリミングされていない最新レコードから読み取りを開始します。これはトピック内の最も古いレコードになります。
+ **タイムスタンプで** – Lambda は、タイムスタンプで定義された位置 (秒単位の Unix 時間) から読み取りを開始します 。[StartingPositionTimestamp パラメータ](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-StartingPositionTimestamp)を使用してタイムスタンプを指定します。

イベントソースマッピングの作成時、または更新が最終的に一貫性を持っている場合にポーリングをストリーミングしてください。
+ イベントソースマッピングの作成時、ストリームからのイベントのポーリングが開始されるまでに数分かかる場合があります。
+ イベントソースマッピングの更新時、ストリーミングからのイベントのポーリングの停止と再開に最大 90 秒かかる場合があります。

この挙動のため、`LATEST` をストリーミング開始位置として指定した場合、作成または更新時にイベントソースマッピングがいくつかのイベントを見逃す可能性があります。イベントが見逃されないようにするには、`TRIM_HORIZON` または `AT_TIMESTAMP` を指定してください。

# Lambda でのカスタマイズ可能なコンシューマーグループ ID
<a name="kafka-consumer-group-id"></a>

Amazon MSK または Apache Kafka をイベントソースとして設定する際、[コンシューマーグループ](https://developer.confluent.io/learn-more/kafka-on-the-go/consumer-groups/) ID を指定できます。このコンシューマーグループ ID は、Lambda 関数を結合したい Kafka コンシューマーグループの既存の識別子です。この機能を使用すると、実行中の Kafka レコード処理設定を他のコンシューマーから Lambda にシームレスに移行できます。

Kafka は、コンシューマーグループ内のすべてのコンシューマーにメッセージを配信します。他のアクティブなコンシューマーが存在するコンシューマーグループ ID を指定した場合、Lambda は Kafka トピックからメッセージの一部のみを受信します。Lambda にトピック内のすべてのメッセージを処理させたい場合、そのコンシューマーグループ内の他のコンシューマーをすべてオフにしてください。

さらに、ユーザーがコンシューマーグループ ID を指定し、Kafka が同じ ID を持つ有効な既存のコンシューマーグループを見つけた場合、Lambda は、イベントソースマッピングの [StartingPosition](kafka-starting-positions.md) を無視します。代わりに、Lambda はコンシューマーグループのコミットされたオフセットに従ってレコードの処理を開始します。コンシューマーグループ ID を指定しても、Kafka が既存のコンシューマーグループを見つけられない場合、Lambda は指定された `StartingPosition` を使用してイベントソースを設定します。

指定するコンシューマーグループ ID は、すべての Kafka イベントソースの中で一意でなければなりません。コンシューマーグループ ID を指定して Kafka イベントソースマッピングを作成した後は、この値を更新することはできません。

# Amazon MSK およびセルフマネージド Apache Kafka イベントソースからのイベントのフィルタリング
<a name="kafka-filtering"></a>

イベントフィルタリングを使用して、Lambda が関数に送信するストリームまたはキューからのレコードを制御することができます。イベントフィルタリングの仕組みに関する一般情報については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

**注記**  
Amazon MSK およびセルフマネージド Apache Kafka イベントソースマッピングは、`value` キーのフィルタリングのみをサポートします。

**Topics**
+ [Kafka イベントフィルタリングの基本](#filtering-kafka)

## Kafka イベントフィルタリングの基本
<a name="filtering-kafka"></a>

プロデューサーが Kafka クラスターのトピックに、有効な JSON 形式またはプレーン文字列として、メッセージを書き込むとします。レコードの例は次のようになり、`value` フィールドでメッセージが Base64 でエンコードされた文字列に変換されます。

```
{
    "mytopic-0":[
        {
            "topic":"mytopic",
            "partition":0,
            "offset":15,
            "timestamp":1545084650987,
            "timestampType":"CREATE_TIME",
            "value":"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
            "headers":[]
        }
    ]
}
```

Apache Kafka プロデューサーが次の JSON 形式でトピックにメッセージを書き込むとします。

```
{
    "device_ID": "AB1234",
    "session":{
        "start_time": "yyyy-mm-ddThh:mm:ss",
        "duration": 162
    }
}
```

`value` キーを使用してレコードをフィルタリングできます。`device_ID` が AB の文字で始まるレコードのみをフィルタリングするとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"value\" : { \"device_ID\" : [ { \"prefix\": \"AB\" } ] } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "value": {
        "device_ID": [ { "prefix": "AB" } ]
      }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "value" : { "device_ID" : [ { "prefix":  "AB" } ] } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:kafka:us-east-2:123456789012:cluster/my-cluster/b-8ac7cc01-5898-482d-be2f-a6b596050ea8 \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"value\" : { \"device_ID\" : [ { \"prefix\":  \"AB\" } ] } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"value\" : { \"device_ID\" : [ { \"prefix\":  \"AB\" } ] } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "value" : { "device_ID" : [ { "prefix":  "AB" } ] } }'
```

------

Kafka では、メッセージがプレーン文字列のレコードをフィルタリングすることもできます。文字列が「error」を含むメッセージを無視するとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"value\" : [ { \"anything-but\": [ \"error\" ] } ] }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "value": [
        {
        "anything-but": [ "error" ]
        }
    ]
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "value" : [ { "anything-but": [ "error" ] } ] }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:kafka:us-east-2:123456789012:cluster/my-cluster/b-8ac7cc01-5898-482d-be2f-a6b596050ea8 \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"value\" : [ { \"anything-but\": [ \"error\" ] } ] }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"value\" : [ { \"anything-but\": [ \"error\" ] } ] }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "value" : [ { "anything-but": [ "error" ] } ] }'
```

------

Kafka メッセージは UTF-8 でエンコードされた文字列 (プレーン文字列または JSON 形式) である必要があります。これは、Lambda がフィルター条件を適用する前に Kafka のバイト配列を UTF-8 にデコードするためです。メッセージが UTF-16 や ASCII などの別のエンコーディングを使用している場合、またはメッセージ形式が `FilterCriteria` 形式と一致しない場合、Lambda はメタデータフィルターのみを処理します。以下は、特定の動作を要約した表です。


| 着信メッセージの形式 | メッセージプロパティのフィルターパターン形式 | 結果として生じるアクション | 
| --- | --- | --- | 
|  プレーン文字列  |  プレーン文字列  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  プレーン文字列  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  プレーン文字列  |  有効な JSON  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  プレーン文字列  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  有効な JSON  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  UTF-8 以外でエンコードされた文字  |  JSON、プレーン文字列、またはパターンなし  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 

# Lambda での Kafka イベントソースとスキーマレジストリの使用
<a name="services-consume-kafka-events"></a>

 スキーマレジストリは、データストリームスキーマの定義と管理に役立ちます。スキーマ は、データレコードの構造と形式を定義します。Kafka イベントソースマッピングのコンテキストでは、Lambda 関数に到達する前に、事前定義されたスキーマに対して Kafka メッセージの構造と形式を検証するようにスキーマレジストリを設定できます。これにより、アプリケーションにデータガバナンスのレイヤーが追加され、イベントフィルタリングを通じてデータ形式を効率的に管理し、スキーマコンプライアンスを確保し、コストを最適化できます。

 この機能はすべてのプログラミング言語で機能しますが、以下の重要な点を考慮してください。
+ Powertools for Lambda は、Java、Python、TypeScript に固有のサポートを提供し、既存の Kafka 開発パターンとの一貫性を維持し、カスタム逆シリアル化コードなしでビジネスオブジェクトに直接アクセスできるようにします。
+ この機能は、プロビジョニングモードを使用したイベントソースマッピングでのみ使用できます。スキーマレジストリは、オンデマンドモードでのイベントソースマッピングをサポートしていません。プロビジョニングモードを使用していて、スキーマレジストリが設定されている場合、スキーマレジストリ設定を最初に削除しない限り、オンデマンドモードに変更することはできません。詳細については、[プロビジョンドモード](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)を参照してください。
+ イベントソースマッピング (ESM) ごとに設定できるスキーマレジストリは 1 つだけです。Kafka イベントソースでスキーマレジストリを使用すると、Lambda の Event Poller Unit (EPU) 使用量が増加する可能性があり、これはプロビジョンドモードの料金計算に影響します。

**Topics**
+ [スキーマレジストリオプション](#services-consume-kafka-events-options)
+ [Lambda が Kafka メッセージのスキーマ検証を実行する方法](#services-consume-kafka-events-how)
+ [Kafka スキーマレジストリの設定](#services-consume-kafka-events-config)
+ [Avro と Protobuf のフィルタリング](#services-consume-kafka-events-filtering)
+ [ペイロード形式と逆シリアル化の動作](#services-consume-kafka-events-payload)
+ [Lambda 関数での逆シリアル化されたデータの操作](#services-consume-kafka-events-payload-examples)
+ [スキーマレジストリの認証方法](#services-consume-kafka-events-auth)
+ [スキーマレジストリの問題のエラー処理とトラブルシューティング](#services-consume-kafka-events-troubleshooting)

## スキーマレジストリオプション
<a name="services-consume-kafka-events-options"></a>

 Lambda は、次のスキーマレジストリオプションをサポートしています。
+ [「AWS Glue スキーマレジストリ](https://docs.aws.amazon.com/glue/latest/dg/schema-registry.html)」
+ [Confluent クラウドスキーマレジストリ](https://docs.confluent.io/platform/current/schema-registry/index.html)
+ [セルフマネージド Confluent スキーマレジストリ](https://docs.confluent.io/platform/current/schema-registry/index.html)

 スキーマレジストリは、次のデータ形式のメッセージの検証をサポートしています。
+ Apache Avro
+ プロトコルバッファ (Protobuf)
+ JSON スキーマ (JSON-SE)

 スキーマレジストリを使用するには、まずイベントソースマッピングがプロビジョニングモードであることを確認します。スキーマレジストリを使用すると、Lambda はスキーマに関するメタデータをペイロードに追加します。詳細については、「[Payload formats and deserialization behavior](#services-consume-kafka-events-payload)」を参照してください。

## Lambda が Kafka メッセージのスキーマ検証を実行する方法
<a name="services-consume-kafka-events-how"></a>

 スキーマレジストリを設定すると、Lambda は Kafka メッセージごとに次の手順を実行します。

1. Lambda は、クラスターから Kafka レコードをポーリングします。

1. Lambda は、スキーマレジストリ内の特定のスキーマに対してレコード内の選択したメッセージ属性を検証します。
   + メッセージに関連付けられたスキーマがレジストリに見つからない場合、Lambda は理由コード `SCHEMA_NOT_FOUND` を使用してメッセージを DLQ に送信します。

1. Lambda は、スキーマレジストリ設定に従ってメッセージを逆シリアル化し、メッセージを検証します。イベントフィルタリングが設定されている場合、Lambda は設定されたフィルター条件に基づいてフィルタリングを実行します。
   + 逆シリアル化が失敗した場合、Lambda は理由コード `DESERIALIZATION_ERROR` を使用して DLQ にメッセージを送信します。DLQ が設定されていない場合、Lambda はメッセージを削除します。

1. メッセージがスキーマレジストリによって検証され、フィルター条件によって除外されない場合、Lambda はメッセージを使用して関数を呼び出します。

 この機能は、スキーマレジストリと統合された Kafka クライアントを使用して既に生成されたメッセージを検証することを目的としています。スキーマレジストリと連携するように Kafka プロデューサーを設定して、適切にフォーマットされたメッセージを作成することをお勧めします。

## Kafka スキーマレジストリの設定
<a name="services-consume-kafka-events-config"></a>

 次のコンソールステップでは、Kafka スキーマレジストリ設定をイベントソースマッピングに追加します。

**Kafka スキーマレジストリ設定をイベントソースマッピングに追加するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. **[設定]** を選択します。

1. **[トリガー]** を選択します。

1. スキーマレジストリを設定する Kafka イベントソースマッピングを選択し、**[編集]** を選択します。

1. **[イベントポーラー設定]** で、**[スキーマレジストリを設定]** を選択します。このオプションを表示するには、イベントソースマッピングがプロビジョニングモードになっている必要があります。

1. **[スキーマレジストリ URI]** には、AWS Glue スキーマレジストリの ARN、または Confluent Cloud スキーマレジストリまたはセルフマネージド Confluent スキーマレジストリの HTTPS URL を入力します。

1. 以下の設定ステップでは、Lambda にスキーマレジストリへのアクセス方法を指示します。詳細については、「[スキーマレジストリの認証方法](#services-consume-kafka-events-auth)」を参照してください。
   + **[アクセス設定タイプ]** で、Lambda がスキーマレジストリにアクセスするために使用する認証のタイプを選択します。
   + **[アクセス設定 URI]** には、該当する場合は Secrets Manager シークレットの ARN を入力して、スキーマレジストリで認証します。関数の[実行ロール](with-msk-permissions.md)に正しいアクセス許可が含まれていることを確認します。

1. **[暗号化]** フィールドは、スキーマレジストリがプライベート認証局 (CA) または Lambda トラストストアにない認証局 (CA) によって署名されている場合にのみ適用されます。該当する場合は、TLS 暗号化のためにスキーマレジストリで使用されるプライベート CA 証明書を含むシークレットキーを指定します。

1. **イベントレコード形式**で、スキーマ検証後に Lambda が関数にレコードを配信する方法を選択します。詳細については、「[Payload format examples](#services-consume-kafka-events-payload)」を参照してください。
   + **[JSON]** を選択した場合、Lambda は以下のスキーマ検証属性で選択した属性を標準 JSON 形式で配信します。選択しない属性については、Lambda がそのまま配信します。
   + **[SOURCE]** を選択した場合、Lambda は以下のスキーマ検証属性で選択した属性を元のソース形式で配信します。

1. **[スキーマ検証属性]** で、Lambda がスキーマレジストリを使用して検証および逆シリアル化するメッセージ属性を選択します。**[KEY]** または **[VALUE]** のどちらかを選択する必要があります。イベントレコード形式に [JSON] を選択した場合、[Lambda] は選択したメッセージ属性を関数に送信する前に逆シリアル化します。詳細については、「[Payload formats and deserialization behavior](#services-consume-kafka-events-payload)」を参照してください。

1. **[保存]** を選択します。

 Lambda API を使用して、スキーマレジストリ設定でイベントソースマッピングを作成または更新することもできます。次の例は、API *AWS Lambdaリファレンス*の [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) および [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) API オペレーションに対応する AWS CLIを使用して、AWS Glue または Confluent スキーマレジストリを設定する方法を示しています。

**重要**  
AWS CLI または `update-event-source-mapping` API を使用してスキーマレジストリ設定フィールドを更新する場合は、スキーマレジストリ設定のすべてのフィールドを更新する必要があります。

------
#### [ Create Event Source Mapping ]

```
aws lambda create-event-source-mapping \
  --function-name my-schema-validator-function \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/a1b2c3d4-5678-90ab-cdef-11111EXAMPLE \
  --topics my-kafka-topic \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=1 \
  --amazon-managed-kafka-event-source-mapping '{
      "SchemaRegistryConfig" : {
          "SchemaRegistryURI": "https://abcd-ef123.us-west-2.aws.confluent.cloud",
          "AccessConfigs": [{
              "Type": "BASIC_AUTH", 
              "URI": "arn:aws:secretsmanager:us-east-1:123456789012:secret:secretName"
          }],
          "EventRecordFormat": "JSON",
          "SchemaValidationConfigs": [
          { 
              "Attribute": "KEY" 
          },
          { 
              "Attribute": "VALUE" 
          }]
      }
  }'
```

------
#### [ Update AWS Glue Schema Registry ]

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --amazon-managed-kafka-event-source-mapping '{
        "SchemaRegistryConfig" : {
            "SchemaRegistryURI": "arn:aws:glue:us-east-1:123456789012:registry/registryName",
            "EventRecordFormat": "JSON",
            "SchemaValidationConfigs": [
            { 
                "Attribute": "KEY" 
            },
            { 
                "Attribute": "VALUE" 
            }]
        }
    }'
```

------
#### [ Update Confluent Schema Registry with Authentication ]

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --amazon-managed-kafka-event-source-mapping '{
        "SchemaRegistryConfig" : {
            "SchemaRegistryURI": "https://abcd-ef123.us-west-2.aws.confluent.cloud",
            "AccessConfigs": [{
                "Type": "BASIC_AUTH", 
                "URI": "arn:aws:secretsmanager:us-east-1:123456789012:secret:secretName"
            }],
            "EventRecordFormat": "JSON",
            "SchemaValidationConfigs": [
            { 
                "Attribute": "KEY" 
            },
            { 
                "Attribute": "VALUE" 
            }]
        }
    }'
```

------
#### [ Update Confluent Schema Registry without Authentication ]

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --amazon-managed-kafka-event-source-mapping '{
        "SchemaRegistryConfig" : {
            "SchemaRegistryURI": "https://abcd-ef123.us-west-2.aws.confluent.cloud",
            "EventRecordFormat": "JSON",
            "SchemaValidationConfigs": [
            { 
                "Attribute": "KEY" 
            },
            { 
                "Attribute": "VALUE" 
            }]
        }
    }'
```

------
#### [ Remove Schema Registry Configuration ]

イベントソースマッピングからスキーマレジストリ設定を削除するには、「*AWS Lambda API リファレンス*」にある CLI コマンド [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) を使用できます。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --amazon-managed-kafka-event-source-mapping '{
        "SchemaRegistryConfig" : {}
    }'
```

------

## Avro と Protobuf のフィルタリング
<a name="services-consume-kafka-events-filtering"></a>

 スキーマレジストリで Avro または Protobuf 形式を使用する場合、Lambda 関数にイベントフィルタリングを適用できます。フィルターパターンは、スキーマ検証後のデータの逆シリアル化された従来の JSON 表現に適用されます。例えば、価格を含む製品詳細を定義する Avro スキーマでは、価格の値に基づいてメッセージをフィルタリングできます。

**注記**  
 逆シリアル化されると、Avro は標準 JSON に変換されます。つまり、Avro オブジェクトに直接変換することはできません。Avro オブジェクトに変換する必要がある場合は、代わりに SOURCE 形式を使用します。  
 Protobuf の逆シリアル化の場合、結果の JSON のフィールド名は、Protobuf が通常行うようにキャメルケースに変換されるのではなく、スキーマで定義されたものと一致します。フィルタリングパターンを作成するときは、この点に注意してください。

```
aws lambda create-event-source-mapping \
    --function-name myAvroFunction \
    --topics myAvroTopic \
    --starting-position TRIM_HORIZON \
    --kafka-bootstrap-servers '["broker1:9092", "broker2:9092"]' \
    --schema-registry-config '{
        "SchemaRegistryURI": "arn:aws:glue:us-east-1:123456789012:registry/myAvroRegistry",
        "EventRecordFormat": "JSON",
        "SchemaValidationConfigs": [
            { 
                "Attribute": "VALUE" 
            }
        ]
    }' \
    --filter-criteria '{
        "Filters": [
            {
                "Pattern": "{ \"value\" : { \"field_1\" : [\"value1\"], \"field_2\" : [\"value2\"] } }"
            }
        ]
    }'
```

 この例では、フィルターパターンは `value` オブジェクトを分析し、`field_1` のメッセージを `"value1"` と、`field_2` を `"value2"` と一致させます。Lambda がメッセージを Avro 形式から JSON に変換した後、フィルター条件は逆シリアル化されたデータに対して評価されます。

 イベント フィルタリングの詳細については、「[Lambda イベントフィルタリング](invocation-eventfiltering.md)」を参照してください。

## ペイロード形式と逆シリアル化の動作
<a name="services-consume-kafka-events-payload"></a>

 スキーマレジストリを使用する場合、Lambda は最終的なペイロードを[通常のイベントペイロード](with-msk.md#msk-sample-event)と同様の形式で関数に配信し、いくつかの追加フィールドがあります。追加のフィールドは、`SchemaValidationConfigs` パラメータによって異なります。検証用に選択した属性 (キーまたは値) ごとに、Lambda は対応するスキーマメタデータをペイロードに追加します。

**注記**  
スキーマメタデータフィールドを使用するには、[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events) をバージョン 3.16.0 以降に更新する必要があります。

 例えば、`value` フィールドを検証すると、Lambda は `valueSchemaMetadata` というフィールドをペイロードに追加します。同様に、`key` フィールドの場合、Lambda は `keySchemaMetadata` というフィールドを追加します。このメタデータには、検証に使用されるデータ形式とスキーマ ID に関する情報が含まれています。

```
"valueSchemaMetadata": {
    "dataFormat": "AVRO",
    "schemaId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
}
```

 `EventRecordFormat` パラメータは `JSON` または `SOURCE` のいずれかに設定できます。これにより、Lambda がスキーマ検証済みデータを関数に配信する前に処理する方法が決まります。各オプションには、さまざまな処理機能があります。
+ `JSON` - Lambda は検証された属性を標準 JSON 形式に逆シリアル化し、ネイティブ JSON をサポートする言語でデータを直接使用できるようにします。この形式は、元のバイナリ形式を保持したり、生成されたクラスを操作する必要がない場合に最適です。
+ `SOURCE` - Lambda はデータの元のバイナリ形式を Base64 エンコードされた文字列として保持し、Avro オブジェクトまたは Protobuf オブジェクトに直接変換できるようにします。この形式は、厳密に型指定された言語を使用する場合や、Avro スキーマまたは Protobuf スキーマの全機能を維持する必要がある場合に不可欠です。

これらの形式特性と言語固有の考慮事項に基づいて、次の形式をお勧めします。


**プログラミング言語に基づく推奨形式**  

| Language | Avro | Protobuf | JSON | 
| --- | --- | --- | --- | 
| Java | SOURCE | SOURCE | SOURCE | 
| Python | JSON | JSON | JSON | 
| NodeJS | JSON | JSON | JSON | 
| .NET | SOURCE | SOURCE | SOURCE | 
| その他 | JSON | JSON | JSON | 

以下のセクションでは、これらの形式について詳しく説明し、各形式のペイロードの例を示します。

### JSON 形式
<a name="services-consume-kafka-events-payload-json"></a>

 `JSON` を `EventRecordFormat` として選択すると、Lambda は [`SchemaValidationConfigs`] フィールドで選択したメッセージ属性 (`key` および/または `value` 属性) を検証および逆シリアル化します。Lambda は選択した属性を、関数内の標準 JSON 表現の base64 エンコードされた文字列として配信します。

**注記**  
 逆シリアル化されると、Avro は標準 JSON に変換されます。つまり、Avro オブジェクトに直接変換することはできません。Avro オブジェクトに変換する必要がある場合は、代わりに SOURCE 形式を使用します。  
 Protobuf の逆シリアル化の場合、結果の JSON のフィールド名は、Protobuf が通常行うようにキャメルケースに変換されるのではなく、スキーマで定義されたものと一致します。フィルタリングパターンを作成するときは、この点に注意してください。

 ペイロードの例を次に示します。ここでは、`JSON` を `EventRecordFormat` として指定し、`key` および `value` 属性の両方を `SchemaValidationConfigs` として指定します。

```
{
   "eventSource":"aws:kafka",
   "eventSourceArn":"arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111-1",
   "bootstrapServers":"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092",
   "records":{
      "mytopic-0":[
         {
            "topic":"mytopic",
            "partition":0,
            "offset":15,
            "timestamp":1545084650987,
            "timestampType":"CREATE_TIME",
            "key":"abcDEFghiJKLmnoPQRstuVWXyz1234==", //Base64 encoded string of JSON
            "keySchemaMetadata": {
                "dataFormat": "AVRO",
                "schemaId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
            },
            "value":"abcDEFghiJKLmnoPQRstuVWXyz1234", //Base64 encoded string of JSON
            "valueSchemaMetadata": {
                "dataFormat": "AVRO",
                "schemaId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
            },
            "headers":[
               {
                  "headerKey":[
                     104,
                     101,
                     97,
                     100,
                     101,
                     114,
                     86,
                     97,
                     108,
                     117,
                     101
                  ]
               }
            ]
         }
      ]
   }
}
```

 この例では、以下のようになっています：
+ `key` と `value` はどちらも、逆シリアル化後の JSON 表現の base64 エンコードされた文字列です。
+ Lambda には、`keySchemaMetadata` と `valueSchemaMetadata` の両方の属性のスキーマメタデータが含まれます。
+ 関数は、`key` および `value` 文字列をデコードして、逆シリアル化された JSON データにアクセスできます。

 JSON 形式は、Python や Node.js など、厳密に入力されていない言語に推奨されます。これらの言語は、JSON のオブジェクトへの変換をネイティブにサポートしています。

### ソース形式
<a name="services-consume-kafka-events-payload-source"></a>

 `SOURCE` を `EventRecordFormat` として指定した場合でも、Lambda はスキーマレジストリに対してレコードを検証しますが、元のバイナリデータを逆シリアル化せずに関数に配信します。このバイナリデータは、元のバイトデータの Base64 でエンコードされた文字列として配信され、プロデューサーが付加したメタデータは削除されます。その結果、未加工のバイナリデータを関数コード内の Avro オブジェクトと Protobuf オブジェクトに直接変換できます。AWS Lambda には Powertools を使用することをお勧めします。これにより、未加工のバイナリデータが逆シリアル化され、Avro オブジェクトと Protobuf オブジェクトが直接提供されます。

 例えば、`key` 属性と `value` 属性の両方を検証するように Lambda を設定し、`SOURCE` 形式を使用する場合、関数は次のようなペイロードを受け取ります。

```
{
    "eventSource": "aws:kafka",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111-1",
    "bootstrapServers": "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092",
    "records": {
        "mytopic-0": [
            {
                "topic": "mytopic",
                "partition": 0,
                "offset": 15,
                "timestamp": 1545084650987,
                "timestampType": "CREATE_TIME",
                "key": "abcDEFghiJKLmnoPQRstuVWXyz1234==", // Base64 encoded string of Original byte data, producer-appended metadata removed
                "keySchemaMetadata": {
                    "dataFormat": "AVRO",
                    "schemaId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
                },
                "value": "abcDEFghiJKLmnoPQRstuVWXyz1234==", // Base64 encoded string of Original byte data, producer-appended metadata removed
                "valueSchemaMetadata": {
                    "dataFormat": "AVRO",
                    "schemaId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
                },
                "headers": [
                    {
                        "headerKey": [
                            104,
                            101,
                            97,
                            100,
                            101,
                            114,
                            86,
                            97,
                            108,
                            117,
                            101
                        ]
                    }
                ]
            }
        ]
    }
}
```

 この例では、以下のようになっています：
+ `key` と `value` の両方に、元のバイナリデータが Base64 でエンコードされた文字列として含まれます。
+ 関数は、適切なライブラリを使用して逆シリアル化を処理する必要があります。

 Avro 生成オブジェクトまたは Protobuf 生成オブジェクト、特に Java 関数を使用している場合は、`EventRecordFormat` ではなく `SOURCE` を選択することをお勧めします。これは、Java が厳密に型付けされており、Avro 形式と Protobuf 形式に特定のデシリアライザーが必要であるためです。関数コードでは、任意の Avro または Protobuf ライブラリを使用してデータを逆シリアル化できます。

## Lambda 関数での逆シリアル化されたデータの操作
<a name="services-consume-kafka-events-payload-examples"></a>

Powertools for AWS Lambda は、使用する形式に基づいて、関数コード内で Kafka レコードを逆シリアル化するのに役立ちます。このユーティリティは、データ変換を処理し、すぐに使えるオブジェクトを提供することで、Kafka レコードの操作を簡素化します。

 関数内で Powertools for AWS Lambda を使用するには、Lambda 関数の構築時に Powertools for AWS Lambda をレイヤーとして追加するか、依存関係として含める必要があります。セットアップ手順と詳細については、使用する言語の　Powertools for AWS Lambda ドキュメントを参照してください。
+ [Powertools for AWS Lambda (Java)](https://docs.powertools.aws.dev/lambda/java/latest/utilities/kafka/)
+ [Powertools for AWS Lambda (Python)](https://docs.powertools.aws.dev/lambda/python/latest/utilities/kafka/)
+ [Powertools for AWS Lambda (TypeScript)](https://docs.powertools.aws.dev/lambda/typescript/latest/features/kafka/)
+ [Powertools for AWS Lambda (.NET)](https://docs.powertools.aws.dev/lambda/dotnet/utilities/kafka/)

**注記**  
スキーマレジストリ統合を使用する場合は、`SOURCE` または `JSON` 形式を選択できます。各オプションは、以下に示すようにさまざまなシリアル化形式をサポートしています。  


| 形式 | サポート対象 | 
| --- | --- | 
|  SOURCE  |  Avro と Protobuf (Lambda Schema Registry 統合を使用)  | 
|  JSON  |  JSON データ  | 

 `SOURCE` または `JSON` 形式を使用する場合、Powertools for AWS を使用して、関数コード内のデータを逆シリアル化できます。さまざまなデータ形式を処理する方法の例を以下に示します。

------
#### [ AVRO ]

Java の例:

```
package org.demo.kafka;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.demo.kafka.avro.AvroProduct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.lambda.powertools.kafka.Deserialization;
import software.amazon.lambda.powertools.kafka.DeserializationType;
import software.amazon.lambda.powertools.logging.Logging;

public class AvroDeserializationFunction implements RequestHandler<ConsumerRecords<String, AvroProduct>, String> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AvroDeserializationFunction.class);

    @Override
    @Logging
    @Deserialization(type = DeserializationType.KAFKA_AVRO)
    public String handleRequest(ConsumerRecords<String, AvroProduct> records, Context context) {
        for (ConsumerRecord<String, AvroProduct> consumerRecord : records) {
            LOGGER.info("ConsumerRecord: {}", consumerRecord);

            AvroProduct product = consumerRecord.value();
            LOGGER.info("AvroProduct: {}", product);

            String key = consumerRecord.key();
            LOGGER.info("Key: {}", key);
        }

        return "OK";
    }

}
```

Python の例

```
from aws_lambda_powertools.utilities.kafka_consumer.kafka_consumer import kafka_consumer
from aws_lambda_powertools.utilities.kafka_consumer.schema_config import SchemaConfig
from aws_lambda_powertools.utilities.kafka_consumer.consumer_records import ConsumerRecords

from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools import Logger

logger = Logger(service="kafkaConsumerPowertools")

value_schema_str = open("customer_profile.avsc", "r").read()

schema_config = SchemaConfig(
value_schema_type="AVRO",
value_schema=value_schema_str)

@kafka_consumer(schema_config=schema_config)
def lambda_handler(event: ConsumerRecords, context:LambdaContext):

  for record in event.records:
      value = record.value
      logger.info(f"Received value: {value}")
```

TypeScript サンプル:

```
import { kafkaConsumer } from '@aws-lambda-powertools/kafka';

import type { ConsumerRecords } from '@aws-lambda-powertools/kafka/types';
import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda';

const logger = new Logger();

type Value = {
    id: number;
    name: string;
    price: number;
};

const schema = '{   
    "type": "record",   
    "name": "Product",   
    "fields": [     
        { "name": "id", "type": "int" },     
        { "name": "name", "type": "string" },     
        { "name": "price", "type": "double" }   
    ] 
}';

export const handler = kafkaConsumer<string, Value>(
    (event: ConsumerRecords<string, Value>, _context: Context) => {
        for (const record of event.records) {
            logger.info(Processing record with key: ${record.key});
            logger.info(Record value: ${JSON.stringify(record.value)});
            // You can add more processing logic here
        }
    },
    {
        value: {
            type: 'avro',
            schema: schema,
        },
    }
);
```

.NET/C\$1 の例:

```
using Amazon.Lambda.Core;
using AWS.Lambda.Powertools.Kafka;
using AWS.Lambda.Powertools.Kafka.Avro;
using AWS.Lambda.Powertools.Logging;
using Com.Example;

// Assembly attribute to enable the Lambda function's Kafka event to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(PowertoolsKafkaAvroSerializer))]

namespace ProtoBufClassLibrary;

public class Function
{
    public string FunctionHandler(ConsumerRecords<string, CustomerProfile> records, ILambdaContext context)
    {
        foreach (var record in records)
        {
            Logger.LogInformation("Processing messagem from topic: {topic}", record.Topic);
            Logger.LogInformation("Partition: {partition}, Offset: {offset}", record.Partition, record.Offset);
            Logger.LogInformation("Produced at: {timestamp}", record.Timestamp);
            
            foreach (var header in record.Headers.DecodedValues())
            {
                Logger.LogInformation($"{header.Key}: {header.Value}");
            }
            
            Logger.LogInformation("Processing order for: {fullName}", record.Value.FullName);
        }
    
        return "Processed " + records.Count() + " records";
    }
}
```

------
#### [ PROTOBUF ]

Java の例:

```
package org.demo.kafka;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.demo.kafka.protobuf.ProtobufProduct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.lambda.powertools.kafka.Deserialization;
import software.amazon.lambda.powertools.kafka.DeserializationType;
import software.amazon.lambda.powertools.logging.Logging;

public class ProtobufDeserializationFunction
        implements RequestHandler<ConsumerRecords<String, ProtobufProduct>, String> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProtobufDeserializationFunction.class);

    @Override
    @Logging
    @Deserialization(type = DeserializationType.KAFKA_PROTOBUF)
    public String handleRequest(ConsumerRecords<String, ProtobufProduct> records, Context context) {
        for (ConsumerRecord<String, ProtobufProduct> consumerRecord : records) {
            LOGGER.info("ConsumerRecord: {}", consumerRecord);

            ProtobufProduct product = consumerRecord.value();
            LOGGER.info("ProtobufProduct: {}", product);

            String key = consumerRecord.key();
            LOGGER.info("Key: {}", key);
        }

        return "OK";
    }

}
```

Python の例

```
from aws_lambda_powertools.utilities.kafka_consumer.kafka_consumer import kafka_consumer

from aws_lambda_powertools.utilities.kafka_consumer.schema_config import SchemaConfig
from aws_lambda_powertools.utilities.kafka_consumer.consumer_records import ConsumerRecords

from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools import Logger

from user_pb2 import User # protobuf generated class

logger = Logger(service="kafkaConsumerPowertools")

schema_config = SchemaConfig(
value_schema_type="PROTOBUF",
value_schema=User)

@kafka_consumer(schema_config=schema_config)
def lambda_handler(event: ConsumerRecords, context:LambdaContext):

  for record in event.records:
      value = record.value
      logger.info(f"Received value: {value}")
```

TypeScript サンプル:

```
import { kafkaConsumer } from '@aws-lambda-powertools/kafka';
import type { ConsumerRecords } from '@aws-lambda-powertools/kafka/types';
import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda';
import { Product } from './product.generated.js';

const logger = new Logger();

type Value = {
    id: number;
    name: string;
    price: number;
};

export const handler = kafkaConsumer<string, Value>(
    (event: ConsumerRecords<string, Value>, _context: Context) => {
        for (const record of event.records) {
            logger.info(Processing record with key: ${record.key});
            logger.info(Record value: ${JSON.stringify(record.value)});
        }
    },
    {
        value: {
            type: 'protobuf',
            schema: Product,
        },
    }
);
```

.NET/C\$1 の例:

```
using Amazon.Lambda.Core;
using AWS.Lambda.Powertools.Kafka;
using AWS.Lambda.Powertools.Kafka.Protobuf;
using AWS.Lambda.Powertools.Logging;
using Com.Example;

// Assembly attribute to enable the Lambda function's Kafka event to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(PowertoolsKafkaProtobufSerializer))]

namespace ProtoBufClassLibrary;

public class Function
{
    public string FunctionHandler(ConsumerRecords<string, CustomerProfile> records, ILambdaContext context)
    {
        foreach (var record in records)
        {
            Logger.LogInformation("Processing messagem from topic: {topic}", record.Topic);
            Logger.LogInformation("Partition: {partition}, Offset: {offset}", record.Partition, record.Offset);
            Logger.LogInformation("Produced at: {timestamp}", record.Timestamp);
            
            foreach (var header in record.Headers.DecodedValues())
            {
                Logger.LogInformation($"{header.Key}: {header.Value}");
            }
            
            Logger.LogInformation("Processing order for: {fullName}", record.Value.FullName);
        }
    
        return "Processed " + records.Count() + " records";
    }
}
```

------
#### [ JSON ]

Java の例:

```
package org.demo.kafka;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import software.amazon.lambda.powertools.kafka.Deserialization;
import software.amazon.lambda.powertools.kafka.DeserializationType;
import software.amazon.lambda.powertools.logging.Logging;

public class JsonDeserializationFunction implements RequestHandler<ConsumerRecords<String, Product>, String> {

    private static final Logger LOGGER = LoggerFactory.getLogger(JsonDeserializationFunction.class);

    @Override
    @Logging
    @Deserialization(type = DeserializationType.KAFKA_JSON)
    public String handleRequest(ConsumerRecords<String, Product> consumerRecords, Context context) {
        for (ConsumerRecord<String, Product> consumerRecord : consumerRecords) {
            LOGGER.info("ConsumerRecord: {}", consumerRecord);

            Product product = consumerRecord.value();
            LOGGER.info("Product: {}", product);

            String key = consumerRecord.key();
            LOGGER.info("Key: {}", key);
        }

        return "OK";
    }
}
```

Python の例

```
from aws_lambda_powertools.utilities.kafka_consumer.kafka_consumer import kafka_consumer

from aws_lambda_powertools.utilities.kafka_consumer.schema_config import SchemaConfig
from aws_lambda_powertools.utilities.kafka_consumer.consumer_records import ConsumerRecords

from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools import Logger

logger = Logger(service="kafkaConsumerPowertools")

schema_config = SchemaConfig(value_schema_type="JSON")

@kafka_consumer(schema_config=schema_config)
def lambda_handler(event: ConsumerRecords, context:LambdaContext):

  for record in event.records:
      value = record.value
      logger.info(f"Received value: {value}")
```

TypeScript サンプル:

```
import { kafkaConsumer } from '@aws-lambda-powertools/kafka';
import type { ConsumerRecords } from '@aws-lambda-powertools/kafka/types';
import { Logger } from '@aws-lambda-powertools/logger';
import type { Context } from 'aws-lambda';

const logger = new Logger();

type Value = {
    id: number;
    name: string;
    price: number;
};

export const handler = kafkaConsumer<string, Value>(
    (event: ConsumerRecords<string, Value>, _context: Context) => {
        for (const record of event.records) {
            logger.info(Processing record with key: ${record.key});
            logger.info(Record value: ${JSON.stringify(record.value)});
            // You can add more processing logic here
        }
    },
    {
        value: {
            type: 'json',
        },
    }
);
```

.NET/C\$1 の例:

```
using Amazon.Lambda.Core;
using AWS.Lambda.Powertools.Kafka;
using AWS.Lambda.Powertools.Kafka.Json;
using AWS.Lambda.Powertools.Logging;
using Com.Example;

// Assembly attribute to enable the Lambda function's Kafka event to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(PowertoolsKafkaJsonSerializer))]

namespace JsonClassLibrary;

public class Function
{
    public string FunctionHandler(ConsumerRecords<string, CustomerProfile> records, ILambdaContext context)
    {
        foreach (var record in records)
        {
            Logger.LogInformation("Processing messagem from topic: {topic}", record.Topic);
            Logger.LogInformation("Partition: {partition}, Offset: {offset}", record.Partition, record.Offset);
            Logger.LogInformation("Produced at: {timestamp}", record.Timestamp);
            
            foreach (var header in record.Headers.DecodedValues())
            {
                Logger.LogInformation($"{header.Key}: {header.Value}");
            }
            
            Logger.LogInformation("Processing order for: {fullName}", record.Value.FullName);
        }
    
        return "Processed " + records.Count() + " records";
    }
}
```

------

## スキーマレジストリの認証方法
<a name="services-consume-kafka-events-auth"></a>

 スキーマレジストリを使用するには、Lambda がスキーマレジストリに安全にアクセスできる必要があります。AWS Glue スキーマレジストリを使用している場合、Lambda は IAM 認証に依存します。つまり、関数の [実行ロール](lambda-intro-execution-role.md)には、AWS Glue レジストリにアクセスするための次のアクセス許可が必要です。
+ *AWS Glueウェブ API リファレンス*の [GetRegistry](https://docs.aws.amazon.com/glue/latest/webapi/API_GetRegistry.html)
+ *AWS Glueウェブ API リファレンス*の [GetSchemaVersion](https://docs.aws.amazon.com/glue/latest/webapi/API_GetSchemaVersion.html)

必要な IAM ポリシーの例：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "glue:GetRegistry",
                "glue:GetSchemaVersion"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

------

**注記**  
 AWS Glue スキーマレジストリの場合、AWS Glue レジストリ に `AccessConfigs` を指定すると、Lambda は検証例外を返します。

Confluent スキーマレジストリを使用している場合は、[KafkaSchemaRegistryAccessConfig](https://docs.aws.amazon.com/lambda/latest/api/API_KafkaSchemaRegistryAccessConfig) オブジェクトの `Type` パラメータでサポートされている 3 つの認証方法のいずれかを選択できます。
+ **BASIC\$1AUTH** — Lambda はユーザー名とパスワードまたは API キーと API シークレット認証を使用してレジストリにアクセスします。このオプションを選択した場合、[URI] フィールドに認証情報を含む Secrets Manager ARN を指定します。
+ **CLIENT\$1CERTIFICATE\$1TLS\$1AUTH** — Lambda はクライアント証明書で相互 TLS 認証を使用します。このオプションを使用するには、Lambda が証明書とプライベートキーの両方にアクセスする必要があります。これらの認証情報を含む Secrets Manager ARN を [URI] フィールドに入力します。
+ **NO\$1AUTH** — パブリック CA 証明書は、Lambda トラストストア内の認証局 (CA) によって署名される必要があります。プライベート CA/自己署名証明書の場合は、サーバルート CA 証明書を設定します。このオプションを使用するには、`AccessConfigs` パラメータを省略します。

 さらに、Lambda がスキーマレジストリの TLS 証明書を検証するためにプライベート CA 証明書にアクセスする必要がある場合は、`Type` として [`SERVER_ROOT_CA_CERT`] を選択し、[URI] フィールドの証明書に Secrets Manager ARN を指定します。

**注記**  
 コンソールで `SERVER_ROOT_CA_CERT` オプションを設定するには、**[暗号化]** フィールドに証明書を含むシークレット ARN を指定します。

 スキーマレジストリの認証設定は、Kafka クラスター用に設定した認証とは別のものです。同様の認証方法を使用している場合でも、両方を個別に設定する必要があります。

## スキーマレジストリの問題のエラー処理とトラブルシューティング
<a name="services-consume-kafka-events-troubleshooting"></a>

Amazon MSK イベントソースでスキーマレジストリを使用すると、さまざまなエラーが発生する可能性があります。このセクションでは、一般的な問題とその解決方法に関するガイダンスを提供します。

### 設定エラー
<a name="consume-kafka-events-troubleshooting-configuration-errors"></a>

これらのエラーは、スキーマレジストリの設定時に発生します。

プロビジョニングモードが必要です  
**エラーメッセージ**: `SchemaRegistryConfig is only available for Provisioned Mode. To configure Schema Registry, please enable Provisioned Mode by specifying MinimumPollers in ProvisionedPollerConfig.`  
**解決策:** `ProvisionedPollerConfig` の `MinimumPollers` パラメータを設定して、イベントソースマッピングのプロビジョニングモードを有効にします。

無効なスキーマレジストリ URL  
**エラーメッセージ**: `Malformed SchemaRegistryURI provided. Please provide a valid URI or ARN. For example, https://schema-registry.example.com:8081 or arn:aws:glue:us-east-1:123456789012:registry/ExampleRegistry.`  
**解決策:** Confluent スキーマレジストリの有効な HTTPS URL または AWS Glue Schema Registry の有効な ARN を指定します。

無効または欠落しているイベントレコード形式  
**エラーメッセージ**: `EventRecordFormat is a required field for SchemaRegistryConfig. Please provide one of supported format types: SOURCE, JSON.`  
**解決策:** スキーマレジストリ設定で EventRecordFormat として SOURCE または JSON を指定します。

重複する検証属性  
**エラーメッセージ**: `Duplicate KEY/VALUE Attribute in SchemaValidationConfigs. SchemaValidationConfigs must contain at most one KEY/VALUE Attribute.`  
**解決策:** SchemaValidationConfigs から重複する KEY 属性または VALUE 属性を削除します。各属性タイプは 1 回しか表示できません。

検証設定がありません  
**エラーメッセージ**: `SchemaValidationConfigs is a required field for SchemaRegistryConfig.`  
**解決策:** SchemaValidationConfigs を設定に追加し、少なくとも 1 つの検証属性 (KEY または VALUE) を指定します。

### アクセスとアクセス許可のエラー
<a name="consume-kafka-events-troubleshooting-access-errors"></a>

これらのエラーは、アクセス許可または認証の問題により Lambda がスキーマレジストリにアクセスできない場合に発生します。

AWS Glue スキーマレジストリへのアクセスが拒否されました  
**エラーメッセージ**: `Cannot access Glue Schema with provided role. Please ensure the provided role can perform the GetRegistry and GetSchemaVersion Actions on your schema.`  
**解決策:** 関数の実行ロールに必要なアクセス許可（`glue:GetRegistry` と `glue:GetSchemaVersion`）を追加します。

Confluent スキーマレジストリへのアクセスが拒否されました  
**エラーメッセージ**: `Cannot access Confluent Schema with the provided access configuration.`  
**解決策:** 認証情報 (Secrets Manager に保存) が正しく、スキーマレジストリにアクセスするために必要なアクセス許可があることを確認します。

クロスアカウント AWS Glue スキーマレジストリ  
**エラーメッセージ**: `Cross-account Glue Schema Registry ARN not supported.`  
**解決策:** Lambda 関数と同じ AWS アカウントにある AWS Glue スキーマレジストリを使用します。

クロスリージョン AWS Glue スキーマレジストリ  
**エラーメッセージ**: `Cross-region Glue Schema Registry ARN not supported.`  
**解決策:** Lambda 関数と同じリージョンにある AWS Glue スキーマレジストリを使用します。

シークレットアクセスの問題  
**エラーメッセージ**: `Lambda received InvalidRequestException from Secrets Manager.`  
**解決策:** 関数の実行ロールにシークレットへのアクセス許可があり、別のアカウントからアクセスする場合、シークレットがデフォルトの AWS KMS キーで暗号化されていないことを確認します。

### 接続エラー
<a name="consume-kafka-events-troubleshooting-connection-errors"></a>

これらのエラーは、Lambda がスキーマレジストリへの接続を確立できない場合に発生します。

VPC 接続の問題  
**エラーメッセージ**: `Cannot connect to your Schema Registry. Your Kafka cluster's VPC must be able to connect to the schema registry. You can provide access by configuring AWS PrivateLink or a NAT Gateway or VPC Peering between Kafka Cluster VPC and the schema registry VPC.`  
**解決策:** AWS PrivateLink、NAT ゲートウェイ、または VPC ピアリングを使用してスキーマレジストリへの接続を許可するように VPC ネットワークを設定します。

TLS ハンドシェイクの失敗  
**エラーメッセージ**: `Unable to establish TLS handshake with the schema registry. Please provide correct CA-certificate or client certificate using Secrets Manager to access your schema registry.`  
**解決策:** CA 証明書とクライアント証明書 (mTLS 用) が正しく、Secrets Manager で適切に設定されていることを確認します。

スロットリング  
**エラーメッセージ**: `Receiving throttling errors when accessing the schema registry. Please increase API TPS limits for your schema registry.`  
**解決策:** スキーマレジストリの API レート制限を引き上げるか、アプリケーションからのリクエストのレートを減らします。

セルフマネージドスキーマレジストリエラー  
**エラーメッセージ**: `Lambda received an internal server an unexpected error from the provided self-managed schema registry.`  
**解決策:** セルフマネージドスキーマレジストリサーバーの状態と設定を確認します。

# Kafka イベントソースのための低レイテンシー処理
<a name="with-kafka-low-latency"></a>

AWS Lambda は、100 ミリ秒未満の一貫したエンドツーエンドレイテンシーを必要とするアプリケーションの低レイテンシーイベント処理をネイティブにサポートします。このページでは、低レイテンシーワークフローを有効にするための設定詳細と推奨事項を説明します。

## 低レイテンシー処理の有効化
<a name="enable-low-latency"></a>

Kafka イベントソースマッピングで低レイテンシー処理を有効にするには、次の基本的な設定が必要です。
+ プロビジョニングモードを有効にする。詳細については、「[プロビジョニングモード](kafka-scaling-modes.md#kafka-provisioned-mode)」を参照してください。
+ イベントソースマッピングの `MaximumBatchingWindowInSeconds` パラメータを 0 に設定する。詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

## 低レイテンシー Kafka ESM の微調整
<a name="recommendations-low-latency"></a>

Kafka イベントソースマッピングを低レイテンシー向けに最適化するには、次の推奨事項を検討してください。

### プロビジョンドモード設定
<a name="recommendations-pollers"></a>

Kafka イベントソースマッピングのプロビジョンドモードでは、Lambda でイベントソースマッピングのスループットを微調整することができます。これは、**イベントポーラー**と呼ばれるリソースの最小数と最大数を設定することによって行います。イベントポーラー (または**ポーラー**) は、プロビジョンドモードでイベントソースマッピングを支えるコンピューティングリソースを表し、最大 5 MB/秒のスループットを割り当てます。各イベントポーラーは、最大 5 個の同時 Lambda 呼び出しをサポートします。

アプリケーションに最適なポーラー設定を判断するには、ピーク取り込みレートと処理要件を考慮してください。単純化した例を見てみましょう。

バッチサイズが 20 レコード、ターゲット関数の平均実行時間が 50 ミリ秒の場合、各ポーラーは 5 MB/秒の制限付きで 1 秒あたり 2,000 レコードを処理できます。これは、(20 レコード × 1000 ミリ秒/50 ミリ秒) × 5 個の同時 Lambda 呼び出しとして計算されます。したがって、希望するピーク取り込みレートが 1 秒あたり 20,000 レコードの場合は、少なくとも 10 個のイベントポーラーが必要になります。

**注記**  
常に最大キャパシティで稼働することを避けるため、追加のイベントポーラーをバッファとしてプロビジョニングすることをお勧めします。

プロビジョンドモードは、**イベントポーラー**に設定された最小数と最大数の範囲内で、トラフィックパターンに基づいたイベントポーラーのスケーリングを自動的に行いますが、これによって再調整がトリガーされるため、レイテンシーが増加する可能性があります。自動スケーリングは、**イベントポーラー**の最小数と最大数に同じ値を設定することで無効化できます。

### その他の考慮事項
<a name="additional-considerations-low-latency"></a>

その他の考慮事項には以下が含まれます。
+ Lambda ターゲット関数の呼び出しからのコールドスタートによって、エンドツーエンドレイテンシーが増加する可能性があります。このリスクを軽減するには、イベントソースマッピングのターゲット関数で、[プロビジョニングされた同時実行](provisioned-concurrency.md)または [SnapStart](snapstart.md) を有効化することを検討してください。さらに、関数のメモリ割り当てを最適化して、一貫性のある最適な実行を確実にします。
+ `MaximumBatchingWindowInSeconds` が 0 に設定されている場合、Lambda は、バッチサイズが上限まで満たされるのを待たずに、処理可能なレコードを即座に処理します。例えば、バッチサイズが 1,000 レコードに設定されていて、処理可能なレコードが 100 レコードしかないという場合、Lambda は 1,000 レコードのすべてが収集されるのを待たずに、これらの 100 レコードを即座に処理します。

**重要**  
低レイテンシー処理に最適な設定は、ユーザー固有のワークロードに応じて大きく異なります。ユースケースに最適な設定を判断するためにも、実際のワークロードで異なる設定をテストすることが強く推奨されます。

# Kafka イベントソースのエラー処理コントロールの設定
<a name="kafka-retry-configurations"></a>

Lambda が Kafka イベントソースマッピングのエラーと再試行を処理する方法を設定できます。これらの設定は、Lambda が失敗したレコードを処理し、再試行動作を管理する方法を制御するのに役立ちます。

## 使用可能な再試行の設定
<a name="kafka-retry-options"></a>

Amazon MSK イベントソースとセルフマネージド Kafka イベントソースの両方で、次の再試行の設定を使用できます。
+ **最大再試行回数** – 関数がエラーを返したときに Lambda が再試行する回数の上限です。これにより、最初の呼び出しの試行はカウントされません。デフォルト値は -1 (無制限) です。[無制限の再試行](kafka-on-failure-destination.md)と障害発生時の送信先の両方を設定すると、Lambda は最大 10 回の再試行を自動的に適用します。
+ **最大レコード有効時間** – Lambda が関数に送信するレコードの最大経過時間。デフォルト値は -1 (無制限) です。
+ **エラー発生時にバッチを分割** – 関数がエラーを返す際、バッチを 2 つの小さなバッチに分割し、それぞれを個別に再試行します。これにより、問題のあるレコードを隔離できます。
+ **部分的なバッチレスポンス** – 関数がバッチ処理で失敗したレコードに関する情報を返せるようにするため、Lambda は失敗したレコードだけを再試行できます。

## エラー処理コントロールの設定 (コンソール)
<a name="kafka-retry-console"></a>

Lambda コンソールで Kafka イベントソースマッピングを作成または更新するときに再試行動作を設定できます。

**Kafka イベントソースの再試行動作を設定するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 関数の名前を選択します。

1. 次のいずれかを行います。
   + 新しい Kafka トリガーを追加するには、**[関数の概要]** で **[トリガーを追加]** を選択します。
   + 既存の Kafka トリガーを変更するには、トリガーを選択し、**[編集]** を選択します。

1. **[イベントポーラー設定]** で、プロビジョンドモードを選択してエラー処理コントロールを設定します。

   1. **[再試行]** には、最大再試行回数 (0～10000、または無限の場合は -1) を入力します。

   1. **[最大レコード有効時間]** には、最大経過時間を秒単位で入力します (60～604800、または無限の場合は -1)。

   1. エラー発生時にバッチ分割を有効にするには、**[エラー発生時にバッチを分割]** を選択します。

   1. 部分的なバッチレスポンスを有効にするには、**[ReportBatchItemFailures]** を選択します。

1. **[追加]** または **[削除]** を選択します。

## 再試行動作の設定 (AWS CLI)
<a name="kafka-retry-cli"></a>

次の AWS CLI コマンドを使用して、Kafka イベントソースマッピングの再試行動作を設定します。

### 再試行設定を使用したイベントソースマッピングの作成
<a name="kafka-retry-cli-create"></a>

次の例では、エラー処理コントロールを使用してセルフマネージド型の Kafka イベントソースマッピングを作成します。

```
aws lambda create-event-source-mapping \
  --function-name my-kafka-function \
  --topics my-kafka-topic \
  --source-access-configuration Type=SASL_SCRAM_512_AUTH,URI=arn:aws:secretsmanager:us-east-1:111122223333:secret:MyBrokerSecretName \
  --self-managed-event-source '{"Endpoints":{"KAFKA_BOOTSTRAP_SERVERS":["abc.xyz.com:9092"]}}' \
  --starting-position LATEST \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=1 \
  --maximum-retry-attempts 3 \
  --maximum-record-age-in-seconds 3600 \
  --bisect-batch-on-function-error \
  --function-response-types "ReportBatchItemFailures"
```

Amazon MSK イベントソースの場合:

```
aws lambda create-event-source-mapping \
  --event-source-arn arn:aws:kafka:us-east-1:111122223333:cluster/my-cluster/fc2f5bdf-fd1b-45ad-85dd-15b4a5a6247e-2 \
  --topics AWSMSKKafkaTopic \
  --starting-position LATEST \
  --function-name my-kafka-function \
  --source-access-configurations '[{"Type": "SASL_SCRAM_512_AUTH","URI": "arn:aws:secretsmanager:us-east-1:111122223333:secret:my-secret"}]' \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=1 \
  --maximum-retry-attempts 3 \
  --maximum-record-age-in-seconds 3600 \
  --bisect-batch-on-function-error \
  --function-response-types "ReportBatchItemFailures"
```

### 再試行設定の更新
<a name="kafka-retry-cli-update"></a>

`update-event-source-mapping` コマンドを使用して、既存のイベントソースマッピングの再試行設定を変更します。

```
aws lambda update-event-source-mapping \
  --uuid 12345678-1234-1234-1234-123456789012 \
  --maximum-retry-attempts 5 \
  --maximum-record-age-in-seconds 7200 \
  --bisect-batch-on-function-error \
  --function-response-types "ReportBatchItemFailures"
```

## PartialBatchResponse
<a name="kafka-partial-batch-response"></a>

ReportBatchItemFailures とも呼ばれる部分的なバッチレスポンスは、Lambda が Kafka ソースと統合する際のエラー処理の主要な機能です。この機能がない場合は、バッチ内のいずれかの項目でエラーが発生すると、そのバッチ内のすべてのメッセージが再処理されます。部分的バッチレスポンスを有効にして実装すると、ハンドラーは失敗したメッセージの識別子のみを返します。これにより、Lambda はそれらの特定の項目のみを再試行できます。これにより、失敗したメッセージを含むバッチの処理方法をより細かく制御できます。

バッチエラーを報告するには、次の JSON スキーマを使用します。

```
{
  "batchItemFailures": [
    {
      "itemIdentifier": {
        "partition": "topic-partition_number",
        "offset": 100
      }
    },
    ...
  ]
}
```

**重要**  
空の有効な JSON または null を返す場合、イベントソースマッピングはバッチを正常に処理されたと見なします。呼び出されたイベントに存在しなかった無効な topic-partition\$1number または返されたオフセットは失敗として扱われ、バッチ全体が再試行されます。

次のコードの例では、Kafka ソースからイベントを受け取る Lambda 関数の部分的なバッチレスポンスの実装方法が示されています。この関数は、レスポンスとしてバッチアイテムの失敗を報告し、対象のメッセージを後で再試行するよう Lambda に伝えます。

このアプローチを示す Python Lambda ハンドラーの実装を次に示します。

```
import base64
from typing import Any, Dict, List

def lambda_handler(event: Dict[str, Any], context: Any) -> Dict[str, List[Dict[str, Dict[str, Any]]]]:
    failures: List[Dict[str, Dict[str, Any]]] = []
    records_dict = event.get("records", {})
    
    for topic_partition, records_list in records_dict.items():
        for record in records_list:
            topic = record.get("topic")
            partition = record.get("partition")
            offset = record.get("offset")
            value_b64 = record.get("value")
            
            try:
                data = base64.b64decode(value_b64).decode("utf-8")
                process_message(data)
            except Exception as exc:
                print(f"Failed to process record topic={topic} partition={partition} offset={offset}: {exc}")
                item_identifier: Dict[str, Any] = {
                    "partition": f"{topic}-{partition}",
                    "offset": int(offset) if offset is not None else None,
                }
                failures.append({"itemIdentifier": item_identifier})
    
    return {"batchItemFailures": failures}

def process_message(data: str) -> None:
    # Your business logic for a single message
    pass
```

Node.js のバージョンは次のとおりです。

```
const { Buffer } = require("buffer");

const handler = async (event) => {
  const failures = [];
  
  for (let topicPartition in event.records) {
    const records = event.records[topicPartition];
    
    for (const record of records) {
      const topic = record.topic;
      const partition = record.partition;
      const offset = record.offset;
      const valueBase64 = record.value;
      const data = Buffer.from(valueBase64, "base64").toString("utf8");
      
      try {
        await processMessage(data);
      } catch (error) {
        console.error("Failed to process record", { topic, partition, offset, error });
        const itemIdentifier = {
          "partition": `${topic}-${partition}`,
          "offset": Number(offset),
        };
        failures.push({ itemIdentifier });
      }
    }
  }
  
  return { batchItemFailures: failures };
};

async function processMessage(payload) {
  // Your business logic for a single message
}

module.exports = { handler };
```

# Amazon MSK とセルフマネージド Apache Kafka イベントソースの破棄されたバッチのキャプチャ
<a name="kafka-on-failure"></a>

失敗したイベントソースマッピング呼び出しの記録を保持するには、関数のイベントソースマッピングに送信先を追加します。送信先に送られる各レコードは、失敗した呼び出しに関するメタデータを含む JSON ドキュメントです。Amazon S3 送信先の場合、Lambda はメタデータと共に呼び出しレコード全体を送信します。任意の Amazon SNS トピック、Amazon SQS キュー、Amazon S3 バケット、または Kafka を送信先として設定できます。

Amazon S3 送信先を使用すると、[Amazon S3 イベント通知](https://docs.aws.amazon.com/)機能を使用して、オブジェクトが送信先 S3 バケットにアップロードされたときに通知を受け取ることができます。また、S3 イベント通知を設定して、失敗したバッチに対して別の Lambda 関数を呼び出し、自動処理を実行することもできます。

実行ロールには、送信先に対するアクセス許可が必要です。
+ **SQS 送信先の場合:** [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)
+ **SNS 送信先の場合:** [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)
+ **S3 送信先の場合:** [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) および [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/ListObjectsV2.html)
+ **Kafka 送信先の場合:** [kafka-cluster:WriteData](https://docs.aws.amazon.com/msk/latest/developerguide/kafka-actions.html)

Kafka トピックは、Kafka イベントソースマッピングの障害発生時の送信先として設定できます。再試行回数を超えた後、またはレコードが最大経過時間を超えた後に Lambda がレコードを処理できなくなると、Lambda は失敗したレコードを指定された Kafka トピックに送信して、後で処理します。「[Kafka トピックを障害発生時の送信先として使用する](kafka-on-failure-destination.md)」を参照してください。

障害発生時の送信先サービスの VPC エンドポイントを Kafka クラスター VPC 内にデプロイする必要があります。

さらに、送信先に KMS キーを設定した場合、Lambda には送信先のタイプに応じて以下のアクセス許可が必要です。
+ S3 送信先に対して独自の KMS キーによる暗号化を有効にしている場合は、[kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) が必要です。KMS キーと S3 バケットの送信先が Lambda 関数および実行ロールとは異なるアカウントにある場合は、kms:GenerateDataKey を許可するように実行ロールを信頼するように KMS キーを設定します。
+ SQS 送信先に対して独自の KMS キーによる暗号化を有効にしている場合は、[kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) および [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) が必要です。KMS キーと SQS キューの送信先が Lambda 関数および実行ロールとは異なるアカウントにある場合は、KMS キーが実行ロールを信頼し、kms:Decryp、kms:GenerateDataKey、[kms:DescribeKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html)、および [kms:ReEncrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_ReEncrypt.html) を許可するように設定します。
+ SNS 送信先に対して独自の KMS キーによる暗号化を有効にしている場合は、[kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) と [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) が必要です。KMS キーと SNS トピックの送信先が Lambda 関数および実行ロールとは異なるアカウントにある場合は、KMS キーが実行ロールを信頼し、kms:Decryp、kms:GenerateDataKey、[kms:DescribeKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_DescribeKey.html)、および [kms:ReEncrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_ReEncrypt.html) を許可するように設定します。

## Kafka イベントソースマッピングの障害発生時の送信先の設定
<a name="kafka-onfailure-destination"></a>

障害発生時の送信先をコンソールを使用して設定するには、以下の手順に従います。

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. [**機能の概要 **] で、[**送信先を追加 **] を選択します。

1. **[ソース]** には、**[イベントソースマッピング呼び出し]** を選択します。

1. **[イベントソースマッピング]** では、この関数用に設定されているイベントソースを選択します。

1. **[条件]** には **[失敗時]** を選択します。イベントソースマッピング呼び出しでは、これが唯一受け入れられる条件です。

1. **[送信先タイプ]** では、Lambda が呼び出しレコードを送信する送信先タイプを選択します。

1. [**送信先**] で、リソースを選択します。

1. **[保存]** を選択します。

AWS CLI を使用して障害発生時の送信先を設定することもできます。例えば、次の [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドは、SQS を障害発生時の送信先として持つイベントソースマッピングを `MyFunction` に追加します。

```
aws lambda create-event-source-mapping \
--function-name "MyFunction" \
--event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/751d2973-a626-431c-9d4e-d7975eb44dd7-2 \
--destination-config '{"OnFailure": {"Destination": "arn:aws:sqs:us-east-1:123456789012:dest-queue"}}'
```

以下の [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドは、S3 の障害発生時の送信先を、入力 `uuid` に関連付けられたイベントソースに追加します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--destination-config '{"OnFailure": {"Destination": "arn:aws:s3:::dest-bucket"}}'
```

送信先を削除するには、`destination-config` パラメータの引数として空の文字列を指定します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--destination-config '{"OnFailure": {"Destination": ""}}'
```

### Amazon S3 送信先のセキュリティのベストプラクティス
<a name="kafka-s3-destination-security"></a>

関数の設定から送信先を削除せずに、送信先として設定された S3 バケットを削除すると、セキュリティリスクが発生する可能性があります。別のユーザーが送信先バケットの名前を知っている場合は、その AWS アカウントでバケットを再作成できます。失敗した呼び出しのレコードがそのバケットに送信され、関数からのデータが公開される可能性があります。

**警告**  
関数からの呼び出しレコードを別の AWS アカウントの S3 バケットに送信できないようにするには、`s3:PutObject` アクセス許可を自分アカウントのバケットに制限する条件を関数の実行ロールに追加します。

次の例は、関数の `s3:PutObject` アクセス許可を自分のアカウントのバケットに制限する IAM ポリシーを示しています。このポリシーは、送信先として S3 バケットを使用するために必要な `s3:ListBucket` アクセス許可も Lambda に付与します。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "S3BucketResourceAccountWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::*/*",
                "arn:aws:s3:::*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:ResourceAccount": "111122223333"
                }
            }
        }
    ]
}
```

AWS マネジメントコンソールまたは AWS CLI を使用して、関数の実行ロールにアクセス許可ポリシーを追加する場合は、次の手順を参照してください。

------
#### [ Console ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 実行ロールを変更する Lambda 関数を選択します。

1. **[構成]** タブで、**[アクセス許可]** を選択します。

1. **[実行ロール]** タブで、関数の **[ロール名]** を選択して、ロールの IAM コンソールページを開きます。

1. 次の手順を実行してアクセス許可ポリシーをロールに追加します。

   1. **[アクセス許可ポリシー]** ペインで、**[アクセス許可の追加]**、**[インラインポリシーを作成]** を選択します。

   1. **ポリシーエディタ**で、**[JSON]** を選択します。

   1. 追加するポリシーをエディタに貼り付け (既存の JSON を置き換える)、**[次へ]** を選択します。

   1. **[ポリシーの詳細]** で **[ポリシー名]** を入力します。

   1. [**Create policy**] (ポリシーの作成) を選択します。

------
#### [ AWS CLI ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (CLI)**

1. 必要なアクセス許可を持つ JSON ポリシードキュメントを作成し、ローカルディレクトリに保存します。

1. IAM `put-role-policy` CLI コマンドを使用して、関数の実行ロールにアクセス許可を追加します。JSON ポリシードキュメントを保存したディレクトリから次のコマンドを実行して、ロール名、ポリシー名、ポリシードキュメントを独自の値に置き換えます。

   ```
   aws iam put-role-policy \
   --role-name my_lambda_role \
   --policy-name LambdaS3DestinationPolicy \
   --policy-document file://my_policy.json
   ```

------

### SNS および SQS の呼び出しレコードの例
<a name="kafka-sns-sqs-destinations"></a>

以下の例は、Kafka イベントソース呼び出しが失敗した場合に Lambda が SNS トピックまたは SQS キューの送信先に送信する内容を示しています。`recordsInfo` の各キーには、Kafka トピックとパーティションの両方がハイフンで区切られて含まれています。例えば、キー `"Topic-0"` の場合、`Topic` は Kafka トピック、`0` はパーティションです。各トピックとパーティションについて、オフセットとタイムスタンプデータを使用して元の呼び出しレコードを検索できます。

```
{
    "requestContext": {
        "requestId": "316aa6d0-8154-xmpl-9af7-85d5f4a6bc81",
        "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted" | "MaximumPayloadSizeExceeded",
        "approximateInvokeCount": 1
    },
    "responseContext": { // null if record is MaximumPayloadSizeExceeded
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:38:06.021Z",
    "KafkaBatchInfo": {
        "batchSize": 500,
        "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/751d2973-a626-431c-9d4e-d7975eb44dd7-2",
        "bootstrapServers": "...",
        "payloadSize": 2039086, // In bytes
        "recordsInfo": {
            "Topic-0": {
                "firstRecordOffset": "49601189658422359378836298521827638475320189012309704722",
                "lastRecordOffset": "49601189658422359378836298522902373528957594348623495186",
                "firstRecordTimestamp": "2019-11-14T00:38:04.835Z",
                "lastRecordTimestamp": "2019-11-14T00:38:05.580Z",
            },
            "Topic-1": {
                "firstRecordOffset": "49601189658422359378836298521827638475320189012309704722",
                "lastRecordOffset": "49601189658422359378836298522902373528957594348623495186",
                "firstRecordTimestamp": "2019-11-14T00:38:04.835Z",
                "lastRecordTimestamp": "2019-11-14T00:38:05.580Z",
            }
        }
    }
}
```

### S3 送信先の呼び出しレコードの例
<a name="kafka-s3-destinations"></a>

S3 の送信先の場合、Lambda は呼び出しレコード全体をメタデータと共に送信先に送信します。以下の例は、Kafka イベントソース呼び出しが失敗した場合に、Lambda が S3 バケットの送信先に送信することを示しています。SQS と SNS の送信先に関する前例のすべてのフィールドに加えて、`payload` フィールドには元の呼び出しレコードがエスケープされた JSON 文字列として含まれています。

```
{
    "requestContext": {
        "requestId": "316aa6d0-8154-xmpl-9af7-85d5f4a6bc81",
        "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted" | "MaximumPayloadSizeExceeded",
        "approximateInvokeCount": 1
    },
    "responseContext": { // null if record is MaximumPayloadSizeExceeded
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:38:06.021Z",
    "KafkaBatchInfo": {
        "batchSize": 500,
        "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/vpc-2priv-2pub/751d2973-a626-431c-9d4e-d7975eb44dd7-2",
        "bootstrapServers": "...",
        "payloadSize": 2039086, // In bytes
        "recordsInfo": {
            "Topic-0": {
                "firstRecordOffset": "49601189658422359378836298521827638475320189012309704722",
                "lastRecordOffset": "49601189658422359378836298522902373528957594348623495186",
                "firstRecordTimestamp": "2019-11-14T00:38:04.835Z",
                "lastRecordTimestamp": "2019-11-14T00:38:05.580Z",
            },
            "Topic-1": {
                "firstRecordOffset": "49601189658422359378836298521827638475320189012309704722",
                "lastRecordOffset": "49601189658422359378836298522902373528957594348623495186",
                "firstRecordTimestamp": "2019-11-14T00:38:04.835Z",
                "lastRecordTimestamp": "2019-11-14T00:38:05.580Z",
            }
        }
    },
    "payload": "<Whole Event>" // Only available in S3
}
```

**ヒント**  
送信先バケットで S3 バージョニングを有効にすることをお勧めします。

# Kafka トピックを障害発生時の送信先として使用する
<a name="kafka-on-failure-destination"></a>

Kafka トピックは、Kafka イベントソースマッピングの障害発生時の送信先として設定できます。再試行回数を超えた後、またはレコードが最大経過時間を超えた後に Lambda がレコードを処理できなくなると、Lambda は失敗したレコードを指定された Kafka トピックに送信して、後で処理します。[無制限の再試行](kafka-retry-configurations.md)と障害発生時の送信先の両方を設定すると、Lambda は最大 10 回の再試行を自動的に適用します。

## Kafka 障害発生時の送信先のしくみ
<a name="kafka-ofd-overview"></a>

Kafka トピックを障害発生時の送信先として設定すると、Lambda は Kafka プロデューサーとして機能し、失敗したレコードを送信先トピックに書き込みます。これにより、Kafka インフラストラクチャ内にデッドレタートピック (DLT) のパターンが作成されます。
+ **同じクラスター要件** – 送信先トピックは、送信元トピックと同じ Kafka クラスターに存在する必要があります。
+ **実際のレコードコンテンツ** – Kafka の送信先は、実際の失敗したレコードと障害のメタデータを受け取ります。
+ **反復防止** – Lambda は、送信元トピックと送信先トピックが同じ場所になっている設定をブロックすることで、無限ループを防止します。

## Kafka 障害発生時の送信先の設定
<a name="kafka-ofd-configure"></a>

Kafka イベントソースマッピングを作成または更新するときに、Kafka トピックを障害発生時の送信先として設定できます。

### Kafka 送信先の設定 (コンソール)
<a name="kafka-ofd-console"></a>

**Kafka トピックを障害発生時の送信先として設定するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 関数の名前を選択します。

1. 次のいずれかを行います。
   + 新しい Kafka トリガーを追加するには、**[関数の概要]** で **[トリガーを追加]** を選択します。
   + 既存の Kafka トリガーを変更するには、トリガーを選択し、**[編集]** を選択します。

1. **[追加設定]** の **[障害発生時の送信先]** で、**[Kafka トピック]** を選択します。

1. **[トピック名]** に、失敗したレコードを送信する Kafka トピックの名前を入力します。

1. **[追加]** または **[削除]** を選択します。

### Kafka 送信先の設定 (AWS CLI)
<a name="kafka-ofd-cli"></a>

`kafka://` プレフィックスを使用して、障害発生時の送信先として Kafka トピックを指定します。

#### Kafka 送信先を使用したイベントソースマッピングの作成
<a name="kafka-ofd-cli-create"></a>

次の例では、障害発生時の送信先として Kafka トピックを使用して Amazon MSK イベントソースマッピングを作成します。

```
aws lambda create-event-source-mapping \
  --function-name my-kafka-function \
  --topics AWSKafkaTopic \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123 \
  --starting-position LATEST \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=3 \
  --destination-config '{"OnFailure":{"Destination":"kafka://failed-records-topic"}}'
```

セルフマネージド型の Kafka の場合は、同じ構文を使用します。

```
aws lambda create-event-source-mapping \
  --function-name my-kafka-function \
  --topics AWSKafkaTopic \
  --self-managed-event-source '{"Endpoints":{"KAFKA_BOOTSTRAP_SERVERS":["abc.xyz.com:9092"]}}' \
  --starting-position LATEST \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=3 \
  --destination-config '{"OnFailure":{"Destination":"kafka://failed-records-topic"}}'
```

#### Kafka 送信先の更新
<a name="kafka-ofd-cli-update"></a>

`update-event-source-mapping` コマンドを使用して Kafka 送信先を追加または変更します。

```
aws lambda update-event-source-mapping \
  --uuid 12345678-1234-1234-1234-123456789012 \
  --destination-config '{"OnFailure":{"Destination":"kafka://failed-records-topic"}}'
```

## Kafka 送信先のレコード形式
<a name="kafka-ofd-record-format"></a>

Lambda が失敗したレコードを Kafka トピックに送信すると、各メッセージにはその障害に関するメタデータと実際のレコードコンテンツの両方が含まれます。

### 障害のメタデータ
<a name="kafka-ofd-metadata"></a>

メタデータには、レコードが失敗した理由に関する情報と元のバッチに関する詳細が含まれます。

```
{
  "requestContext": {
    "requestId": "e4b46cbf-b738-xmpl-8880-a18cdf61200e",
    "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST",
    "condition": "RetriesExhausted",
    "approximateInvokeCount": 3
  },
  "responseContext": {
    "statusCode": 200,
    "executedVersion": "$LATEST",
    "functionError": "Unhandled"
  },
  "version": "1.0",
  "timestamp": "2019-11-14T18:16:05.568Z",
  "KafkaBatchInfo": {
    "batchSize": 1,
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123",
    "bootstrapServers": "b-1.mycluster.abc123.kafka.us-east-1.amazonaws.com:9098",
    "payloadSize": 1162,
    "recordInfo": {
      "offset": "49601189658422359378836298521827638475320189012309704722",
      "timestamp": "2019-11-14T18:16:04.835Z"
    }
  },
  "payload": {
    "bootstrapServers": "b-1.mycluster.abc123.kafka.us-east-1.amazonaws.com:9098",
    "eventSource": "aws:kafka",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123",
    "records": {
      "my-topic-0": [
        {
          "headers": [],
          "key": "dGVzdC1rZXk=",
          "offset": 100,
          "partition": 0,
          "timestamp": 1749116692330,
          "timestampType": "CREATE_TIME",
          "topic": "my-topic",
          "value": "dGVzdC12YWx1ZQ=="
        }
      ]
    }
  }
}
```

### パーティションキーの動作
<a name="kafka-ofd-partitioning"></a>

Lambda は、送信先トピックに生成するときに、元のレコードと同じパーティションキーを使用します。元のレコードにキーがない場合、Lambda は送信先トピックで使用可能なすべてのパーティションで Kafka のデフォルトのラウンドロビンパーティショニングを使用します。

## 要件と制限
<a name="kafka-ofd-requirements"></a>
+ **プロビジョニングモードが必要** – Kafka 障害発生時の送信先は、プロビジョニングモードが有効になっているイベントソースマッピングでのみ使用できます。
+ **同じクラスターのみ** – 送信先トピックは、送信元トピックと同じ Kafka クラスターに存在する必要があります。
+ **トピックのアクセス許可** – イベントソースマッピングには、送信先トピックへの書き込みアクセス許可が必要です。例:

  ```
  {
      "Version": "2012-10-17",		 	 	 
      "Statement": [
          {
              "Sid": "ClusterPermissions",
              "Effect": "Allow",
              "Action": [
                  "kafka-cluster:Connect",
                  "kafka-cluster:DescribeCluster",
                  "kafka-cluster:DescribeTopic",
                  "kafka-cluster:WriteData",
                  "kafka-cluster:ReadData"
              ],
              "Resource": [
                  "arn:aws:kafka:*:*:cluster/*"
              ]
          },
          {
              "Sid": "TopicPermissions",
              "Effect": "Allow",
              "Action": [
                  "kafka-cluster:DescribeTopic",
                  "kafka-cluster:WriteData",
                  "kafka-cluster:ReadData"
              ],
              "Resource": [
                  "arn:aws:kafka:*:*:topic/*/*"
              ]
          },
          {
              "Effect": "Allow",
              "Action": [
                  "kafka:DescribeCluster",
                  "kafka:GetBootstrapBrokers",
                  "kafka:Produce"
              ],
              "Resource": "arn:aws:kafka:*:*:cluster/*"
          },
          {
              "Effect": "Allow",
              "Action": [
                  "ec2:CreateNetworkInterface",
                  "ec2:DescribeNetworkInterfaces",
                  "ec2:DeleteNetworkInterface",
                  "ec2:DescribeSubnets",
                  "ec2:DescribeSecurityGroups"
              ],
              "Resource": "*"
          }
      ]
  }
  ```
+ **反復なし** – 送信先トピック名を送信元トピック名と同じにすることはできません。

# Kafka イベントソースマッピングのログ記録
<a name="esm-logging"></a>

Kafka イベントソースマッピングのシステムレベルのログ記録を設定すると、Lambda イベントポーラーが CloudWatch に送信するシステムログを有効化およびフィルタリングできます。

この機能は Kafka イベントソースマッピングでのみ使用可能で、[プロビジョニングモード](https://docs.aws.amazon.com/lambda/latest/dg/kafka-scaling-modes.html#kafka-provisioned-mode)を指定して実行できます。

ログ記録設定を含むイベントソースマッピングの場合、コンソールの **[Lambda]** > **[その他のリソース]** > **[イベントソースマッピング]** ページにある **[モニタリング]** タブで、事前定義済みのログクエリによって返されたシステムログを確認することもできます。

## ログ記録の仕組み
<a name="esm-logging-overview"></a>

イベントソースマッピングでログレベルのログ記録設定を設定すると、Lambda イベントポーラーは対応するログ (イベントソースマッピングのシステムログ) を送信します。

イベントソースマッピングでは、Lambda 関数が使用しているのと同じ[ログ送信先](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-logs.html#configuring-log-destinations)が再利用されます。Lambda 関数の実行ロールに必要なログ記録権限があることを確認します。

イベントソースマッピングには独自のログストリーム機能があり、ログストリーム名は日付とイベントソースマッピングの UUID で構成されます (`2020/01/01/12345678-1234-1234-1234-12345678901`)。

イベントソースマッピングのシステムログについては、次のログレベルから選択できます。


| ログレベル | 使用方法 | 
| --- | --- | 
| DEBUG (詳細度が最も高い) | イベントソース処理の進行状況に関する詳細情報 | 
| 情報 | イベントソースマッピングの通常の動作に関するメッセージ | 
| WARN (詳細度が最も低い) | 予期しない動作につながる可能性のある潜在的な警告およびエラーに関するメッセージ | 

ログレベルを選択すると、Lambda イベントポーラーはそのレベル以下のログを送信します。例えば、イベントソースマッピングのシステムログレベルを INFO に設定すると、イベントポーラーは DEBUG レベルでログ出力を送信しません。

## ログの設定
<a name="esm-logging-configure"></a>

Kafka イベントソースマッピングを作成または更新するときに、ログ記録設定を設定できます。

### ログ記録の設定 (コンソール)
<a name="esm-logging-console"></a>

**ログ記録を設定するには (コンソール）**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 関数の名前を選択します。

1. 次のいずれかを行います。
   + 新しい Kafka トリガーを追加するには、**[関数の概要]** で **[トリガーを追加]** を選択します。
   + 既存の Kafka トリガーを変更するには、トリガーを選択し、**[編集]** を選択します。

1. **[イベントポーラーの設定]** の **[プロビジョニングモード]** で、**[設定]** チェックボックスを有効にします。**[ログレベル]** 設定が表示されます。

1.  **[ログレベル]** ドロップダウンリストをクリックし、イベントソースマッピングのレベルを選択します。

1. 下部にある **[追加]** または **[保存]** を選択して、イベントソースマッピングを作成または更新します。

### ログの設定 (AWS CLI)
<a name="esm-logging-cli"></a>

#### ログ記録付きイベントソースマッピングの作成
<a name="esm-logging-cli-create"></a>

次の例では、ログ記録設定を含む Amazon MSK イベントソースマッピングを作成します。

```
aws lambda create-event-source-mapping \
  --function-name my-kafka-function \
  --topics AWSKafkaTopic \
  --event-source-arn arn:aws:kafka:us-east-1:123456789012:cluster/my-cluster/abc123 \
  --starting-position LATEST \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=3 \
  --logging-config '{"SystemLogLevel":"DEBUG"}'
```

セルフマネージド型の Kafka の場合は、同じ構文を使用します。

```
aws lambda create-event-source-mapping \
  --function-name my-kafka-function \
  --topics AWSKafkaTopic \
  --self-managed-event-source '{"Endpoints":{"KAFKA_BOOTSTRAP_SERVERS":["abc.xyz.com:9092"]}}' \
  --starting-position LATEST \
  --provisioned-poller-config MinimumPollers=1,MaximumPollers=3 \
  --logging-config '{"SystemLogLevel":"DEBUG"}'
```

#### ログ記録設定の更新
<a name="esm-logging-cli-update"></a>

`update-event-source-mapping` コマンドを使用すると、ログ記録設定を追加または変更できます。

```
aws lambda update-event-source-mapping \
  --uuid 12345678-1234-1234-1234-123456789012 \
  --logging-config '{"SystemLogLevel":"WARN"}'
```

## Kafka イベントソースマッピングのシステムログのレコード形式
<a name="esm-logging-record-format"></a>

Lambda イベントポーラーがログを送信する場合、各ログエントリには一般的なイベントソースマッピングメタデータとイベント固有のコンテンツが含まれています。

### WARN ログレコード
<a name="esm-logging-warn-record"></a>

WARN レコードにはイベントポーラーからのエラーまたは警告が含まれ、イベントの発生時に出力されます。例えば、次のようになります。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1546347650000,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:12345678-1234-1234-1234-123456789012",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/tests-cluster/87654321-4321-4321-4321-876543221-s1",
    "eventProcessorId": "12345678-1234-1234-1234-123456789012/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "Timeout expired while fetching topic metadata",
        "errorCode": "org.apache.kafka.common.errors.TimeoutException"
    }
}
```

### INFO ログレコード
<a name="esm-logging-info-record"></a>

INFO レコードには各イベントポーラーの Kafka コンシューマークライアント設定が含まれ、コンシューマーの構築または変更といったイベント時に出力されます。例えば、次のようになります。

```
{
    "eventType": "POLLER_STATUS_EVENT",
    "timestamp": 1546347660000,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:12345678-1234-1234-1234-123456789012",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/tests-cluster/87654321-4321-4321-4321-876543221-s1",
    "eventProcessorId": "12345678-1234-1234-1234-123456789012/0",
    "logLevel": "INFO",
    "kafkaEventSourceConnection": {
        "brokerEndpoints": "boot-abcd1234.c2.kafka-serverless.us-east-1.amazonaws.com:9098",
        "consumerId": "12345678-1234-1234-1234-123456789012-0",
        "topics": [
            "test"
        ],
        "consumerGroupId": "12345678-1234-1234-1234-123456789012",
        "securityProtocol": "SASL_SSL",
        "saslMechanism": "AWS_MSK_IAM",
        "totalPartitionCount": 2,
        "assignedPartitionCount": 2,
        "partitionsAssignmentGeneration": 5,
        "assignedPartitions": [
            "test-0",
            "test-1"
        ],
        "networkConfig": {
            "ipAddresses": [
                "10.100.141.1"
            ],
            "subnetCidrBlock": "10.100.128.0/20",
            "securityGroups": [
                "sg-abcdefabcdefabcdef"
            ]
        }
    }
}
```

### DEBUG ログレコード
<a name="esm-logging-debug-record"></a>

DEBUG ログにはイベントソースマッピング処理における Kafka オフセットの関連情報が含まれ、オフセット情報は 1 分ごとに出力されます。例：

```
{
    "eventType": "KAFKA_STATUS_EVENT",
    "timestamp": 1546347670000,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:12345678-1234-1234-1234-123456789012",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/tests-cluster/87654321-4321-4321-4321-876543221-s1",
    "eventProcessorId": "12345678-1234-1234-1234-123456789012/0",
    "logLevel": "DEBUG",
    "kafkaPartitionOffsets": {
        "partition": "test-1",
        "endOffset": 5004,
        "consumedOffset": 5003,
        "processedOffset": 5003,
        "committedOffset": 5004
    }
}
```

# セルフマネージド Kafka イベントソースマッピングエラーのトラブルシューティング
<a name="with-kafka-troubleshoot"></a>

次のトピックでは、Lambda で Amazon MSK またはセルフマネージド Apache Kafka を使用するときに発生する可能性のあるエラーや問題のトラブルシューティングのアドバイスを提供します。

トラブルシューティングの詳細については、「 [AWS ナレッジセンター](https://repost.aws/knowledge-center#AWS_Lambda)」を参照してください。

## 認証と認可のエラー
<a name="kafka-permissions-errors"></a>

Kafka クラスターからのデータを消費するために必要な許可のいずれかが欠落している場合、Lambda は **[LastProcessingResult]** のイベントソースマッピングに以下のエラーメッセージのいずれかを表示します。

**Topics**
+ [クラスターが Lambda の認可に失敗した](#kafka-authorize-errors)
+ [SASL 認証に失敗した](#kafka-sasl-errors)
+ [Server failed to authenticate Lambda (サーバーが Lambda の認証に失敗しました)](#kafka-mtls-errors-server)
+ [Lambda failed to authenticate server (Lambda がサーバーの認証に失敗しました)](#kafka-mtls-errors-lambda)
+ [Provided certificate or private key is invalid (提供された証明書またはプライベートキーが無効です)](#kafka-key-errors)

### クラスターが Lambda の認可に失敗した
<a name="kafka-authorize-errors"></a>

SALS/SCRAM または mTLS の場合、このエラーは、指定されたユーザーが以下の必要とされる Kafka アクセスコントロールリスト (ACL) 許可のすべてを持っていないことを示します。
+ DescribeConfigs クラスター
+ グループを記述する
+ グループを読み取る
+ トピックを記述する
+ トピックを読み取る

必要な `kafka-cluster` 許可を使用して Kafka ACL を作成するときは、リソースとしてトピックとグループを指定します。トピック名は、イベントソースマッピングのトピックと一致する必要があります。グループ名は、イベントソースマッピングの UUID と一致する必要があります。

必要な許可を実行ロールに追加した後は、変更が有効になるまで数分間かかる場合があります。

この問題で[ログ記録設定](esm-logging.md)を有効にした後の ESM システムレベルのログの例を次に示します。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1734567890123,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/12345678-abcd-1234-efgh-EXAMPLE11111-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "Not authorized to access topics: [my-topic]",
        "errorCode": "org.apache.kafka.common.errors.TopicAuthorizationException"
    }
}
```

### SASL 認証に失敗した
<a name="kafka-sasl-errors"></a>

SASL/SCRAM または SASL/PLAIN の場合、このエラーは指定されたサインイン認証情報が無効であることを示します。

IAM アクセスコントロールの場合、実行ロールにクラスターに対する `kafka-cluster:Connect` 許可がありません。この許可をロールに追加して、クラスターの Amazon リソースネーム (ARN) をリソースとして指定します。

このエラーは断続的に発生する場合があります。クラスターは、TCP 接続の数がサービスクォータを超過すると、接続を拒否します。Lambda は接続に成功するまでバックオフし、再試行します。Lambda がクラスターに接続してレコードをポーリングすると、最後の処理結果が `OK` に変わります。

IAM 認証を使用するときにこの問題の[ログ記録設定](esm-logging.md)を有効にした後の ESM システムレベルのログの例を次に示します。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1734567890456,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLE22222",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/12345678-abcd-1234-efgh-EXAMPLE22222-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE22222/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "[a1b2c3d4-5678-90ab-cdef-EXAMPLE22222]: Access denied",
        "errorCode": "org.apache.kafka.common.errors.SaslAuthenticationException"
    }
}
```

### Server failed to authenticate Lambda (サーバーが Lambda の認証に失敗しました)
<a name="kafka-mtls-errors-server"></a>

このエラーは、Kafka ブローカーが Lambda の認証に失敗したことを示します。このエラーは、以下が原因で発生する可能性があります。
+ mTLS 認証用のクライアント証明書を提供していない。
+ クライアント証明書を提供したが、Kafka ブローカーが mTLS 認証を使用するように設定されていない。
+ クライアント証明書が Kafka ブローカーに信頼されていない。

### Lambda failed to authenticate server (Lambda がサーバーの認証に失敗しました)
<a name="kafka-mtls-errors-lambda"></a>

このエラーは、Lambda が Kafka ブローカーの認証に失敗したことを示します。このエラーは、以下が原因で発生する可能性があります。
+ セルフマネージド Apache Kafka の場合: Kafka ブローカーは自己署名証明書またはプライベート CA を使用するが、サーバールート CA 証明書を提供しなかった。
+ セルフマネージド Apache Kafka の場合: サーバールート CA 証明書が、ブローカーの証明書に署名したルート CA と一致しない。
+ ブローカーの証明書にサブジェクトの別名としてブローカーの DNS 名または IP アドレスが含まれていないため、ホスト名の検証が失敗した。

### Provided certificate or private key is invalid (提供された証明書またはプライベートキーが無効です)
<a name="kafka-key-errors"></a>

このエラーは、Kafka コンシューマーが提供された証明書またはプライベートキーを使用できなかったことを示します。証明書とキーが PEM 形式を使用しており、プライベートキーの暗号化が PBES1 アルゴリズムを使用していることを確認してください。

この問題で[ログ記録設定](esm-logging.md)を有効にした後の ESM システムレベルのログの例を次に示します。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1734567891234,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLE44444",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/12345678-abcd-1234-efgh-EXAMPLE44444-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE44444/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "Invalid PEM keystore configs",
        "errorCode": "org.apache.kafka.common.errors.InvalidConfigurationException"
    }
}
```

## ネットワークと接続のエラー
<a name="kafka-network-errors"></a>

ネットワーク設定の問題により、Lambda が Kafka クラスターに接続できなくなる可能性があります。以下のトピックでは、一般的なネットワーク関連のエラーについて説明します。

**Topics**
+ [セキュリティグループ設定による接続タイムアウト](#kafka-security-group-errors)
+ [Kafka ブローカーエンドポイントを解決できません](#kafka-cluster-deleted-errors)

### セキュリティグループ設定による接続タイムアウト
<a name="kafka-security-group-errors"></a>

Kafka クラスターに関連付けられたセキュリティグループがそれ自体からのインバウンドトラフィックを許可しない場合、Lambda はクラスターに接続できません。セキュリティグループのインバウンドルールで、Kafka ブローカーポートのセキュリティグループ自体からのトラフィックが許可されていることを確認します。

この問題で[ログ記録設定](esm-logging.md)を有効にした後の ESM システムレベルのログの例を次に示します。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1734567892345,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLE55555",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/12345678-abcd-1234-efgh-EXAMPLE55555-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE55555/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "Timeout expired while fetching topic metadata",
        "errorCode": "org.apache.kafka.common.errors.TimeoutException"
    }
}
```

Kafka コンシューマーの INFO ログを確認して、接続とネットワーク設定を確認することもできます。`brokerEndpoints` フィールドには Kafka ブローカーアドレスが表示され、`securityProtocol` と `saslMechanism` (該当する場合) には認証方法が表示され、`networkConfig` フィールドにはイベントソースマッピングで使用される IP アドレス、サブネット CIDR ブロック、セキュリティグループが表示されます。リストされているセキュリティグループで、必要なインバウンドトラフィックが許可されていることを確認します。

```
{
    "eventType": "POLLER_STATUS_EVENT",
    "timestamp": 1734567892456,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-11111EXAMPLE",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/a1b2c3d4-5678-90ab-cdef-11111EXAMPLE-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE/0",
    "logLevel": "INFO",
    "kafkaEventSourceConnection": {
        "brokerEndpoints": "boot-abcd1234.c2.kafka-serverless.us-east-1.amazonaws.com:9098",
        "consumerId": "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE-0",
        "topics": [
            "my-topic"
        ],
        "consumerGroupId": "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE",
        "securityProtocol": "SASL_SSL",
        "saslMechanism": "AWS_MSK_IAM",
        "totalPartitionCount": 2,
        "assignedPartitionCount": 2,
        "partitionsAssignmentGeneration": 1,
        "assignedPartitions": [
            "my-topic-0",
            "my-topic-1"
        ],
        "networkConfig": {
            "ipAddresses": [
                "10.0.0.37"
            ],
            "subnetCidrBlock": "10.0.0.32/28",
            "securityGroups": [
                "sg-0123456789abcdef0"
            ]
        }
    }
}
```

### Kafka ブローカーエンドポイントを解決できません
<a name="kafka-cluster-deleted-errors"></a>

このエラーは、Kafka クラスターが存在しないか、削除されたことを示します。イベントソースマッピングで指定されたクラスターが存在し、アクティブ状態であることを確認します。

この問題で[ログ記録設定](esm-logging.md)を有効にした後の ESM システムレベルのログの例を次に示します。

```
{
    "eventType": "ESM_PROCESSING_EVENT",
    "timestamp": 1734567893456,
    "resourceArn": "arn:aws:lambda:us-east-1:123456789012:event-source-mapping:a1b2c3d4-5678-90ab-cdef-EXAMPLE66666",
    "eventSourceArn": "arn:aws:kafka:us-east-1:123456789012:cluster/my-kafka-cluster/12345678-abcd-1234-efgh-EXAMPLE66666-1",
    "eventProcessorId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE66666/0",
    "logLevel": "WARN",
    "error": {
        "errorMessage": "No resolvable bootstrap urls given in bootstrap.servers",
        "errorCode": "org.apache.kafka.common.config.ConfigException"
    }
}
```

## イベントソースマッピングエラー
<a name="services-event-errors"></a>

Apache Kafka クラスターを Lambda 関数の[イベントソース](invocation-eventsourcemapping.md)として追加すると、関数でエラーが発生した場合、Kafka コンシューマーはレコードの処理を停止します。トピックパーティションのコンシューマーは、レコードのサブスクライブ、読み取り、処理を行います。その他の Kafka コンシューマーは、同じエラーが発生しない限り、レコードの処理を続行できます。

停止したコンシューマの原因を特定するには、`StateTransitionReason` のレスポンスの `EventSourceMapping` フィールドを確認します。以下は、受け取る可能性があるイベントソースエラーを説明するリストです。

**`ESM_CONFIG_NOT_VALID`**  
イベントソースマッピングの設定が無効です。

**`EVENT_SOURCE_AUTHN_ERROR`**  
Lambda がイベントソースを認証できませんでした。

**`EVENT_SOURCE_AUTHZ_ERROR`**  
Lambda にイベントソースへのアクセスに必要な許可がありません。

**`FUNCTION_CONFIG_NOT_VALID`**  
関数の設定が無効です。

**注記**  
Lambda のイベントレコードが許容サイズ制限である 6 MB を超えると、未処理になります。

# Amazon API Gateway エンドポイントを使用した Lambda 関数の呼び出し
<a name="services-apigateway"></a>

Amazon API Gateway を使用して、Lambda 関数の HTTP エンドポイントを持つウェブ API を作成できます。API Gateway は、HTTP リクエストを Lambda 関数にルーティングするウェブ API を、作成および文書化するためのツールを提供します。認証および認可のコントロールにより、API へのアクセスを保護できます。API は、インターネット経由でトラフィックを処理することも、VPC 内でのみアクセス可能にすることもできます。

**ヒント**  
Lambda には、HTTP エンドポイントを介して関数を呼び出す 2 つの方法として、API Gateway および Lambda 関数 URL が用意されています。ユースケースに最適な方法がわからない場合、「[HTTP リクエストを使用して Lambda 関数を呼び出す方法を選択する](apig-http-invoke-decision.md)」を参照してください。

API 内のリソースは、GET や POST などの 1 つ以上のメソッドを定義します。メソッドには、Lambda 関数または別の統合タイプにリクエストをルーティングする統合があります。各リソースとメソッドを個別に定義することも、特殊なリソースとメソッドタイプを使用して、パターンに一致するすべてのリクエストを照合することもできます。[プロキシリソース](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html)は、リソースの下にあるすべてのパスをキャッチします。`ANY` メソッドは、すべての HTTP メソッドをキャッチします。

**Topics**
+ [API タイプの選択](#services-apigateway-apitypes)
+ [エンドポイントの Lambda 関数への追加](#apigateway-add)
+ [プロキシ統合](#apigateway-proxy)
+ [イベント形式](#apigateway-example-event)
+ [レスポンスの形式](#apigateway-types-transforms)
+ [アクセス許可](#apigateway-permissions)
+ [サンプルアプリケーション](#services-apigateway-samples)
+ [Powertools for AWS Lambda のイベントハンドラー](#services-apigateway-powertools)
+ [チュートリアル: API Gateway で Lambda を使用する](services-apigateway-tutorial.md)
+ [API Gateway API を使用した Lambda エラーの処理](services-apigateway-errors.md)
+ [HTTP リクエストを使用して Lambda 関数を呼び出す方法を選択する](apig-http-invoke-decision.md)

## API タイプの選択
<a name="services-apigateway-apitypes"></a>

API Gateway は、Lambda 関数を呼び出す 3 種類の API をサポートしています。
+ [HTTP API](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html): 軽量で低レイテンシーの RESTful API。
+ [REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html): カスタマイズ可能で機能豊富な RESTful API。
+ [WebSocket API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html): 全二重通信のためにクライアントとの永続的な接続を維持するウェブ API。

HTTP API と REST API は、両方とも HTTP リクエストを処理し、レスポンスを返す RESTful API です。HTTP API は新しいバージョンであり、API Gateway バージョン 2 API を使用して構築されています。HTTP API では、次の機能が新しく追加されました。

**HTTP API の機能**
+ **自動デプロイ** - ルートまたは統合を変更した場合、変更は自動デプロイが有効になっているステージに自動的にデプロイされます。
+ **デフォルトステージ** - API の URL のルートパスでリクエストを処理するデフォルトステージ (`$default`) を作成できます。名前付きステージの場合は、パスの先頭にステージ名を含める必要があります。
+ **CORS 設定** - CORS ヘッダーを関数コードで手動で追加する代わりに、送信レスポンスに CORS ヘッダーを追加するように API を設定できます。

REST API は、当初から API Gateway でサポートされている従来の RESTful API です。REST API には現在、より多くのカスタマイズ、統合、および管理機能があります。

**REST API の機能**
+ **統合タイプ** - REST API は、カスタム Lambda 統合をサポートします。カスタム統合では、リクエストのボディだけを関数に送信するか、関数に送信する前にリクエストボディに変換テンプレートを適用できます。
+ **アクセスコントロール** - REST API では、認証と認可のためのより多くのオプションがサポートされています。
+ **モニタリングとトレース** - REST API では、AWS X-Ray のトレースと追加のログ記録オプションがサポートされます。

詳細な比較については、「*API ゲートウェイのデベロッパーガイド*」の「[REST API と HTTP API のどちらかを選択する](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html)」を参照してください。

WebSocket API も API Gateway バージョン 2 API を使用し、同様の機能セットをサポートします。クライアントと API 間の永続的な接続を活用できるアプリケーションには、WebSocket API を使用します。WebSocket API は全二重通信を提供します。つまり、クライアントと API の両方がレスポンスを待たずにメッセージを継続的に送信できます。

HTTP API では、簡略化されたイベント形式 (バージョン 2.0) がサポートされています。HTTP API からのイベントの例については、「[API Gateway で HTTP API の AWS Lambda プロキシ統合を作成する](https://docs.aws.amazon.com//apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)」を参照してください。

詳細については、「[API Gateway で HTTP API の AWS Lambda プロキシ統合を作成する](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)」を参照してください。

## エンドポイントの Lambda 関数への追加
<a name="apigateway-add"></a>

**パブリックエンドポイントを Lambda 関数に追加するには**

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. [**機能の概要**] で、[**トリガーを追加**] を選択します。

1. [** API Gateway **] を選択します。

1. **[Create an API]** (API の作成) または **[Use an existing API]** (既存の API の使用) を選択します。

   1. **[New API]** (新しい API): **[API type]** (API タイプ) で、**[HTTP API]** を選択します。詳細については、「[API タイプの選択](#services-apigateway-apitypes)」を参照してください。

   1. **[既存の API]**: ドロップダウンリストから API を選択するか、API ID (r3pmxmplak など) を入力します。

1. [**Security (セキュリティ)**] で、[**Open (開く)**] を選択します。

1. [**Add**] (追加) をクリックします。

## プロキシ統合
<a name="apigateway-proxy"></a>

API Gateway API は、ステージ、リソース、メソッド、および統合で構成されています。ステージとリソースによって、エンドポイントのパスが決まります。

**API パス形式**
+ `/prod/` - `prod` ステージおよびルートリソース。
+ `/prod/user` - `prod` ステージおよび `user` リソース。
+ `/dev/{proxy+}` - `dev` ステージ内の任意のルート。
+ `/` - (HTTP API) デフォルトのステージおよびルートリソース。

Lambda 統合は、パスと HTTP メソッドの組み合わせを Lambda 関数にマッピングします。HTTP リクエストのボディをそのまま渡すように (カスタム統合)、またはヘッダー、リソース、パス、メソッドなどすべてのリクエスト情報を含むドキュメントにリクエストボディをカプセル化するように、API Gateway を設定できます。

詳細については、「[API Gateway での Lambda プロキシ統合](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html)」を参照してください。

## イベント形式
<a name="apigateway-example-event"></a>

Amazon API Gateway は、HTTP リクエストの JSON 表現を含むイベントを使用して、関数を[同期的に](invocation-sync.md)呼び出します。カスタム統合の場合、イベントはリクエストのボディです。プロキシ統合の場合、イベントは定義された構造を持ちます。API Gateway REST API からのプロキシイベントの例については、「*API Gateway デベロッパーガイド*」の「[プロキシ統合のための Lambda 関数の入力形式](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format)」を参照してください。

## レスポンスの形式
<a name="apigateway-types-transforms"></a>

API Gateway は関数からのレスポンスを待ち、その結果を発信者に中継します。カスタム統合の場合は、統合レスポンスとメソッドレスポンスを定義して、関数からの出力を HTTP レスポンスに変換します。プロキシ統合の場合、関数はレスポンスを特定の形式で表現して応答する必要があります。

次の例は、Node.js 関数からのレスポンスオブジェクトを示しています。レスポンスオブジェクトは、JSON ドキュメントを含む成功した HTTP レスポンスを表します。

**Example index.js - プロキシ統合レスポンスオブジェクト (Node.js)**  

```
var response = {
      "statusCode": 200,
      "headers": {
        "Content-Type": "application/json"
      },
      "isBase64Encoded": false,
      "multiValueHeaders": { 
        "X-Custom-Header": ["My value", "My other value"],
      },
      "body": "{\n  \"TotalCodeSize\": 104330022,\n  \"FunctionCount\": 26\n}"
    }
```

Lambda ランタイムは、レスポンスオブジェクトを JSON にシリアル化し、API に送信します。API はレスポンスを解析し、それを使用して HTTP レスポンスを作成します。次に、そのレスポンスを元のリクエストを実行したクライアントに送信します。

**Example HTTP レスポンス**  

```
< HTTP/1.1 200 OK
  < Content-Type: application/json
  < Content-Length: 55
  < Connection: keep-alive
  < x-amzn-RequestId: 32998fea-xmpl-4268-8c72-16138d629356
  < X-Custom-Header: My value
  < X-Custom-Header: My other value
  < X-Amzn-Trace-Id: Root=1-5e6aa925-ccecxmplbae116148e52f036
  <
  {
    "TotalCodeSize": 104330022,
    "FunctionCount": 26
  }
```

## アクセス許可
<a name="apigateway-permissions"></a>

Amazon API Gateway は、関数の[リソースベースのポリシー](access-control-resource-based.md)から関数を呼び出すアクセス許可を取得します。API 全体に対する呼び出しアクセス許可を付与したり、ステージ、リソース、またはメソッドに対する制限付きアクセスを付与したりできます。

Lambda コンソールまたは API Gateway コンソールを使用するか、AWS SAM テンプレートで API を関数に追加すると、関数のリソースベースのポリシーが自動的に更新されます。関数ポリシーの例を以下に示します。

**Example 関数ポリシー**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Id": "default",
  "Statement": [
    {
      "Sid": "nodejs-apig-functiongetEndpointPermissionProd-BWDBXMPLXE2F",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-2:111122223333:function:nodejs-apig-function-1G3MXMPLXVXYI",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "111122223333"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:execute-api:us-east-2:111122223333:ktyvxmpls1/*/GET/"
        }
      }
    }
  ]
}
```

次の API オペレーションを使用して、関数ポリシーのアクセス許可を手動で管理できます。
+ [AddPermission](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html)
+ [RemovePermission](https://docs.aws.amazon.com/lambda/latest/api/API_RemovePermission.html)
+ [GetPolicy](https://docs.aws.amazon.com/lambda/latest/api/API_GetPolicy.html)

既存の API への呼び出しアクセス許可を付与するには、`add-permission` コマンドを使用します。例:

```
aws lambda add-permission \
  --function-name my-function \
  --statement-id apigateway-get --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-arn "arn:aws:execute-api:us-east-2:123456789012:mnh1xmpli7/default/GET/"
```

以下の出力が表示されます。

```
{
    "Statement": "{\"Sid\":\"apigateway-test-2\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-2:123456789012:function:my-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:us-east-2:123456789012:mnh1xmpli7/default/GET\"}}}"
}
```

**注記**  
関数と API が異なる AWS リージョンにある場合、ソース ARN のリージョン識別子は、API のリージョンではなく、関数のリージョンと一致している必要があります。API Gateway が関数を呼び出すと、API の ARN に基づくリソース ARN が使用されますが、その関数のリージョンと一致するように変更されます。

この例のソース ARN は、API のデフォルトステージにあるルートリソースの GET メソッドでの統合に ID `mnh1xmpli7` のアクセス許可を付与します。ソース ARN でアスタリスクを使用すると、複数のステージ、メソッド、またはリソースにアクセス許可を付与できます。

**リソースパターン**
+ `mnh1xmpli7/*/GET/*` - すべてのステージのすべてのリソースの GET メソッド。
+ `mnh1xmpli7/prod/ANY/user` - `prod` ステージの `user` リソースにおけるすべてのメソッド。
+ `mnh1xmpli7/*/*/*` - すべてのステージのすべてのリソースの任意のメソッド。

ポリシーの表示とステートメントの削除の詳細については、「」を参照してください[Lambda でのリソースベースの IAM ポリシーの表示](access-control-resource-based.md)

## サンプルアプリケーション
<a name="services-apigateway-samples"></a>

[Node.js を使用した API Gateway](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/nodejs-apig) のサンプルアプリには、AWS SAM テンプレートを使用した関数が含まれています。このテンプレートは、AWS X-Ray のトレースが有効にされた REST API を作成します。これには、デプロイ、関数の呼び出し、API のテスト、およびクリーンアップ用のスクリプトも含まれます。

## Powertools for AWS Lambda のイベントハンドラー
<a name="services-apigateway-powertools"></a>

Powertools for AWS Lambda ツールキットのイベントハンドラーは、API Gateway エンドポイント (HTTP または REST) によって呼び出される Lambda 関数を記述するときに、ルーティング、ミドルウェア、CORS 設定、OpenAPI 仕様生成、リクエスト検証、エラー処理、その他の便利な機能を提供します。イベントハンドラーユーティリティは、Python および TypeScript/JavaScript で使用できます。詳細については、*Powertools for AWS Lambda (Python) ドキュメント*の「[イベントハンドラー REST API](https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/)」および *Powertools for AWS Lambda (TypeScript) ドキュメント*の「[イベントハンドラー HTTP API](https://docs.aws.amazon.com/powertools/typescript/latest/features/event-handler/http/)」を参照してください。

### Python
<a name="services-apigateway-powertools-python"></a>

```
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing.lambda_context import LambdaContext

app = APIGatewayRestResolver()
logger = Logger()

@app.get("/healthz")
def ping():
    return {"message": "health status ok"}

@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)  
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)
```

### Typescript
<a name="services-apigateway-powertools-typescript"></a>

```
import { Router } from '@aws-lambda-powertools/event-handler/experimental-rest';
import { Logger } from '@aws-lambda-powertools/logger';
import {
  correlationPaths,
  search,
} from '@aws-lambda-powertools/logger/correlationId';
import type { Context } from 'aws-lambda/handler';

const logger = new Logger({
  correlationIdSearchFn: search,
});

const app = new Router({ logger });

app.get("/healthz", async () => {
  return { message: "health status ok" };
});

export const handler = async (event: unknown, context: Context) => {
  // You can continue using other utilities just as before
  logger.addContext(context);
  logger.setCorrelationId(event, correlationPaths.API_GATEWAY_REST);
  return app.resolve(event, context);
};
```

# チュートリアル: API Gateway で Lambda を使用する
<a name="services-apigateway-tutorial"></a>

このチュートリアルでは、HTTP リクエストを使用して Lambda 関数を呼び出す REST API を作成します。Lambda 関数は、DynamoDB テーブルで作成、読み取り、更新、および削除 (CRUD) 操作を実行します。このチュートリアルで提供される関数はデモ用ですが、任意の Lambda 関数を呼び出すことができる API Gateway REST API を設定する方法を学びます。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/APIG_tut_resources.png)


API Gateway を使用することで、Lambda 関数を呼び出すためのセキュアな HTTP エンドポイントがユーザーに提供されるとともに、トラフィックのスロットリングと、API コールの自動的な検証と承認によって、関数に対する大量の呼び出しを管理するためにも役立ちます。API Gateway は、AWS Identity and Access Management (IAM) と Amazon Cognito を使用した柔軟なセキュリティコントロールも提供します。これは、アプリケーションへの呼び出しに事前承認が必要なユースケースに役立ちます。

**ヒント**  
Lambda には、HTTP エンドポイントを介して関数を呼び出す 2 つの方法として、API Gateway および Lambda 関数 URL が用意されています。ユースケースに最適な方法がわからない場合、「[HTTP リクエストを使用して Lambda 関数を呼び出す方法を選択する](apig-http-invoke-decision.md)」を参照してください。

このチュートリアルは、以下の段階を通じて完了します。

1. DynamoDB テーブルで操作を実行するための Lambda 関数を Python または Node.js で作成し、設定する。

1. API Gateway で、Lambda 関数に接続するための REST API を作成する。

1. DynamoDB テーブルを作成し、コンソールで Lambda 関数を使用してテーブルをテストする。

1. API をデプロイし、ターミナルで curl を使用してセットアップ全体をテストする。

これらの段階を完了することにより、あらゆる規模で Lambda 関数をセキュアに呼び出すことができる HTTP エンドポイントを作成するために API Gateway を使用する方法を学びます。また、API をデプロイする方法と、それをコンソールでテスト、およびターミナルを使用して HTTP リクエストを送信することでテストする方法も学びます。

## 許可ポリシーを作成する
<a name="services-apigateway-tutorial-policy"></a>

Lambda 関数の[実行ロール](lambda-intro-execution-role.md)を作成する前に、必要な AWS リソースにアクセスするための許可を関数に付与する許可ポリシーを作成する必要があります。このチュートリアルでは、このポリシーが、DynamoDB テーブルで CRUD 操作を実行し、Amazon CloudWatch Logs に書き込むことを Lambda に許可します。

**ポリシーを作成する**

1. IAM コンソールの[ポリシー](https://console.aws.amazon.com/iam/home#/policies)ページを開きます。

1. **[ポリシーの作成]** を選択します。

1. **[JSON]** タブを選択して、次のカスタムポリシーを JSON エディタに貼り付けます。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Sid": "Stmt1428341300017",
         "Action": [
           "dynamodb:DeleteItem",
           "dynamodb:GetItem",
           "dynamodb:PutItem",
           "dynamodb:Query",
           "dynamodb:Scan",
           "dynamodb:UpdateItem"
         ],
         "Effect": "Allow",
         "Resource": "*"
       },
       {
         "Sid": "",
         "Resource": "*",
         "Action": [
           "logs:CreateLogGroup",
           "logs:CreateLogStream",
           "logs:PutLogEvents"
         ],
         "Effect": "Allow"
       }
     ]
   }
   ```

------

1. **[次へ: タグ]** を選択します。

1. **[次へ: レビュー]** を選択します。

1. **[ポリシーの確認]** でポリシーの **[名前]** に「**lambda-apigateway-policy**」と入力します。

1. **[ポリシーの作成]** を選択します。

## 実行ロールを作成する
<a name="services-apigateway-tutorial-role"></a>

[実行ロール](lambda-intro-execution-role.md)とは、AWS のサービス およびリソースに対するアクセス許可を Lambda 関数に付与する AWS Identity and Access Management (IAM) のロールです。関数が DynamoDB テーブルで操作を実行できるようにするには、前のステップで作成した許可ポリシーをアタッチします。

**実行ロールを作成して、カスタム許可ポリシーをアタッチする**

1. IAM コンソールの[ロールページ](https://console.aws.amazon.com/iam/home#/roles)を開きます。

1. **[ロールの作成]** を選択します。

1. 信頼されたエンティティには、**[AWS サービス]** を選択し、ユースケースには **[Lambda]** を選択します。

1. **[次へ]** をクリックします。

1. ポリシー検索ボックスに、「**lambda-apigateway-policy**」と入力します。

1. 検索結果で作成したポリシー (`lambda-apigateway-policy`) を選択し、**[次へ]** を選択します。

1. **[ロールの詳細]** で **[ロール名]** に **lambda-apigateway-role** を入力してから、**[ロールの作成]** を選択します。

## Lambda 関数を作成する
<a name="services-apigateway-tutorial-function"></a>

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、**[関数の作成]** を選択します。

1. **[一から作成]** を選択します。

1. **[関数名]** に「`LambdaFunctionOverHttps`」と入力します。

1. **[ランタイム]** で、最新の Node.js または Python ランタイムを選択します。

1. **[アクセス権限]** で、**[デフォルトの実行ロールの変更]** を展開します。

1. **[既存の実行ロールを使用する]** を選択し、前に作成した **lambda-apigateway-role** ロールを選択します。

1. [**関数の作成**] を選択してください。

1. **[コードソース]** ペインで、デフォルトコードを次の Node.js または Python コードに置き換えます。

------
#### [ Node.js ]

   `region` 設定は、関数をデプロイし、[DynamoDB テーブルを作成](#services-apigateway-tutorial-table)する AWS リージョン と一致させる必要があります。

**Example index.mjs**  

   ```
   import { DynamoDBDocumentClient, PutCommand, GetCommand, 
            UpdateCommand, DeleteCommand} from "@aws-sdk/lib-dynamodb";
   import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
   
   const ddbClient = new DynamoDBClient({ region: "us-east-2" });
   const ddbDocClient = DynamoDBDocumentClient.from(ddbClient);
   
   // Define the name of the DDB table to perform the CRUD operations on
   const tablename = "lambda-apigateway";
   
   /**
    * Provide an event that contains the following keys:
    *
    *   - operation: one of 'create,' 'read,' 'update,' 'delete,' or 'echo'
    *   - payload: a JSON object containing the parameters for the table item
    *     to perform the operation on
    */
   export const handler = async (event, context) => {
      
        const operation = event.operation;
      
        if (operation == 'echo'){
             return(event.payload);
        }
        
       else { 
           event.payload.TableName = tablename;
           let response;
           
           switch (operation) {
             case 'create':
                  response = await ddbDocClient.send(new PutCommand(event.payload));
                  break;
             case 'read':
                  response = await ddbDocClient.send(new GetCommand(event.payload));
                  break;
             case 'update':
                  response = ddbDocClient.send(new UpdateCommand(event.payload));
                  break;
             case 'delete':
                  response = ddbDocClient.send(new DeleteCommand(event.payload));
                  break;
             default:
               response = 'Unknown operation: ${operation}';
             }
           console.log(response);
           return response;
       }
   };
   ```

------
#### [ Python ]

**Example lambda\$1function.py**  

   ```
   import boto3
   
   # Define the DynamoDB table that Lambda will connect to
   table_name = "lambda-apigateway"
   
   # Create the DynamoDB resource
   dynamo = boto3.resource('dynamodb').Table(table_name)
   
   # Define some functions to perform the CRUD operations
   def create(payload):
       return dynamo.put_item(Item=payload['Item'])
   
   def read(payload):
       return dynamo.get_item(Key=payload['Key'])
   
   def update(payload):
       return dynamo.update_item(**{k: payload[k] for k in ['Key', 'UpdateExpression', 
       'ExpressionAttributeNames', 'ExpressionAttributeValues'] if k in payload})
   
   def delete(payload):
       return dynamo.delete_item(Key=payload['Key'])
   
   def echo(payload):
       return payload
   
   operations = {
       'create': create,
       'read': read,
       'update': update,
       'delete': delete,
       'echo': echo,
   }
   
   def lambda_handler(event, context):
       '''Provide an event that contains the following keys:
         - operation: one of the operations in the operations dict below
         - payload: a JSON object containing parameters to pass to the 
           operation being performed
       '''
       
       operation = event['operation']
       payload = event['payload']
       
       if operation in operations:
           return operations[operation](payload)
           
       else:
           raise ValueError(f'Unrecognized operation "{operation}"')
   ```

------
**注記**  
この例では、DynamoDB テーブルの名前が関数コード内の変数として定義されます。実際のアプリケーションでは、このパラメータを環境変数として渡し、テーブル名をハードコーディングしないことがベストプラクティスです。詳細については、「[AWS Lambda 環境変数の使用](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html)」を参照してください。

1. **[DEPLOY]** セクションで、**[デプロイ]** を選択して関数のコードを更新します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

## 関数をテストする
<a name="services-apigateway-tutorial-test-function"></a>

関数を API Gateway と統合する前に、関数が正常にデプロイされたことを確認します。Lambda コンソールを使用してテストイベントを関数に送信します。

1. 関数の Lambda コンソールページで、**[テスト]** タブを選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/test-tab.png)

1. **[イベント JSON]** セクションまで下にスクロールし、デフォルトのイベントを次のように置き換えます。このイベントは、Lambda 関数で想定される構造と一致します。

   ```
   {
       "operation": "echo",
       "payload": {
           "somekey1": "somevalue1",
           "somekey2": "somevalue2"
       }
   }
   ```

1. **[テスト]** を選択します。

1. **[関数の実行: 成功]** で、**[詳細]** を展開します。以下のようなレスポンスが表示されます。

   ```
   {
     "somekey1": "somevalue1",
     "somekey2": "somevalue2"
   }
   ```

## API Gateway を使用して REST API を作成する
<a name="services-apigateway-tutorial-api"></a>

このステップでは、Lambda 関数を呼び出すために使用する API Gateway REST API を作成します。

**API を作成するには**

1. [API Gateway コンソール](https://console.aws.amazon.com/apigateway)を開きます。

1. **[API の作成]** を選択します。

1. **[REST API]** ボックスで、**[構築]** を選択します。

1. **[API の詳細]** で **[新しい API]** を選択したままにし、**[API 名]** には **DynamoDBOperations** と入力します。

1. **[API の作成]** を選択します。

## REST API でリソースを作成する
<a name="services-apigateway-tutorial-resource"></a>

API に HTTP メソッドを追加するには、まずそのメソッドが操作を実行するリソースを作成する必要があります。ここでは、DynamoDB テーブルを管理するためのリソースを作成します。

**リソースを作成する**

1. [API Gateway コンソール](https://console.aws.amazon.com/apigateway)の API の **[リソース]** ページで、**[リソースの作成]** をクリックします。

1. **[リソースの詳細]** の **[リソース名]** に、**DynamoDBManager** と入力します。

1. **[リソースの作成]** を選択します。

## HTTP POST メソッドを作成する
<a name="services-apigateway-tutorial-method"></a>

このステップでは、`DynamoDBManager` リソースのためのメソッド (`POST`) を作成します。この `POST` メソッドを Lambda 関数にリンクして、メソッドが HTTP リクエストを受け取るときに、API Gateway が Lambda 関数を呼び出すようにします。

**注記**  
 このチュートリアルの目的上、DynamoDB テーブルですべての操作を実行する単一の Lambda 関数を呼び出すために、1 つの HTTP メソッド (`POST`) が使用されます。実際のアプリケーションでは、操作ごとに異なる Lambda 関数と HTTP メソッドを使用することがベストプラクティスです。詳細については、Serverless Land の「[Lambda モノリス](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/monolith)」を参照してください。

**POST メソッドを作成する**

1. API の **[リソース]** ページで、`/DynamoDBManager` リソースが強調表示されていることを確認します。次に、**[メソッド]** ペインで **[メソッドの作成]** をクリックします。

1. **[メソッドタイプ]** で、**[POST]** を選択します。

1. **[統合タイプ]** で、**[Lambda 関数]** を選択します。

1. **[Lambda 関数]** で、使用する関数 (`LambdaFunctionOverHttps`) の Amazon リソースネーム (ARN)を選択します。

1. **[メソッドの作成]** を選択します。

## DynamoDB テーブルを作成する
<a name="services-apigateway-tutorial-table"></a>

Lambda 関数が CRUD 操作を実行する空の DynamoDB テーブルを作成します。

**DynamoDB テーブルを作成する**

1. DynamoDB コンソールで [[テーブル]](https://console.aws.amazon.com/dynamodbv2#tables) ページを開きます。

1. **[テーブルの作成]** を選択します。

1. [**テーブルの詳細**] で、次の操作を行います。

   1. **[テーブル名]** に「**lambda-apigateway**」と入力します。

   1. **[パーティションキー]** に「**id**」と入力し、データ型を **[文字列]** のままにします。

1. **[Table settings]** (テーブル設定) では、**[Default settings]** (デフォルト設定) をそのまま使用します。

1. **[テーブルの作成]** を選択します。

## API Gateway、Lambda、および DynamoDB の統合をテストする
<a name="services-apigateway-tutorial-test-setup"></a>

これで、API Gateway API メソッドの Lambda 関数および DynamoDB テーブルとの統合をテストするための準備が整いました。API Gateway コンソールで、コンソールのテスト機能を使用して `POST` メソッドにリクエストを直接送信します。このステップでは、まず `create` 操作を使用して DynamoDB テーブルに新しい項目を追加し、次に `update` 操作を使用してその項目を変更します。

**テスト 1 DynamoDB テーブルで新しい項目を作成する**

1. [API Gateway コンソール](https://console.aws.amazon.com/apigateway)で、API (`DynamoDBOperations`) を選択します。

1. `DynamoDBManager` リソースの **[POST]** メソッドを選択します。

1. **[テスト]** タブを選択します。タブを表示するには、右矢印ボタンを選択する必要がある場合があります。

1. **[テストメソッド]** では、**[クエリ文字列]** と **[ヘッダー]** を空白のままにします。**[リクエスト本文]** に以下の JSON を貼り付けます。

   ```
   {
     "operation": "create",
     "payload": {
       "Item": {
         "id": "1234ABCD",
         "number": 5
       }
     }
   }
   ```

1. **[テスト]** を選択します。

   テストが完了したときに表示される結果には、`200` というステータスが表示されるはずです。このステータスコードは、`create` 操作が正常に実行されたことを示します。

    それを確認するため、DynamoDB テーブルに新しい項目が含まれていることをチェックします。

1. DynamoDB コンソールで [[Tables]](https://console.aws.amazon.com/dynamodbv2#tables) (テーブル) ページを開き、`lambda-apigateway` テーブルを選択します。

1. **[Explore table items]** (テーブルアイテムの探索) を選択します。**[返された項目]** ペインに、**[id]** `1234ABCD` と **[番号]** `5` が付いた 1 つの項目が表示されます。例:  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/items-returned.png)

**テスト 2 DynamoDB テーブルの項目を更新する**

1. [API Gateway コンソール](https://console.aws.amazon.com/apigateway)で POST メソッドの **[テスト]** タブに戻ります。

1. **[テストメソッド]** では、**[クエリ文字列]** と **[ヘッダー]** を空白のままにします。**[リクエスト本文]** に以下の JSON を貼り付けます。

   ```
   {
       "operation": "update",
       "payload": {
           "Key": {
               "id": "1234ABCD"
           },
           "UpdateExpression": "SET #num = :newNum",
           "ExpressionAttributeNames": {
               "#num": "number"
           },
           "ExpressionAttributeValues": {
               ":newNum": 10
           }
       }
   }
   ```

1. **[テスト]** を選択します。

   テストが完了したときに表示される結果には、`200` というステータスが表示されるはずです。このステータスコードは、`update` 操作が正常に実行されたことを示します。

    それを確認するため、DynamoDB テーブルの項目が変更されていることをチェックします。

1. DynamoDB コンソールで [[テーブル]](https://console.aws.amazon.com/dynamodbv2#tables) ページを開き、`lambda-apigateway` テーブルを選択します。

1. **[Explore table items]** (テーブルアイテムの探索) を選択します。**[返された項目]** ペインに、**[id]** `1234ABCD` と **[番号]** `10` が付いた 1 つの項目が表示されます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/items-returned-2.png)

## API をデプロイする
<a name="services-apigateway-tutorial-deploy-api"></a>

クライアントが API を呼び出すには、デプロイと関連するステージを作成する必要があります。ステージは、メソッドと統合が含まれる API のスナップショットを表します。

**API をデプロイする**

1. [API Gateway コンソール](https://console.aws.amazon.com/apigateway)の **[API]** ページを開き、`DynamoDBOperations` API を選択します。

1. API の **[リソース]** ページで **[API のデプロイ]** をクリックします。

1. **[ステージ]** で **[\$1新しいステージ\$1]** をクリックし、**[ステージ名]** には **test** を入力します。

1. **[デプロイ]** をクリックします。

1. **[ステージの詳細]** ペインで **[URL を呼び出す]** をコピーします。これは、HTTP リクエストを使用して関数を呼び出すために、次のステップで使用します。

## HTTP リクエストを使用して関数を呼び出すために curl を使用する
<a name="services-apigateway-tutorial-invoke-function"></a>

これで、API に HTTP リクエストを発行することで Lambda 関数を呼び出せるようになりました。このステップでは、DynamoDB テーブルに新しい項目を作成してから、その項目でオペレーションの読み取り、更新、削除を実行します。

**curl を使用して DynamoDB テーブルに項目を作成するには**

1. ローカルマシンでターミナルまたはコマンドプロンプトを開き、前のステップでコピーした呼び出し URL を使用して次の `curl` コマンドを実行します。このコマンドでは、以下のオプションを使用します。
   + `-H`: リクエストにカスタムヘッダーを追加します。ここでは、コンテンツタイプを JSON として指定します。
   + `-d`: リクエストボディでデータを送信します。このオプションは、デフォルトで HTTP POST メソッドを使用します。

------
#### [ Linux/macOS ]

   ```
   curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \
   -H "Content-Type: application/json" \
   -d '{"operation": "create", "payload": {"Item": {"id": "5678EFGH", "number": 15}}}'
   ```

------
#### [ PowerShell ]

   ```
   curl.exe 'https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager' -H 'Content-Type: application/json' -d '{\"operation\": \"create\", \"payload\": {\"Item\": {\"id\": \"5678EFGH\", \"number\": 15}}}'
   ```

------

   オペレーションが成功すると、HTTP ステータスコードが 200 のレスポンスが返されます。

1. また、次の操作を実行して、DynamoDB コンソールを使用して新しい項目がテーブルにあることを確認できます。

   1. DynamoDB コンソールで [[テーブル]](https://console.aws.amazon.com/dynamodbv2#tables) ページを開き、`lambda-apigateway` テーブルを選択します。

   1. **[Explore table items]** (テーブルアイテムの探索) を選択します。**[返された項目]** ペインに、**[id]** `5678EFGH` と **[number]** (番号) `15` が付いた 1 つの項目が表示されます。

**curl を使用して DynamoDB テーブルの項目を読み取るには**
+ ターミナルまたはコマンドプロンプトで、以下の `curl` コマンドを実行して、先ほど作成した項目の値を読み取ります。独自の呼び出し URL を使用してください。

------
#### [ Linux/macOS ]

  ```
  curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \
  -H "Content-Type: application/json" \
  -d '{"operation": "read", "payload": {"Key": {"id": "5678EFGH"}}}'
  ```

------
#### [ PowerShell ]

  ```
  curl.exe 'https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager' -H 'Content-Type: application/json' -d '{\"operation\": \"read\", \"payload\": {\"Key\": {\"id\": \"5678EFGH\"}}}'
  ```

------

  Node.js 関数コード、または Python 関数コードのどちらを選択したかに応じて、次のいずれかの出力が表示されます。

------
#### [ Node.js ]

  ```
  {"$metadata":{"httpStatusCode":200,"requestId":"7BP3G5Q0C0O1E50FBQI9NS099JVV4KQNSO5AEMVJF66Q9ASUAAJG",
  "attempts":1,"totalRetryDelay":0},"Item":{"id":"5678EFGH","number":15}}
  ```

------
#### [ Python ]

  ```
  {"Item":{"id":"5678EFGH","number":15},"ResponseMetadata":{"RequestId":"QNDJICE52E86B82VETR6RKBE5BVV4KQNSO5AEMVJF66Q9ASUAAJG",
  "HTTPStatusCode":200,"HTTPHeaders":{"server":"Server","date":"Wed, 31 Jul 2024 00:37:01 GMT","content-type":"application/x-amz-json-1.0",
  "content-length":"52","connection":"keep-alive","x-amzn-requestid":"QNDJICE52E86B82VETR6RKBE5BVV4KQNSO5AEMVJF66Q9ASUAAJG","x-amz-crc32":"2589610852"},
  "RetryAttempts":0}}
  ```

------

**curl を使用して DynamoDB テーブルの項目を更新するには**

1. ターミナルまたはコマンドプロンプトで、以下の `curl` コマンドを実行して、先ほど作成した項目の `number` 値を更新します。独自の呼び出し URL を使用してください。

------
#### [ Linux/macOS ]

   ```
   curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \
   -H "Content-Type: application/json" \
   -d '{"operation": "update", "payload": {"Key": {"id": "5678EFGH"}, "UpdateExpression": "SET #num = :new_value", "ExpressionAttributeNames": {"#num": "number"}, "ExpressionAttributeValues": {":new_value": 42}}}'
   ```

------
#### [ PowerShell ]

   ```
   curl.exe 'https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager' -H 'Content-Type: application/json' -d '{\"operation\": \"update\", \"payload\": {\"Key\": {\"id\": \"5678EFGH\"}, \"UpdateExpression\": \"SET #num = :new_value\", \"ExpressionAttributeNames\": {\"#num\": \"number\"}, \"ExpressionAttributeValues\": {\":new_value\": 42}}}'
   ```

------

1. 項目の `number` の値が更新されたことを確認するには、別の読み取りコマンドを実行します。

------
#### [ Linux/macOS ]

   ```
   curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \
   -H "Content-Type: application/json" \
   -d '{"operation": "read", "payload": {"Key": {"id": "5678EFGH"}}}'
   ```

------
#### [ PowerShell ]

   ```
   curl.exe 'https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager' -H 'Content-Type: application/json' -d '{\"operation\": \"read\", \"payload\": {\"Key\": {\"id\": \"5678EFGH\"}}}'
   ```

------

**curl を使用して DynamoDB テーブルの項目を削除するには**

1. ターミナルまたはコマンドプロンプトで、以下の `curl` コマンドを実行して、先ほど作成した項目を削除します。独自の呼び出し URL を使用してください。

------
#### [ Linux/macOS ]

   ```
   curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \
   -H "Content-Type: application/json" \
   -d '{"operation": "delete", "payload": {"Key": {"id": "5678EFGH"}}}'
   ```

------
#### [ PowerShell ]

   ```
   curl.exe 'https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager' -H 'Content-Type: application/json' -d '{\"operation\": \"delete\", \"payload\": {\"Key\": {\"id\": \"5678EFGH\"}}}'
   ```

------

1. 削除操作が正常に実行されたことを確認します。DynamoDB コンソールの **[項目を探索]** ページの **[返された項目]** ペインで、**[id]** `5678EFGH` の項目がテーブル内に存在しなくなったことを確認します。

## リソースをクリーンアップする (オプション)
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[Delete]** (削除) を選択します。

**API を削除する**

1. API Gateway コンソールで [API のページ](https://console.aws.amazon.com/apigateway/main/apis)を開きます。

1. 作成した API を選択します。

1. [** Actions**] で、[**Delete **] を選択します。

1. [**削除**] を選択します。

**DynamoDB テーブルを削除するには**

1. DynamoDB コンソールで [[Tables (テーブル)] ページ](https://console.aws.amazon.com//dynamodb/home#tables:)を開きます。

1. 作成したテーブルを選択します。

1. [**削除**] を選択します。

1. テキストボックスに「**delete**」と入力します。

1. **[テーブルの削除]** を選択します。

# API Gateway API を使用した Lambda エラーの処理
<a name="services-apigateway-errors"></a>

API Gateway はすべての呼び出しエラーと関数エラーを内部エラーとして扱います。Lambda API が呼び出しリクエストを拒否した場合、API Gateway は 500 エラーコードを返します。関数が実行されてもエラーが返された場合、または誤った形式でレスポンスが返された場合、API Gateway は 502 を返します。どちらの場合も、API Gateway からのレスポンスの本文は `{"message": "Internal server error"}` です。

**注記**  
API Gateway は、Lambda 呼び出しを再試行しません。Lambda がエラーを返す場合、API Gateway はクライアントにエラーレスポンスを返します。

以下の例では、関数エラーになり API Gateway から 502 が返されたリクエストの X-Ray トレースマップを示しています。クライアントは一般的なエラーメッセージを受け取ります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/tracemap-apig-502.png)


エラーレスポンスをカスタマイズするには、コードでエラーをキャッチし、レスポンスを必要な形式に加工する必要があります。

**Example [index.js](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/nodejs-apig/function/index.mjs) - エラーの形式**  

```
var formatError = function(error){
  var response = {
    "statusCode": error.statusCode,
    "headers": {
      "Content-Type": "text/plain",
      "x-amzn-ErrorType": error.code
    },
    "isBase64Encoded": false,
    "body": error.code + ": " + error.message
  }
  return response
}
```

API Gateway は、このレスポンスをカスタムステータスコードと本文を含む HTTP エラーに変換します。トレースマップで、関数ノードが緑色なのは、エラーを処理したためです。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/tracemap-apig-404.png)


# HTTP リクエストを使用して Lambda 関数を呼び出す方法を選択する
<a name="apig-http-invoke-decision"></a>

Lambda の一般的なユースケースの多くでは、HTTP リクエストを使用した関数の呼び出しを行います。例えば、ウェブアプリケーションがブラウザリクエストを通じて関数を呼び出すようにしたい場合があります。Lambda 関数を使用して、完全な REST API の作成、モバイルアプリからのユーザーインタラクションの処理、HTTP コールによる外部サービスからのデータの処理、カスタムウェブフックの作成を行うこともできます。

以下のセクションでは、HTTP によって Lambda を呼び出す際の選択について説明し、特定のユースケースに適した意思決定に役立つ情報を提供します。

## HTTP 呼び出し方法を選択する場合、どのような選択肢がありますか
<a name="w2aad101c29c46b9"></a>

Lambda には、HTTP リクエストを使用して関数を呼び出す方法として、主に[関数 URL](urls-configuration.md) と [API Gateway](services-apigateway.md) の 2 つがあります。両者の主な違いは以下のとおりです。
+ **Lambda 関数 URL** は、Lambda 関数のシンプルで直接的な HTTP エンドポイントを提供します。シンプルさとコスト効率のために最適化されており、HTTP 経由で Lambda 関数を公開するための最速のパスを提供します。
+ **API Gateway** は、豊富な機能を備えた API をビルドするためのより高度なサービスです。API Gateway は、本番環境 API を大規模にビルドおよび管理することに最適化されており、セキュリティ、モニタリング、トラフィック管理の包括的なツールを提供します。

## 要件が既にわかっている場合の推奨事項
<a name="w2aad101c29c46c11"></a>

要件が既に明確な場合は、基本的な推奨事項を以下に示します。

基本認証方式とリクエスト/レスポンス処理のみが必要で、コストと複雑さを最小限に抑えたいシンプルなアプリケーションやプロトタイプには、**[関数 URL](urls-configuration.md)** をお勧めします。

**[API Gateway](services-apigateway.md)** は、大規模な本稼働用アプリケーションや、[OpenAPI Description](https://www.openapis.org/) サポート、認証オプションの選択、カスタムドメイン名、またはスロットリング、キャッシュ、リクエスト/レスポンス変換を含む豊富なリクエスト/レスポンス処理など、より高度な機能が必要な場合に適しています。

## Lambda 関数を呼び出す方法を選択する際の考慮事項
<a name="w2aad101c29c46c13"></a>

関数 URL と API Gateway から選択する場合、次の要素を考慮する必要があります。
+ ユーザーの認証に OAuth または Amazon Cognito が必要かどうかなど、認証のニーズ
+ スケーリング要件と実装する API の複雑さ
+ リクエストの検証やリクエスト/レスポンスのフォーマットなどの高度な機能が必要かどうか
+ モニタリング要件
+ コスト目標

これらの要素を理解することで、セキュリティ、複雑さ、コスト要件のバランスを取るのに最適なオプションを選択できます。

次の情報は、2 つのオプションの主な違いをまとめたものです。

### 認証
<a name="w2aad101c29c46c13c11b1"></a>
+ **関数 URL** は AWS Identity and Access Management (IAM) を通じて基本的な認証オプションを提供します。エンドポイントは、パブリック (認証なし) にするか、IAM 認証を要求するように設定できます。IAM 認証では、標準の AWS 認証情報または IAM ロールを使用してアクセスを制御できます。設定は簡単ですが、このアプローチでは、他の認証方式に比べてオプションが限られています。
+ **API Gateway** では、より包括的な認証オプションが使用できます。IAM 認証に加えて、[Lambda オーソライザー](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) (カスタム認証ロジック)、[Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) ユーザープール、および OAuth2.0 フローを使用できます。この柔軟性により、サードパーティー認証プロバイダー、トークンベースの認証、多要素認証などの複雑な認証スキームを実装できます。

### リクエスト/レスポンス処理
<a name="w2aad101c29c46c13c11b3"></a>
+ **関数 URL** は、基本的な HTTP リクエストとレスポンスの処理を提供します。標準 HTTP メソッドがサポートされており、組み込みの Cross-Origin Resource Sharing (CORS) サポートが含まれています。JSON ペイロードとクエリパラメータは処理できますが、リクエスト変換や検証機能は提供されません。レスポンス処理も同様にシンプルです。クライアントは Lambda が返すのとまったく同じように、Lambda 関数からレスポンスを受け取ります。
+ **API Gateway** では、高度なリクエストおよびレスポンス処理機能が提供されます。リクエスト検証機能の定義、マッピングテンプレートを使用したリクエストとレスポンスの変換、リクエスト/レスポンスヘッダーの設定、およびレスポンスキャッシュの実装ができます。API Gateway はバイナリペイロードとカスタムドメイン名もサポートしており、クライアントに到達する前にレスポンスを変更できます。JSON スキーマを使用して、リクエスト/レスポンスの検証と変換のモデルを設定できます。

### スケーリング
<a name="w2aad101c29c46c13c11b5"></a>
+ **関数 URL** は、Lambda 関数の同時実行数の制限に合わせて直接スケーリングし、設定された同時実行数の上限まで関数をスケールアップすることでトラフィックの急増を処理します。この制限に達すると、Lambda は HTTP 429 レスポンスで追加のリクエストに応答します。組み込みのキューイングメカニズムがないため、スケーリングの処理は Lambda 関数の設定に完全に依存します。デフォルトでは、Lambda 関数の同時実行数は AWS リージョンあたり 1,000 に制限されています。
+ **API Gateway** には、Lambda 独自のスケーリングに加えて追加のスケーリング機能があります。リクエストキューイングとスロットリング制御が組み込まれているため、トラフィックの急増をより適切に管理できます。API Gateway は、デフォルトでリージョンごとに 1 秒あたり最大 10,000 件のリクエストを処理できます。バーストキャパシティは 1 秒あたり 5,000 件のリクエストです。また、バックエンドを保護するために、さまざまなレベル (API、ステージ、またはメソッド) でリクエストを調整するツールも提供します。

### モニタリング
<a name="w2aad101c29c46c13c11b7"></a>
+ **関数 URL** は、リクエスト数、レイテンシー、エラー率など、Amazon CloudWatch メトリクスによる基本的なモニタリングを提供します。標準の Lambda メトリクスとログにアクセスでき、関数に送信される未加工のリクエストが表示されます。これにより運用上の重要な可視性が得られますが、メトリクスは主に関数の実行に関するものになります。
+ **API Gateway** では、詳細なメトリクス、ログ記録、トレースオプションなど、包括的なモニタリング機能が提供されます。CloudWatch を使用して、API コール、レイテンシー、エラー率、キャッシュヒット/ミス率をモニタリングできます。また、API Gateway は AWS X-Ray と統合して分散型トレースを行い、ログ形式のカスタマイズが可能です。

### Cost
<a name="w2aad101c29c46c13c11b9"></a>
+ **関数 URL** は、標準の Lambda 料金モデルに従います。関数の呼び出しと計算時間についてのみ料金が発生します。URL エンドポイント自体には追加料金はかかりません。これにより、API Gateway の追加機能が必要ない場合は、シンプルな API またはトラフィックの少ないアプリケーションに対して費用対効果の高い選択肢になります。
+ **API Gateway** には、REST API で受信される 100 万回の API コールと、HTTP API で受信される 100 万回の API コールを含む[無料利用枠](https://aws.amazon.com/api-gateway/pricing/#Free_Tier)が用意されています。無料利用枠を超えると、API Gateway では API コール、データ転送、キャッシュ (有効になっている場合) に対して料金が発生します。独自のユースケースのコストについては、API Gateway の[料金ページ](https://aws.amazon.com/api-gateway/pricing/)を参照してください。

### その他の機能
<a name="w2aad101c29c46c13c11c11"></a>
+ **関数 URL** は、簡単に利用でき、Lambda と直接統合できるように設計されています。HTTP エンドポイントと HTTPS エンドポイントの両方をサポートし、組み込みの CORS サポートとデュアルスタック (IPv4 および IPv6) エンドポイントを提供します。高度な機能はありませんが、HTTP 経由で Lambda 関数を公開する迅速かつシンプルな方法が必要なシナリオに適しています。
+ **API Gateway** には、API バージョニング、ステージ管理、使用量プランの API キー、Swagger/OpenAPI による API ドキュメント、WebSocket API、VPC 内のプライベート API、セキュリティを強化するための WAF 統合など、さまざまな追加機能が含まれています。また、カナリアデプロイ、テスト用のモック統合、Lambda 以外の他の AWS のサービスとの統合もサポートされています。

## Lambda 関数を呼び出す方法を選択する
<a name="w2aad101c29c46c15"></a>

Lambda 関数 URL と API Gateway の選択基準とその主な違いについて確認した後は、ニーズに最適なオプションを選択し、以下のリソースを使用して利用を開始できます。

------
#### [ Function URLs ]

**以下のリソースを使用して関数 URL の使用を開始する**
+ 「[チュートリアル: 関数 URL を使用する Lambda 関数の作成](urls-webhook-tutorial.md)」に従います。
+ 関数 URL の詳細については、このガイドの「[Lambda 関数 URL の作成と管理](urls-configuration.md)」の章を参照してください。
+ 次の操作を実行して、コンソール内ガイド付きチュートリアル「**シンプルなウェブアプリケーションを作成**」を試します。

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 画面の右上にあるアイコンを選択して、ヘルプパネルを開きます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_help_screenshot.png)

1. **[チュートリアル]** を選択します。

1. **[シンプルなウェブアプリケーションを作成]** で、**[チュートリアルを開始]** を選択します。

------
#### [ API Gateway ]

**以下のリソースを使用して Lambda と API Gateway の使用を開始する**
+ 「[チュートリアル: API Gateway で Lambda を使用する](services-apigateway-tutorial.md)」に従って、バックエンド Lambda 関数と統合した REST API を作成します。
+ API Gateway が提供するさまざまな種類の API の詳細については、「*Amazon API Gateway デベロッパーガイド*」の以下のセクションを参照してください。
  + [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html)
  + [API Gateway HTTP API](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html)
  + [API Gateway WebSocket API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html)
+ 「*Amazon API Gateway デベロッパーガイド*」の「[Amazon API Gateway のチュートリアルとワークショップ](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-tutorials.html)」セクションで 1 つまたは複数の例を試してください。

------

# での AWS Lambda の使用AWS Infrastructure Composer
<a name="services-appcomposer"></a>

AWS Infrastructure Composer は、AWS で最新のアプリケーションを設計するためのビジュアルビルダーです。ビジュアルキャンバスで AWS のサービスをドラッグ、グループ化、接続して、アプリケーションアーキテクチャを設計します。Infrastructure Composer は、[AWS SAM](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) または [CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) を使用してデプロイできる設計から Infrastructure as Code (IaC) テンプレートを作成します。

## Infrastructure Composer への Lambda 関数のエクスポート
<a name="services-appcomposer-export"></a>

Infrastructure Composer の使用を開始するには、Lambda コンソールを使用して既存の Lambda 関数の設定に基づいて新しいプロジェクトを作成します。関数の設定とコードを Infrastructure Composer にエクスポートして新しいプロジェクトを作成するには、以下の操作を行います。

1. Lambda コンソールの「[関数](https://console.aws.amazon.com/lambda/home#/functions)」ページを開きます。

1. Infrastructure Composer プロジェクトの基礎として使用する関数を選択します。

1. **[関数の概要]** ペインで、**[Infrastructure Composer にエクスポート]** を選択します。

   関数の設定とコードを Infrastructure Composer にエクスポートするには、Lambda でアカウントに Amazon S3 バケットを作成し、このデータを一時的に保存します。

1. ダイアログボックスで **[プロジェクトの確認と作成]** を選択し、このバケットのデフォルト名をそのまま使用して、関数の設定とコードを Infrastructure Composer にエクスポートします。

1. (オプション) Lambda で作成する Amazon S3 バケットに別の名前を選択する場合は、新しい名前を入力して **[プロジェクトの確認と作成]** を選択します。Amazon S3 バケットの名前は、グローバルに一意で、[バケットの命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)に従ったものである必要があります。

1. プロジェクトファイルと関数ファイルを Infrastructure Composer に保存するには、[ローカル同期モード](https://docs.aws.amazon.com/application-composer/latest/dg/reference-features-local-sync.html)をアクティブ化します。

**注記**  
以前に **[Application Composer にエクスポート]** 機能を使用し、デフォルト名を使用して Amazon S3 バケットを作成したことがある場合、Lambda はこのバケットがまだ存在していれば再利用できます。既存のバケットを再利用するには、ダイアログボックスのデフォルトのバケット名をそのまま使用してください。

### Amazon S3 転送バケット設定
<a name="services-appcomposer-bucket-info"></a>

Lambda が関数の設定を転送するために作成する Amazon S3 バケットは、AES 256 暗号化標準を使用してオブジェクトを自動的に暗号化します。また、Lambda は[バケット所有者条件](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html)を使用するようにバケットを設定して、ユーザーの AWS アカウントだけがバケットにオブジェクトを追加できるようにします。

Lambda は、アップロードされてから 10 日後にオブジェクトを自動的に削除するようにバケットを設定します。ただし、Lambda はバケット自体を自動的に削除しません。AWS アカウントからバケットを削除するには、「[バケットの削除](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html)」の手順に従います。デフォルトのバケット名には、プレフィックス `lambdasam`、10 桁の英数字の文字列、および関数を作成した AWS リージョンが使用されます。

```
lambdasam-06f22da95b-us-east-1
```

AWS アカウントに追加料金が発生しないように、関数を Infrastructure Composer にエクスポートし終えたらすぐに Amazon S3 バケットを削除することをお勧めします。

標準の [Amazon S3 の料金](https://aws.amazon.com/s3/pricing/)が適用されます。

### 必要なアクセス許可
<a name="services-appcomposer-permissions"></a>

Lambda と Infrastructure Composer の統合機能を使用するには、AWS SAM テンプレートをダウンロードし、関数の設定を Amazon S3 に書き込むための特定の権限が必要です。

AWS SAM テンプレートをダウンロードするには、次の API アクションに対するアクセス権限が必要です。
+ [GetPolicy](https://docs.aws.amazon.com/lambda/latest/api/API_GetPolicy.html)
+ [iam:GetPolicyVersion](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetPolicyVersion.html)
+ [iam:GetRole](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRole.html)
+ [iam:GetRolePolicy](https://docs.aws.amazon.com/IAM/latest/APIReference/API_GetRolePolicy.html)
+ [iam:ListAttachedRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html)
+ [iam:ListRolePolicies](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRolePolicies.html)
+ [iam:ListRoles](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListRoles.html)

IAM ユーザーロールに [https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambda_ReadOnlyAccess.html](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambda_ReadOnlyAccess.html) AWS マネージドポリシーを追加することで、これらすべてのアクションを使用する権限を付与できます。

Lambda が関数の設定を Amazon S3 に書き込むには、以下の API アクションを使用するアクセス許可が必要です。
+ [S3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
+ [S3:CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)
+ [S3:PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)
+ [S3:PutBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html)

関数の設定を Infrastructure Composer にエクスポートできない場合は、アカウントにこれらのオペレーションに必要なアクセス許可があることを確認してください。必要なアクセス許可を持っていても、関数の設定をエクスポートできない場合は、Amazon S3 へのアクセスを制限している可能性がある[リソースベースのポリシー](access-control-resource-based.md)がないか確認します。

## その他のリソース
<a name="w2aad101c33b7"></a>

既存の Lambda 関数に基づいて Infrastructure Composer でサーバーレスアプリケーションを設計する方法のより詳細なチュートリアルについては、「[Lambda と Infrastructure as code (IaC) の使用](foundation-iac.md)」を参照してください。

Infrastructure Composer および AWS SAM を使用し、Lambda を使用して完全なサーバーレスアプリケーションを設計およびデプロイするには、「[AWS Serverless Patterns Workshop](https://catalog.workshops.aws/serverless-patterns/en-US)」の「[AWS Infrastructure Composer tutorial](https://catalog.workshops.aws/serverless-patterns/en-US/dive-deeper/module1a)」に従うこともできます。

# AWS Lambdaと使用するCloudFormation
<a name="services-cloudformation"></a>

AWS CloudFormation テンプレートでは、Lambda 関数をカスタムリソースのターゲットとして指定できます。パラメータの処理にカスタムリソースを使用したり、設定値を取得したり、スタックのライフサイクルイベント中に他の AWS のサービスを呼び出したりします。

次の例は、テンプレートの別の場所で定義される関数を呼び出します。

**Example - カスタムリソースの定義**  

```
Resources:
  primerinvoke:
    Type: [AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html)
    Version: "1.0"
    Properties:
      ServiceToken: !GetAtt primer.Arn
      FunctionName: !Ref randomerror
```

サービストークンは、スタックの作成、更新あるいは削除時に CloudFormation が呼び出す関数の Amazon リソースネーム (ARN) です。また、`FunctionName` のように CloudFormation が関数にそのまま渡す追加のプロパティを含めることができます。

CloudFormation では、コールバック URL を含むイベントで[非同期的に](invocation-async.md) Lambda 関数を呼び出します。

**Example – CloudFormation メッセージイベント**  

```
{
    "RequestType": "Create",
    "ServiceToken": "arn:aws:lambda:us-east-1:123456789012:function:lambda-error-processor-primer-14ROR2T3JKU66",
    "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3-us-east-1.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A123456789012%3Astack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456%7Cprimerinvoke%7C5d478078-13e9-baf0-464a-7ef285ecc786?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Expires=1555451971&Signature=28UijZePE5I4dvukKQqM%2F9Rf1o4%3D",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456",
    "RequestId": "5d478078-13e9-baf0-464a-7ef285ecc786",
    "LogicalResourceId": "primerinvoke",
    "ResourceType": "AWS::CloudFormation::CustomResource",
    "ResourceProperties": {
        "ServiceToken": "arn:aws:lambda:us-east-1:123456789012:function:lambda-error-processor-primer-14ROR2T3JKU66",
        "FunctionName": "lambda-error-processor-randomerror-ZWUC391MQAJK"
    }
}
```

関数は、成功あるいは失敗を示すコールバック URL にレスポンスを返す処理を行います 完全なレスポンスの構文については、「[カスタムリソースの応答オブジェクト](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html)」を参照してください。

**Example – CloudFormation カスタムリソース応答**  

```
{
    "Status": "SUCCESS",
    "PhysicalResourceId": "2019/04/18/[$LATEST]b3d1bfc65f19ec610654e4d9b9de47a0",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456",
    "RequestId": "5d478078-13e9-baf0-464a-7ef285ecc786",
    "LogicalResourceId": "primerinvoke"
}
```

CloudFormation は応答の送信を処理する `cfn-response` という名前のライブラリを提供します。テンプレートで関数を定義する場合、ライブラリを名前で使用できます。CloudFormation はこのライブラリを作成する関数のデプロイパッケージに追加します。

カスタムリソースが使用する関数に [Elastic Network Interface](configuration-vpc.md#configuration-vpc-enis) がアタッチされている場合、次のリソースを **region** が関数が属するリージョンにダッシュがない VPC ポリシーに追加します。たとえば、`us-east-1` は `useast1` です。これにより、カスタムリソースは、CloudFormation スタックにシグナルを送り返すコールバック URL に応答できるようになります。

```
arn:aws:s3:::cloudformation-custom-resource-response-region",
"arn:aws:s3:::cloudformation-custom-resource-response-region/*",
```

次の関数例では、2 番目の関数を呼び出しています。呼び出しが成功すると、この関数は成功レスポンスを CloudFormation に送信し、スタックの更新が継続します。テンプレートは、AWS Serverless Application Model から提供される [AWS:: Serverless:: Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) リソースタイプを使用します。

**Example – カスタムリソース関数**  

```
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  primer:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Handler: index.handler
      Runtime: nodejs16.x
      InlineCode: |
        var aws = require('aws-sdk');
        var response = require('cfn-response');
        exports.handler = function(event, context) {
            // For Delete requests, immediately send a SUCCESS response.
            if (event.RequestType == "Delete") {
                response.send(event, context, "SUCCESS");
                return;
            }
            var responseStatus = "FAILED";
            var responseData = {};
            var functionName = event.ResourceProperties.FunctionName
            var lambda = new aws.Lambda();
            lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                if (err) {
                    responseData = {Error: "Invoke call failed"};
                    console.log(responseData.Error + ":\n", err);
                }
                else responseStatus = "SUCCESS";
                response.send(event, context, responseStatus, responseData);
            });
        };
      Description: Invoke a function to create a log stream.
      MemorySize: 128
      Timeout: 8
      Role: !GetAtt role.Arn
      Tracing: Active
```

カスタムリソースが呼び出す関数がテンプレートで定義されていない場合、AWS CloudFormation の [cfn-response モジュール](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html)から `cfn-response` のリソースコードを取得できます。

カスタムリソースの詳細については、*AWS CloudFormationユーザーガイド*の[カスタムリソース](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html)を参照してください。

# Lambda を使用した Amazon DocumentDB イベントの処理
<a name="with-documentdb"></a>

Amazon DocumentDB クラスターをイベントソースとして設定することにより、Lambda 関数を使用して [Amazon DocumentDB (MongoDB 互換) 変更ストリーム](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html)でイベントを処理できます。その後、Amazon DocumentDB クラスターでデータが変更されるたびに Lambda 関数を呼び出すことで、イベント駆動型のワークロードを自動化できます。

**注記**  
Lambda では Amazon DocumentDB のバージョン 4.0 および 5.0 のみがサポートされています。バージョン 3.6 はサポートされていません。  
また、イベントソースマッピングでは、Lambda はインスタンスベースのクラスターとリージョンレベルのクラスターのみをサポートします。Lambda は、[Elastic クラスター](https://docs.aws.amazon.com/documentdb/latest/developerguide/docdb-using-elastic-clusters.html)または[グローバルクラスター](https://docs.aws.amazon.com/documentdb/latest/developerguide/global-clusters.html)をサポートしていません。この制限は、Lambda を Amazon DocumentDB に接続するクライアントとして使用する場合には適用されません。Lambda はすべてのクラスタータイプに接続して CRUD 操作を実行できます。

Lambda は、Amazon DocumentDB 変更ストリームからのイベントを、到着した順序に沿って処理します。このため、関数は Amazon DocumentDB からの同時呼び出しを一度に 1 つしか処理できません。関数を監視するには、その[同時実行メトリクス](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-concurrency.html)を追跡できます。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

**Topics**
+ [Amazon DocumentDB イベントの例](#docdb-sample-event)
+ [前提条件とアクセス許可](#docdb-prereqs)
+ [ネットワークセキュリティを設定する](#docdb-network)
+ [Amazon DocumentDB イベントソースマッピングを作成する (コンソール)](#docdb-configuration)
+ [Amazon DocumentDB イベントソースマッピングを作成する (SDK または CLI)](#docdb-api)
+ [ポーリングとストリームの開始位置](#docdb-stream-polling)
+ [Amazon DocumentDB イベントソースのモニタリング](#docdb-monitoring)
+ [チュートリアル: Amazon DocumentDB を用いて AWS Lambda のストリームの使用](with-documentdb-tutorial.md)

## Amazon DocumentDB イベントの例
<a name="docdb-sample-event"></a>

```
{
    "eventSourceArn": "arn:aws:rds:us-east-1:123456789012:cluster:canaryclusterb2a659a2-qo5tcmqkcl03",
    "events": [
        {
            "event": {
                "_id": {
                    "_data": "0163eeb6e7000000090100000009000041e1"
                },
                "clusterTime": {
                    "$timestamp": {
                        "t": 1676588775,
                        "i": 9
                    }
                },
                "documentKey": {
                    "_id": {
                        "$oid": "63eeb6e7d418cd98afb1c1d7"
                    }
                },
                "fullDocument": {
                    "_id": {
                        "$oid": "63eeb6e7d418cd98afb1c1d7"
                    },
                    "anyField": "sampleValue"
                },
                "ns": {
                    "db": "test_database",
                    "coll": "test_collection"
                },
                "operationType": "insert"
            }
        }
    ],
    "eventSource": "aws:docdb"
}
```

この例のイベントとその形状の詳細については、MongoDB ドキュメントウェブサイトの「[変更イベント](https://www.mongodb.com/docs/manual/reference/change-events/)」を参照してください。

## 前提条件とアクセス許可
<a name="docdb-prereqs"></a>

Amazon DocumentDB を Lambda 関数のイベントソースとして使用する前に、次の前提条件に注意してください。必要なもの:
+ **関数と同じ AWS アカウント と AWS リージョン に既存の Amazon DocumentDB クラスターが必要です。**既存のクラスターがない場合は、「*Amazon DocumentDB デベロッパーガイド*」の「[Amazon DocumentDB の開始方法](https://docs.aws.amazon.com/documentdb/latest/developerguide/get-started-guide.html)」のステップに従って作成できます。または、「[チュートリアル: Amazon DocumentDB を用いて AWS Lambda のストリームの使用](with-documentdb-tutorial.md)」の最初の一連のステップに従って、必要な前提条件をすべて備えた Amazon DocumentDB クラスターを作成する方法もあります。
+ **Lambda が、Amazon DocumentDB クラスターに関連付けられている Amazon Virtual Private Cloud (Amazon VPC) リソースにアクセスできるようにします。**詳細については、「[ネットワークセキュリティを設定する](#docdb-network)」を参照してください。
+ **Amazon DocumentDB クラスターで TLS を有効にします。**これはデフォルトの設定です。TLS を無効にすると、Lambda はクラスターと通信できません。
+ **Amazon DocumentDB クラスターで変更ストリームをアクティブ化します。**詳細については、「*Amazon DocumentDB デベロッパーガイド*」の「[Amazon DocumentDB で変更ストリームを使用する](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html)」を参照してください。
+ **Amazon DocumentDB クラスターにアクセスするための認証情報を Lambda に提供します。**イベントソースを設定するときは、クラスターへのアクセスに必要な認証の詳細 (ユーザー名とパスワード) を含む [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) キーを指定します。セットアップ中にこのキーを指定するには、次のいずれかを行います。
  + セットアップに Lambda コンソールを使用している場合は、**[Secrets Manager キー]** フィールドでこのキーを指定します。
  + セットアップに AWS Command Line Interface (AWS CLI) を使用している場合は、`source-access-configurations` オプションでこのキーを指定します。このオプションは、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドまたは [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドのどちらにも含めることができます。例えば、次のようになります。

    ```
    aws lambda create-event-source-mapping \
        ...
        --source-access-configurations  '[{"Type":"BASIC_AUTH","URI":"arn:aws:secretsmanager:us-west-2:123456789012:secret:DocDBSecret-AbC4E6"}]' \
        ...
    ```
+ **Amazon DocumentDB ストリームに関連するリソースを管理するには、Lambda に許可を付与します。**関数の[実行ロール](lambda-intro-execution-role.md)に次の許可を手動で追加します。
  + [rds:DescribeDBClusters](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusters.html)
  + [rds:DescribeDBClusterParameters](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusterParameters.html)
  + [rds:DescribeDBSubnetGroups](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBSubnetGroups.html)
  + [ec2:CreateNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
  + [ec2:DescribeNetworkInterfaces](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
  + [ec2:DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
  + [ec2:DeleteNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
  + [ec2:DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
  + [ec2:DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
  + [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)
  + [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)
+ **Lambda に送信する Amazon DocumentDB 変更ストリームイベントのサイズは 6 MB 未満にしてください。**Lambda は最大 6 MB のペイロードサイズをサポートします。変更ストリームが 6 MB を超えるイベントを Lambda に送信しようとすると、Lambda はメッセージを削除して `OversizedRecordCount` メトリクスを発行します。Lambda は、ベストエフォートベースですべてのメトリクスを発行します。

**注記**  
Lambda 関数の最大タイムアウト制限は通常 15 分ですが、Amazon MSK、自己管理型 Apache Kafka、Amazon DocumentDB、および ActiveMQ と RabbitMQ 向け Amazon MQ のイベントソースマッピングでは、最大タイムアウト制限が 14 分の関数のみがサポートされます。この制約により、イベントソースマッピングは関数エラーと再試行を適切に処理できます。

## ネットワークセキュリティを設定する
<a name="docdb-network"></a>

イベントソースマッピングを通じて Lambda に Amazon DocumentDB へのフルアクセスを許可するには、クラスターがパブリックエンドポイント (パブリック IP アドレス) を使用するか、クラスターを作成した Amazon VPC へのアクセスを提供する必要があります。

Lambda で Amazon DocumentDB を使用する場合は、関数に Amazon VPC 内のリソースへのアクセスを付与する [AWS PrivateLink VPC エンドポイント](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html)を作成します。

**注記**  
イベントポーラーにデフォルト (オンデマンド) モードを使用するイベントソースマッピングを持つ関数には、AWS PrivateLink VPC エンドポイントが必要です。イベントソースマッピングが[プロビジョンドモード](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)を使用している場合は、AWS PrivateLink VPC エンドポイントを設定する必要はありません。

エンドポイントを作成して、次のリソースへのアクセスを提供します。
+  Lambda — Lambda サービスプリンシパルのエンドポイントを作成します。
+  AWS STS — サービスプリンシパルがユーザーに代わってロールを引き受けるために、AWS STS のエンドポイントを作成します。
+  Secrets Manager — クラスターが Secrets Manager を使用して認証情報を保存する場合は、Secrets Manager のエンドポイントを作成します。

または、Amazon VPC の各パブリックサブネットに NAT ゲートウェイを設定します。詳細については、「[VPC に接続された Lambda 関数にインターネットアクセスを有効にする](configuration-vpc-internet.md)」を参照してください。

Amazon DocumentDB のイベントソースマッピングを作成するとき、Lambda は Amazon VPC 用に設定されたサブネットおよびセキュリティグループに Elastic Network Interface (ENI) が既に存在するかどうかを確認します。Lambda が既存の ENI を検出した場合、再利用しようとします。それ以外の場合、Lambda は新しい ENI を作成し、イベントソースに接続して関数を呼び出します。

**注記**  
Lambda 関数は、Lambda サービスが所有する VPC 内で常に実行されます。関数の VPC 設定はイベントソースマッピングに影響しません。Lambda がイベントソースに接続する方法を判定するのは、イベントソースのネットワーク設定のみです。

クラスターを含む Amazon VPC のセキュリティグループを設定します。デフォルトでは、Amazon DocumentDB はポート: `27017` を使用します。
+ インバウンドルール – イベントソースに関連付けられたセキュリティグループに対してデフォルトのブローカーポート上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、同じセキュリティグループ内のインスタンスからのアクセスを許可することもできます。
+ アウトバウンドルール – 関数が AWS サービスと通信する必要がある場合、外部送信先のポート `443` 上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、他の AWS サービスと通信する必要がない場合は、ブローカーへのアクセスを制限することもできます。
+ Amazon VPC エンドポイントのインバウンドルール – Amazon VPC エンドポイントを使用している場合、Amazon VPC エンドポイントに関連付けられたセキュリティグループは、クラスターセキュリティグループからポート `443` でインバウンドトラフィックを許可する必要があります。

クラスターが認証を使用する場合、Secrets Manager エンドポイントのエンドポイントポリシーを制限することもできます。Secrets Manager API を呼び出す場合、Lambda は Lambda サービスプリンシパルではなく、関数ロールを使用します。

**Example VPC エンドポイントポリシー – Secrets Manager エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "secretsmanager:GetSecretValue",
              "Effect": "Allow",
              "Principal": {
                  "AWS": [
                      "arn:aws::iam::123456789012:role/my-role"
                  ]
              },
              "Resource": "arn:aws::secretsmanager:us-west-2:123456789012:secret:my-secret"
          }
      ]
  }
```

Amazon VPC エンドポイントを使用する場合、AWS は API コールをルーティングし、エンドポイントの Elastic Network Interface (ENI) を使用して関数を呼び出します。Lambda サービスプリンシパルは、これらの ENI を使用するすべてのロールおよび関数に対して `lambda:InvokeFunction` を呼び出す必要があります。

デフォルトでは、Amazon VPC エンドポイントには、リソースへの広範なアクセスを許可するオープンな IAM ポリシーが適用されています。そのエンドポイントを使用して必要なアクションを実行するためのベストプラクティスは、これらのポリシーを制限することです。イベントソースマッピングが Lambda 関数を呼び出せるようにするには、VPC エンドポイントポリシーで、Lambda サービスプリンシパルが `sts:AssumeRole` および `lambda:InvokeFunction` を呼び出すことを許可する必要があります。組織内で発生する API コールのみを許可するように VPC エンドポイントポリシーを制限すると、イベントソースマッピングが正しく機能しなくなるため、これらのポリシーには `"Resource": "*"` が必要です。

次の VPC エンドポイントポリシーの例では、AWS STS および Lambda エンドポイントに Lambda サービスプリンシパルの必要なアクセスを付与する方法について示しています。

**Example VPC エンドポイントポリシー - AWS STS エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
    }
```

**Example VPC エンドポイントポリシー – Lambda エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "lambda:InvokeFunction",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
  }
```

## Amazon DocumentDB イベントソースマッピングを作成する (コンソール)
<a name="docdb-configuration"></a>

Amazon DocumentDB クラスターの変更ストリームから読み取る Lambda 関数に対して、[イベントソースマッピング](invocation-eventsourcemapping.md)を作成します。このセクションでは、Lambda コンソールからこれを実行する方法を説明します。AWSSDK と AWS CLI 手順については、「[Amazon DocumentDB イベントソースマッピングを作成する (SDK または CLI)](#docdb-api)」を参照してください。

**Amazon DocumentDB イベントソースマッピングを作成するには (コンソール)**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 関数の名前を選択します。

1. **[関数の概要]** で **[トリガーを追加]** をクリックします。

1. **[トリガーの設定]** のドロップダウンリストから **[DocumentDB]** を選択します。

1. 必要なオプションを設定し、**[追加]** を選択します。

Lambda は、Amazon DocumentDB イベントソースの以下のオプションをサポートしています。
+ **[DocumentDB クラスター]** – Amazon DocumentDB クラスターを選択します。
+ **[トリガーをアクティブ化]** – トリガーを今すぐアクティブ化するかどうかを選択します。このチェックボックスをオンにすると、関数は、イベントソースマッピングの作成時に、指定された Amazon DocumentDB 変更ストリームからのトラフィックの受信を直ちに開始します。チェックボックスをオフにして、テストのために非アクティブ化された状態でイベントソースマッピングを作成することを推奨します。作成後、いつでもイベントソースマッピングをアクティブ化できます。
+ **[データベース名]** – 使用するクラスター内のデータベースの名前を入力します。
+ (オプション) **[コレクション名]** – 使用するデータベース内のコレクションの名前を入力します。コレクションを指定しない場合、Lambda はデータベース内の各コレクションのすべてのイベントをリッスンします。
+ **[バッチサイズ]** - 単一のバッチで取得するメッセージの最大数 (最大 10,000 件) を設定します。デフォルトバッチサイズは 100 です。
+ **[開始位置] –** レコードの読み取りを開始するストリーム内の位置を選択します。
  + **[最新] -** ストリームに追加された新しいレコードのみを処理します。関数は、Lambda がイベントソースの作成を完了した後にのみ、レコードの処理を開始します。これは、イベントソースが正常に作成されるまで、一部のレコードが削除される可能性があることを意味します。
  + **[水平トリム]** - ストリーム内のすべてのレコードを処理します。Lambda は、クラスターのログ保持期間を使用して、イベントの読み取りを開始する場所を決定します。具体的には、Lambda は `current_time - log_retention_duration` から読み取りを開始します。Lambda がすべてのイベントを読み取るには、このタイムスタンプの前に変更ストリームが既にアクティブになっている必要があります。
  + **[タイムスタンプ]** - 特定の時刻以降のレコードを処理します。Lambda がすべてのイベントを適切に読み取るには、指定されたタイムスタンプの前に変更ストリームが既にアクティブになっている必要があります。
+ **[認証]** – クラスター内のブローカーにアクセスするための認証方法を選択します。
  + **[BASIC\$1AUTH]** – 基本認証では、クラスターにアクセスするための認証情報を含む Secrets Manager キーを指定する必要があります。
+ **[Secrets Manager キー]** – Amazon DocumentDB クラスターへのアクセスに必要な認証の詳細 (ユーザー名とパスワード) を含む Secrets Manager キーを選択します。
+ (オプション) **[バッチウィンドウ]** - 関数を呼び出す前にレコードを収集する最大時間を 300 までの秒数で設定します。
+ (オプション) **[ドキュメントの完全な設定]** – ドキュメントの更新オペレーションでは、ストリームに送信するものを選択します。デフォルト値は `Default` です。これは、各変更ストリームイベントについて、行われた変更について記述するデルタのみを Amazon DocumentDB が送信することを意味します。このフィールドの詳細については、MongoDB Javadocs の API ドキュメントの「[FullDocument](https://mongodb.github.io/mongo-java-driver/3.9/javadoc/com/mongodb/client/model/changestream/FullDocument.html#DEFAULT)」を参照してください。
  + **[デフォルト]** – Lambda は、行われた変更について記述する部分的なドキュメントのみを送信します。
  + **[UpdateLookup]** – Lambda は、ドキュメント全体のコピーとともに、変更について記述するデルタを送信します。

## Amazon DocumentDB イベントソースマッピングを作成する (SDK または CLI)
<a name="docdb-api"></a>

Amazon DocumentDB イベントソースマッピングを [AWS SDK](https://aws.amazon.com/developer/tools/) を使用して作成または管理するには、次の API オペレーションを使用します。
+ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)
+ [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html)
+ [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html)
+ [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)
+ [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html)

AWS CLI を使用してイベントソースマッピングを作成するには、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドを使用します。以下の例では、このコマンドを使用して、`my-function` という名前の関数を Amazon DocumentDB 変更ストリームにマッピングします。イベントソースは Amazon リソースネーム (ARN) によって指定され、バッチサイズ 500 で、Unix 時間形式のタイムスタンプから始まります。このコマンドでは、Lambda が Amazon DocumentDB への接続に使用する Secrets Manager キーも指定します。さらに、データベースと読み取り元のコレクションを指定する `document-db-event-source-config` パラメーターも含まれています。

```
aws lambda create-event-source-mapping --function-name my-function \
    --event-source-arn arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy
    --batch-size 500 \
    --starting-position AT_TIMESTAMP \
    --starting-position-timestamp 1541139109 \
    --source-access-configurations '[{"Type":"BASIC_AUTH","URI":"arn:aws:secretsmanager:us-east-1:123456789012:secret:DocDBSecret-BAtjxi"}]' \
    --document-db-event-source-config '{"DatabaseName":"test_database", "CollectionName": "test_collection"}' \
```

次のような出力が表示されます。

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "BatchSize": 500,
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "MaximumBatchingWindowInSeconds": 0,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541348195.412,
    "LastProcessingResult": "No records processed",
    "State": "Creating",
    "StateTransitionReason": "User action"
}
```

作成後、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドを使用して、Amazon DocumentDB イベントソースに関連する設定を更新できます。次の例では、バッチサイズを 1,000 に更新し、バッチウィンドウを 10 秒に更新します。このコマンドには、`list-event-source-mapping` コマンドまたは Lambda コンソールから取得できるイベントソースマッピングの UUID が必要です。

```
aws lambda update-event-source-mapping --function-name my-function \
    --uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
    --batch-size 1000 \
    --batch-window 10
```

このような出力が表示されます。

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "BatchSize": 500,
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "MaximumBatchingWindowInSeconds": 0,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541359182.919,
    "LastProcessingResult": "OK",
    "State": "Updating",
    "StateTransitionReason": "User action"
}
```

Lambda は設定を非同期的に更新するため、プロセスが完了するまでこれらの変更が出力に表示されない場合があります。イベントソースマッピングの現在の設定を表示するには、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html) コマンドを使用します。

```
aws lambda get-event-source-mapping --uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b
```

このような出力が表示されます。

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "BatchSize": 1000,
    "MaximumBatchingWindowInSeconds": 10,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541359182.919,
    "LastProcessingResult": "OK",
    "State": "Enabled",
    "StateTransitionReason": "User action"
}
```

Amazon DocumentDB イベントソースマッピングを削除するには、[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/delete-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/delete-event-source-mapping.html) コマンドを使用します。

```
aws lambda delete-event-source-mapping \
    --uuid 2b733gdc-8ac3-cdf5-af3a-1827b3b11284
```

## ポーリングとストリームの開始位置
<a name="docdb-stream-polling"></a>

イベントソースマッピングの作成時および更新時のストリームのポーリングは、最終的に一貫性があることに注意してください。
+ イベントソースマッピングの作成時、ストリームからのイベントのポーリングが開始されるまでに数分かかる場合があります。
+ イベントソースマッピングの更新時、ストリームからのイベントのポーリングが停止および再開されるまでに数分かかる場合があります。

つまり、`LATEST` をストリームの開始位置として指定すると、イベントソースマッピングの作成または更新中にイベントを見逃す可能性があります。イベントを見逃さないようにするには、ストリームの開始位置を `TRIM_HORIZON` または `AT_TIMESTAMP` として指定します。

## Amazon DocumentDB イベントソースのモニタリング
<a name="docdb-monitoring"></a>

Amazon DocumentDB イベントソースのモニタリングに役立つよう、関数がレコードのバッチの処理を完了したときに、Lambda は `IteratorAge` メトリクスを発行します。*イテレータの有効期間*とは、最新のイベントのタイムスタンプと現在のタイムスタンプの差のことです。基本的に、`IteratorAge` メトリクスは、バッチで最後に処理されたレコードの古さを示します。関数が新しいイベントを現在処理している場合、イテレーターの有効期間を使用して、レコードが追加されてから関数によって処理されるまでのレイテンシーを推定できます。`IteratorAge` の増加傾向は、関数に問題があることを示している可能性があります。詳細については、「[Lambda での CloudWatch メトリクスの使用](monitoring-metrics.md)」を参照してください。

Amazon DocumentDB の変更ストリームは、イベント間の大きなタイムギャップを処理するようには最適化されていません。Amazon DocumentDB イベントソースが長期間にイベントを受信しない場合、Lambda はイベントソースマッピングを無効にすることがあります。この期間の長さは、クラスターのサイズやその他のワークロードに応じて、数週間から数か月までさまざまです。

Lambda は最大 6 MB のペイロードをサポートします。ただし、Amazon DocumentDB 変更ストリームイベントのサイズは最大 16 MB です。変更ストリームが 6 MB を超える変更ストリームイベントを Lambda に送信しようとすると、Lambda はメッセージを削除して `OversizedRecordCount` メトリクスを発行します。Lambda は、ベストエフォートベースですべてのメトリクスを発行します。

# チュートリアル: Amazon DocumentDB を用いて AWS Lambda のストリームの使用
<a name="with-documentdb-tutorial"></a>

 このチュートリアルでは、Amazon DocumentDB (MongoDB 互換) 変更ストリームからのイベントを処理する基本的な Lambda 関数を作成します。このチュートリアルは、以下の段階を通じて完了します。
+ Amazon DocumentDB クラスターをセットアップして接続し、そのクラスターで変更ストリームをアクティブ化します。
+ Lambda 関数を作成し、Amazon DocumentDB クラスターを関数のイベントソースとして設定します。
+ Amazon DocumentDB データベースにアイテムを挿入して、セットアップをテストします。

## Amazon DocumentDB クラスターの作成
<a name="docdb-documentdb-cluster"></a>

1. [Amazon DocumentDB コンソール](https://console.aws.amazon.com/docdb/home#)を開きます。**[クラスタ]** で **[作成]** を選択します。

1. 次の設定でクラスターを作成します。
   + **[クラスタータイプ]** で **[インスタンスベースのクラスター]** を選択します。これがデフォルトのオプションです。
   + **[クラスター設定]** で、**[エンジンバージョン]** 5.0.0 が選択されていることを確認します。これがデフォルトのオプションです。
   + **[インスタンス設定]** で次の設定を行なってください。
     + **[DB インスタンスクラス]** で、**[メモリ最適化クラス]** を選択します。これがデフォルトのオプションです。
     + **[通常のレプリカインスタンスの数]** には 1 を選択します。
     + **[インスタンスクラス]** にはデフォルトの選択を使用します。
   + **[認証]** でプライマリユーザーのユーザー名を入力し、**[セルフマネージド]** を選択します。パスワードを入力して確認します。
   + 他のデフォルト設定をすべて維持します。

1. **[クラスターを作成]** を選択します。

## Secrets Manager でシークレットを作成する
<a name="docdb-secret-in-secrets-manager"></a>

Amazon DocumentDB がクラスターを作成している間に、データベースの認証情報を保存する AWS Secrets Manager シークレットを作成します。このシークレットは、後の手順で Lambda イベントソースマッピングを作成するときに指定します。

**Secrets Manager でシークレットを保存するには**

1. [[Secrets Manager]](https://console.aws.amazon.com/secretsmanager/home#) コンソールを開き、**[新しいシークレットを保存]** を選択します。

1. **[シークレットのタイプを選択]** で、以下のいずれかのオプションを選択します。
   + **[基本情報]** の下:
     + **[シークレットタイプ]**: Amazon DocumentDB データベース用の認証情報
     + **[認証情報]** で、Amazon DocumentDB クラスターの作成に使用したユーザー名およびパスワードを入力します。
     + **[データベース]**: ご使用の Amazon DocumentDB クラスターを選択します。
     + [**次へ**] を選択します。

1. **[条件]** は、以下のオプションから選択します。
   + **[シークレット名]**: `DocumentDBSecret`
   + [**次へ**] を選択します。

1. [**次へ**] を選択します。

1. [**保存する**] を選択します。

1. コンソールを更新して、`DocumentDBSecret` シークレットが正常に保存されたことを確認します。

**[シークレット ARN]** をメモしておきます。これは、後のステップで必要になります。

## クラスターに接続する
<a name="docdb-connect-to-cluster"></a>

**AWS CloudShell を使用して Amazon DocumentDB クラスターに接続する**

1. Amazon DocumentDB マネジメントコンソールの **[クラスター]** で、作成したクラスターを探します。クラスターの横にあるチェックボックスをクリックして選択します。

1. **[クラスターに接続]** を選択します。CloudShell の **[Run コマンド]** 画面が表示されます。

1. **[新しい環境の名前]** フィールドに、「test」などの一意の名前を入力し、**[作成して実行する]** を選択します。

1. プロンプトが表示されたら、パスワードを入力します。プロンプトが `rs0 [direct: primary] <env-name>>` に変わったら、Amazon DocumentDB クラスターに正常に接続できています。

## 変更ストリームを有効にする
<a name="docdb-activate-change-streams"></a>

本チュートリアルでは、Amazon DocumentDB クラスター内にある `docdbdemo` データベースの `products` コレクションへの変更を追跡します。これを行うには、[[変更ストリーム]](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html) を有効にします。

**クラスター内に新しいデータベースを作成するには**

1. 次のコマンドを実行し、`docdbdemo` と呼ばれる新しいデータベースを作成します。

   ```
   use docdbdemo
   ```

1. ターミナルウィンドウで、次のコマンドを使用してレコードを `docdbdemo` に挿入します。

   ```
   db.products.insertOne({"hello":"world"})
   ```

   次のような出力が表示されます。

   ```
   {
     acknowledged: true,
     insertedId: ObjectId('67f85066ca526410fd531d59')
   }
   ```

1. 次に、次のコマンドを使用して、`docdbdemo` データベースの `products` コレクションの変更ストリームを有効にします。

   ```
   db.adminCommand({modifyChangeStreams: 1,
       database: "docdbdemo",
       collection: "products", 
       enable: true});
   ```

    次のような出力が表示されます。

   ```
   { "ok" : 1, "operationTime" : Timestamp(1680126165, 1) }
   ```

## インターフェイス VPC エンドポイントを作成する
<a name="docdb-create-interface-vpc-endpoints"></a>

次に、[インターフェイス VPC エンドポイント](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#create-interface-endpoint-aws)を作成して、Lambda と Secrets Manager (後でクラスターアクセス認証情報を保存するために使用) がデフォルト VPC に接続できるようにします。

**インターフェイス VPC エンドポイントを作成するには**

1. [[VPC] コンソール](https://console.aws.amazon.com/vpc/home#)を開きます。左側のメニューの **[仮想プライベートクラウド]** で、**[エンドポイント]** を選択します。

1. **エンドポイントの作成** を選択します。次の構成でエンドポイントを作成します。
   + **[名前タグ]** に「`lambda-default-vpc`」を入力します。
   + **[サービスカテゴリ]** で、[AWS サービス] を選択します。
   + **サービス**には、検索ボックスで「`lambda`」と入力します。フォーマット `com.amazonaws.<region>.lambda` のサービスを選択してください。
   + **[VPC]** で、Amazon DocumentDB クラスターがある VPC を選択します。通常、これは[デフォルト VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) になります。
   + **サブネット** には、各アベイラビリティーゾーンの横にあるボックスをチェックします。それぞれのアベイラビリティゾーンに正しいサブネット ID を選択します。
   + [**IP アドレスの種類**] には [IPv4] を選択します。
   + **[セキュリティグループ]** で、Amazon DocumentDB クラスターが使用するセキュリティグループを選択します。通常、これは `default` セキュリティグループになります。
   + 他のデフォルト設定をすべて維持します。
   + **エンドポイントの作成** を選択します。

1. **[エンドポイントの作成]** を再び選択します。次の構成でエンドポイントを作成します。
   + **[名前タグ]** に「`secretsmanager-default-vpc`」を入力します。
   + **[サービスカテゴリ]** で、[AWS サービス] を選択します。
   + **サービス**には、検索ボックスで「`secretsmanager`」と入力します。フォーマット `com.amazonaws.<region>.secretsmanager` のサービスを選択してください。
   + **[VPC]** で、Amazon DocumentDB クラスターがある VPC を選択します。通常、これは[デフォルト VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html) になります。
   + **サブネット** には、各アベイラビリティーゾーンの横にあるボックスをチェックします。それぞれのアベイラビリティゾーンに正しいサブネット ID を選択します。
   + [**IP アドレスの種類**] には [IPv4] を選択します。
   + **[セキュリティグループ]** で、Amazon DocumentDB クラスターが使用するセキュリティグループを選択します。通常、これは `default` セキュリティグループになります。
   + 他のデフォルト設定をすべて維持します。
   + **エンドポイントの作成** を選択します。

 これで、このチュートリアルのクラスターセットアップの部分は完了です。

## 実行ロールを作成する
<a name="docdb-create-the-execution-role"></a>

 次のステップでは、Lambda 関数を作成します。まず、クラスターにアクセスするためのアクセス許可を関数に付与する実行ロールを作成する必要があります。これを行うには、最初に IAM ポリシーを作成してから、次にこのポリシーを IAM ロールにアタッチします。

**IAM ポリシーを作成するには**

1. IAM コンソールの [[ポリシー] ページ](https://console.aws.amazon.com/iam/home#/policies) を開き、**[ポリシーの作成]** を選択します。

1. **JSON** タブを選択します。次のポリシーでは、ステートメントの最後の行にある Secrets Manager リソース ARN を以前のシークレット ARN で置き換え、ポリシーをエディタにコピーします。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "LambdaESMNetworkingAccess",
               "Effect": "Allow",
               "Action": [
                   "ec2:CreateNetworkInterface",
                   "ec2:DescribeNetworkInterfaces",
                   "ec2:DescribeVpcs",
                   "ec2:DeleteNetworkInterface",
                   "ec2:DescribeSubnets",
                   "ec2:DescribeSecurityGroups",
                   "kms:Decrypt"
               ],
               "Resource": "*"
           },
           {
               "Sid": "LambdaDocDBESMAccess",
               "Effect": "Allow",
               "Action": [
                   "rds:DescribeDBClusters",
                   "rds:DescribeDBClusterParameters",
                   "rds:DescribeDBSubnetGroups"
               ],
               "Resource": "*"
           },
           {
               "Sid": "LambdaDocDBESMGetSecretValueAccess",
               "Effect": "Allow",
               "Action": [
                   "secretsmanager:GetSecretValue"
               ],
               "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:DocumentDBSecret"
           }
       ]
   }
   ```

------

1. **[次へ: タグ]**、**[次へ: 確認]** の順に選択します。

1. **[Name]** (名前) に `AWSDocumentDBLambdaPolicy` と入力します。

1. [**ポリシーの作成**] を選択します。

**IAM ロールを作成するには**

1. IAM コンソールの [[ロール] ページ](https://console.aws.amazon.com/iam/home#/roles)を開いて、**[ロールの作成]** を選択します。

1. **[信頼できるエンティティを選択]** には、次のオプションを選択します。
   + **[信頼できるエンティティタイプ]**: AWS サービス
   + **[サービスまたはユースケース]**: Lambda
   + [**次へ**] を選択します。

1. **[アクセス権限の追加]** では、作成したばかりの `AWSDocumentDBLambdaPolicy` ポリシーを選択し、`AWSLambdaBasicExecutionRole` と同様に関数に Amazon CloudWatch Logs への書き込み権限を付与します。

1. [**次へ**] を選択します。

1. **[Role name]** (ロール名) に`AWSDocumentDBLambdaExecutionRole`と入力します。

1. [**ロールの作成**] を選択してください。

## Lambda 関数を作成する
<a name="docdb-create-the-lambda-function"></a>

このチュートリアルは Python 3.14 ランタイムを使用しますが、他のランタイム用のサンプルコードのファイルも用意しています。次のボックスでタブを選択すると、関心のあるランタイムのコードが表示されます。

このコードは Amazon DocumentDB イベント入力を受け取り、そこに含まれるメッセージを処理します。

**Lambda 関数を作成するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. [**関数の作成**] を選択してください。

1. **[一から作成]** を選択します。

1. **[基本的な情報]** で、以下を実行します。

   1. **[関数名]** に `ProcessDocumentDBRecords` と入力します。

   1. **[ランタイム]** には、**[Python 3.14]** を選択します。

   1. **[アーキテクチャ]** で **[x86\$164]** を選択します。

1. **[デフォルトの実行ロールの変更]** タブで、次の操作を行います。

   1. タブを展開し、**[既存のロールを使用する]** を選択します。

   1. 先ほど作成した `AWSDocumentDBLambdaExecutionRole` を選択します。

1. [**関数の作成**] を選択してください。

**関数コードをデプロイするには**

1. 次のボックスで **[Python]** タブを選択し、コードをコピーします。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での Amazon DocumentDB イベントの消費。  

   ```
   using Amazon.Lambda.Core;
   using System.Text.Json;
   using System;
   using System.Collections.Generic;
   using System.Text.Json.Serialization;
   //Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
   [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
   
   namespace LambdaDocDb;
   
   public class Function
   {
       
        /// <summary>
       /// Lambda function entry point to process Amazon DocumentDB events.
       /// </summary>
       /// <param name="event">The Amazon DocumentDB event.</param>
       /// <param name="context">The Lambda context object.</param>
       /// <returns>A string to indicate successful processing.</returns>
       public string FunctionHandler(Event evnt, ILambdaContext context)
       {
           
           foreach (var record in evnt.Events)
           {
               ProcessDocumentDBEvent(record, context);
           }
   
           return "OK";
       }
   
        private void ProcessDocumentDBEvent(DocumentDBEventRecord record, ILambdaContext context)
       {
           
           var eventData = record.Event;
           var operationType = eventData.OperationType;
           var databaseName = eventData.Ns.Db;
           var collectionName = eventData.Ns.Coll;
           var fullDocument = JsonSerializer.Serialize(eventData.FullDocument, new JsonSerializerOptions { WriteIndented = true });
   
           context.Logger.LogLine($"Operation type: {operationType}");
           context.Logger.LogLine($"Database: {databaseName}");
           context.Logger.LogLine($"Collection: {collectionName}");
           context.Logger.LogLine($"Full document:\n{fullDocument}");
       }
   
   
   
       public class Event
       {
           [JsonPropertyName("eventSourceArn")]
           public string EventSourceArn { get; set; }
   
           [JsonPropertyName("events")]
           public List<DocumentDBEventRecord> Events { get; set; }
   
           [JsonPropertyName("eventSource")]
           public string EventSource { get; set; }
       }
   
       public class DocumentDBEventRecord
       {
           [JsonPropertyName("event")]
           public EventData Event { get; set; }
       }
   
       public class EventData
       {
           [JsonPropertyName("_id")]
           public IdData Id { get; set; }
   
           [JsonPropertyName("clusterTime")]
           public ClusterTime ClusterTime { get; set; }
   
           [JsonPropertyName("documentKey")]
           public DocumentKey DocumentKey { get; set; }
   
           [JsonPropertyName("fullDocument")]
           public Dictionary<string, object> FullDocument { get; set; }
   
           [JsonPropertyName("ns")]
           public Namespace Ns { get; set; }
   
           [JsonPropertyName("operationType")]
           public string OperationType { get; set; }
       }
   
       public class IdData
       {
           [JsonPropertyName("_data")]
           public string Data { get; set; }
       }
   
       public class ClusterTime
       {
           [JsonPropertyName("$timestamp")]
           public Timestamp Timestamp { get; set; }
       }
   
       public class Timestamp
       {
           [JsonPropertyName("t")]
           public long T { get; set; }
   
           [JsonPropertyName("i")]
           public int I { get; set; }
       }
   
       public class DocumentKey
       {
           [JsonPropertyName("_id")]
           public Id Id { get; set; }
       }
   
       public class Id
       {
           [JsonPropertyName("$oid")]
           public string Oid { get; set; }
       }
   
       public class Namespace
       {
           [JsonPropertyName("db")]
           public string Db { get; set; }
   
           [JsonPropertyName("coll")]
           public string Coll { get; set; }
       }
   }
   ```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   package main
   
   import (
   	"context"
   	"encoding/json"
   	"fmt"
   
   	"github.com/aws/aws-lambda-go/lambda"
   )
   
   type Event struct {
   	Events []Record `json:"events"`
   }
   
   type Record struct {
   	Event struct {
   		OperationType string `json:"operationType"`
   		NS            struct {
   			DB   string `json:"db"`
   			Coll string `json:"coll"`
   		} `json:"ns"`
   		FullDocument interface{} `json:"fullDocument"`
   	} `json:"event"`
   }
   
   func main() {
   	lambda.Start(handler)
   }
   
   func handler(ctx context.Context, event Event) (string, error) {
   	fmt.Println("Loading function")
   	for _, record := range event.Events {
   		logDocumentDBEvent(record)
   	}
   
   	return "OK", nil
   }
   
   func logDocumentDBEvent(record Record) {
   	fmt.Printf("Operation type: %s\n", record.Event.OperationType)
   	fmt.Printf("db: %s\n", record.Event.NS.DB)
   	fmt.Printf("collection: %s\n", record.Event.NS.Coll)
   	docBytes, _ := json.MarshalIndent(record.Event.FullDocument, "", "  ")
   	fmt.Printf("Full document: %s\n", string(docBytes))
   }
   ```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での Amazon DocumentDB イベントの消費。  

   ```
   import java.util.List;
   import java.util.Map;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   
   public class Example implements RequestHandler<Map<String, Object>, String> {
   
       @SuppressWarnings("unchecked")
       @Override
       public String handleRequest(Map<String, Object> event, Context context) {
           List<Map<String, Object>> events = (List<Map<String, Object>>) event.get("events");
           for (Map<String, Object> record : events) {
               Map<String, Object> eventData = (Map<String, Object>) record.get("event");
               processEventData(eventData);
           }
   
           return "OK";
       }
   
       @SuppressWarnings("unchecked")
       private void processEventData(Map<String, Object> eventData) {
           String operationType = (String) eventData.get("operationType");
           System.out.println("operationType: %s".formatted(operationType));
   
           Map<String, Object> ns = (Map<String, Object>) eventData.get("ns");
   
           String db = (String) ns.get("db");
           System.out.println("db: %s".formatted(db));
           String coll = (String) ns.get("coll");
           System.out.println("coll: %s".formatted(coll));
   
           Map<String, Object> fullDocument = (Map<String, Object>) eventData.get("fullDocument");
           System.out.println("fullDocument: %s".formatted(fullDocument));
       }
   
   }
   ```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での Amazon DocumentDB イベントの消費。  

   ```
   console.log('Loading function');
   exports.handler = async (event, context) => {
       event.events.forEach(record => {
           logDocumentDBEvent(record);
       });
       return 'OK';
   };
   
   const logDocumentDBEvent = (record) => {
       console.log('Operation type: ' + record.event.operationType);
       console.log('db: ' + record.event.ns.db);
       console.log('collection: ' + record.event.ns.coll);
       console.log('Full document:', JSON.stringify(record.event.fullDocument, null, 2));
   };
   ```
TypeScript を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   import { DocumentDBEventRecord, DocumentDBEventSubscriptionContext } from 'aws-lambda';
   
   console.log('Loading function');
   
   export const handler = async (
     event: DocumentDBEventSubscriptionContext,
     context: any
   ): Promise<string> => {
     event.events.forEach((record: DocumentDBEventRecord) => {
       logDocumentDBEvent(record);
     });
     return 'OK';
   };
   
   const logDocumentDBEvent = (record: DocumentDBEventRecord): void => {
     console.log('Operation type: ' + record.event.operationType);
     console.log('db: ' + record.event.ns.db);
     console.log('collection: ' + record.event.ns.coll);
     console.log('Full document:', JSON.stringify(record.event.fullDocument, null, 2));
   };
   ```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   <?php
   
   require __DIR__.'/vendor/autoload.php';
   
   use Bref\Context\Context;
   use Bref\Event\Handler;
   
   class DocumentDBEventHandler implements Handler
   {
       public function handle($event, Context $context): string
       {
   
           $events = $event['events'] ?? [];
           foreach ($events as $record) {
               $this->logDocumentDBEvent($record['event']);
           }
           return 'OK';
       }
   
       private function logDocumentDBEvent($event): void
       {
           // Extract information from the event record
   
           $operationType = $event['operationType'] ?? 'Unknown';
           $db = $event['ns']['db'] ?? 'Unknown';
           $collection = $event['ns']['coll'] ?? 'Unknown';
           $fullDocument = $event['fullDocument'] ?? [];
   
           // Log the event details
   
           echo "Operation type: $operationType\n";
           echo "Database: $db\n";
           echo "Collection: $collection\n";
           echo "Full document: " . json_encode($fullDocument, JSON_PRETTY_PRINT) . "\n";
       }
   }
   return new DocumentDBEventHandler();
   ```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   import json
   
   def lambda_handler(event, context):
       for record in event.get('events', []):
           log_document_db_event(record)
       return 'OK'
   
   def log_document_db_event(record):
       event_data = record.get('event', {})
       operation_type = event_data.get('operationType', 'Unknown')
       db = event_data.get('ns', {}).get('db', 'Unknown')
       collection = event_data.get('ns', {}).get('coll', 'Unknown')
       full_document = event_data.get('fullDocument', {})
   
       print(f"Operation type: {operation_type}")
       print(f"db: {db}")
       print(f"collection: {collection}")
       print("Full document:", json.dumps(full_document, indent=2))
   ```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   require 'json'
   
   def lambda_handler(event:, context:)
     event['events'].each do |record|
       log_document_db_event(record)
     end
     'OK'
   end
   
   def log_document_db_event(record)
     event_data = record['event'] || {}
     operation_type = event_data['operationType'] || 'Unknown'
     db = event_data.dig('ns', 'db') || 'Unknown'
     collection = event_data.dig('ns', 'coll') || 'Unknown'
     full_document = event_data['fullDocument'] || {}
   
     puts "Operation type: #{operation_type}"
     puts "db: #{db}"
     puts "collection: #{collection}"
     puts "Full document: #{JSON.pretty_generate(full_document)}"
   end
   ```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用して Lambda で Amazon DocumentDB イベントの消費。  

   ```
   use lambda_runtime::{service_fn, tracing, Error, LambdaEvent};
   use aws_lambda_events::{
       event::documentdb::{DocumentDbEvent, DocumentDbInnerEvent},
      };
   
   
   // Built with the following dependencies:
   //lambda_runtime = "0.11.1"
   //serde_json = "1.0"
   //tokio = { version = "1", features = ["macros"] }
   //tracing = { version = "0.1", features = ["log"] }
   //tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }
   //aws_lambda_events = "0.15.0"
   
   async fn function_handler(event: LambdaEvent<DocumentDbEvent>) ->Result<(), Error> {
       
       tracing::info!("Event Source ARN: {:?}", event.payload.event_source_arn);
       tracing::info!("Event Source: {:?}", event.payload.event_source);
     
       let records = &event.payload.events;
      
       if records.is_empty() {
           tracing::info!("No records found. Exiting.");
           return Ok(());
       }
   
       for record in records{
           log_document_db_event(record);
       }
   
       tracing::info!("Document db records processed");
   
       // Prepare the response
       Ok(())
   
   }
   
   fn log_document_db_event(record: &DocumentDbInnerEvent)-> Result<(), Error>{
       tracing::info!("Change Event: {:?}", record.event);
       
       Ok(())
   
   }
   
   #[tokio::main]
   async fn main() -> Result<(), Error> {
       tracing_subscriber::fmt()
       .with_max_level(tracing::Level::INFO)
       .with_target(false)
       .without_time()
       .init();
   
       let func = service_fn(function_handler);
       lambda_runtime::run(func).await?;
       Ok(())
       
   }
   ```

------

1. Lambda コンソールの **[コードソース]** ペインで、コードをコードエディタに貼り付け、Lambda が作成したコードを置き換えます。

1. **[DEPLOY]** セクションで、**[デプロイ]** を選択して関数のコードを更新します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

## Lambda イベントソースマッピングを作成します。
<a name="docdb-create-the-lambda-event-source-mapping"></a>

 Amazon DocumentDB 変更ストリームを Lambda 関数と関連付けるイベントソースマッピングを作成します。このイベントソースマッピングを作成すると、AWS Lambda はストリームのポーリングをすぐに開始します。

**イベントソースマッピングを作成するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 先ほど作成した `ProcessDocumentDBRecords` 関数を選択します。

1. **[設定]** タブを選択し、左側のメニューで **[トリガー]** を選択します。

1. **[トリガーを追加]** を選択します。

1. **[トリガー設定]** で、**[Amazon DocumentDB]** をソースとして選択します。

1. イベントソースマッピングには、次の設定制限があります。
   + **[Amazon DocumentDB クラスター]**: 先ほど作成したクラスターを選択します。
   + **[データベース名]**: docdbdemo
   + **[コレクション名]**: 製品
   + **[バッチサイズ]**: 1
   + **[開始位置]**: 最新
   + **[認証]**: BASIC\$1AUTH
   + **[Secrets Manager キー]**: Amazon DocumentDB クラスターのシークレットを選択します。`rds!cluster-12345678-a6f0-52c0-b290-db4aga89274f` のような名前になります。
   + **[バッチウィンドウ]**: 1
   + **[フルドキュメント設定]**: UpdateLookup

1. **[Add]** (追加) を選択します。イベントソースマッピングの作成には数分かかる場合があります。

## 関数をテストする
<a name="docdb-test-insert"></a>

イベントソースマッピングが **[有効]** 状態になるまで待ちます。これには数分間かかる場合があります。次に、データベースレコードを挿入、更新、削除して、エンドツーエンドのセットアップをテストします。開始する前に:

1. CloudShell 環境で [Amazon DocumentDB クラスターに再接続](#docdb-connect-to-cluster)します。

1. 次のコマンドを実行し、`docdbdemo` データベースを使用できているのを確認します。

   ```
   use docdbdemo
   ```

### レコードを挿入する
<a name="docdb-test-insert"></a>

`docdbdemo` データベースの `products` コレクションにレコードを挿入します。

```
db.products.insertOne({"name":"Pencil", "price": 1.00})
```

[CloudWatch Logs をチェック](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)して、関数がこのイベントを正常に処理したことを確認します。次のようなログエントリが表示されます。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/documentdb-insert-log.png)


### レコードの更新
<a name="docdb-test-update"></a>

次のコマンドを使用して挿入したレコードを更新します。

```
db.products.updateOne(
    { "name": "Pencil" },
    { $set: { "price": 0.50 }}
)
```

[CloudWatch Logs をチェック](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)して、関数がこのイベントを正常に処理したことを確認します。次のようなログエントリが表示されます。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/documentdb-update-log.png)


### レコードを削除する
<a name="docdb-test-delete"></a>

次のコマンドを使用して更新したレコードを削除します。

```
db.products.deleteOne( { "name": "Pencil" } )
```

[CloudWatch Logs をチェック](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)して、関数がこのイベントを正常に処理したことを確認します。次のようなログエントリが表示されます。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/documentdb-delete-log.png)


## トラブルシューティング
<a name="docdb-lambda-troubleshooting"></a>

関数の CloudWatch ログにデータベースイベントが表示されない場合、次の内容を確認してください。
+ Lambda イベントソースマッピング (トリガーとも呼ばれる) が **[有効]** 状態になっていることを確認します。イベントソースマッピングは作成に数分かかる場合があります。
+ イベントソースマッピングが **[有効]** になっても CloudWatch にデータベースイベントが表示されない場合、次の内容を実行してください。
  + イベントソースマッピングの **[データベース名]** が `docdbdemo` に設定されていることを確認します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/documentdb-trigger.png)
  + イベントソースマッピングの **[最終処理結果]** フィールドに、次のメッセージがあるかどうか確認します。「問題: 接続エラー。VPC は Lambda および STS との接続に加え、認証が必要な場合は Secrets Manager にも接続できる必要があります」 このエラーが表示された場合、[Lambda および Secrets Manager VPC インターフェイスエンドポイントが作成されているか](#docdb-create-interface-vpc-endpoints)、またエンドポイントは Amazon DocumentDB クラスターが使用するのと同じ VPC およびサブネットを使用しているかを確認してください。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/documentdb-lastprocessingresult.png)

## リソースのクリーンアップ
<a name="docdb-cleanup"></a>

 このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**VPC エンドポイントを削除するには**

1. [[VPC] コンソール](https://console.aws.amazon.com/vpc/home#)を開きます。左側のメニューの **[仮想プライベートクラウド]** で、**[エンドポイント]** を選択します。

1. 作成したエンドポイントを選択します。

1. **[アクション]**、**[VPC エンドポイントを削除]** の順に選択します。

1. テキスト入力フィールドに **delete** を入力します。

1. **[削除]** を選択します。

**Amazon DocumentDB クラスターを削除するには**

1. [Amazon DocumentDB コンソール](https://console.aws.amazon.com/docdb/home#)を開きます。

1. 本チュートリアル用に作成した Amazon DocumentDB クラスターを選択し、削除保護を無効にします。

1. メインの **[クラスター]** ページで、作成した Amazon DocumentDB クラスターを再度選択します。

1. **[アクション]**、**[削除]** の順に選択します。

1. **[最終クラスタースナップショットの作成]** で **[いいえ]** を選択します。

1. テキスト入力フィールドに **delete** を入力します。

1. **[削除]** を選択します。

**シークレットを Secrets Manager で削除するには**

1. [Secrets Manager コンソール](https://console.aws.amazon.com/secretsmanager/home#)を開きます。

1. このチュートリアルで作成したシークレットを選択します。

1. **[アクション]**、**[シークレットの削除]** を選択します。

1. **[Schedule deletion]** (削除をスケジュールする) を選択します。

# Amazon DynamoDB で AWS Lambda を使用する
<a name="with-ddb"></a>

**注記**  
Lambda 関数以外のターゲットにデータを送信したい、または送信する前にデータをエンリッチしたいという場合は、「[Amazon EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html)」を参照してください。

AWS Lambda 関数を使用して、[Amazon DynamoDB ストリーム](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html)のレコードを処理します。DynamoDB Streams では、Lambda 関数を使用して、DynamoDB テーブルが更新されるたびに追加の作業を実行することができます。

DynamoDB ストリームを処理するときは、部分的なバッチレスポンスロジックを実装して、バッチ内の一部のレコードで障害が発生した場合に正常に処理されたレコードが再試行されないようにする必要があります。Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)は、Python、TypeScript、.NET、Java で利用でき、部分的なバッチレスポンスロジックを自動的に処理して開発時間を短縮し、信頼性を向上させることで、この実装を簡素化します。

**Topics**
+ [ポーリングストリームとバッチストリーム](#dynamodb-polling-and-batching)
+ [ポーリングとストリームの開始位置](#dyanmo-db-stream-poll)
+ [DynamoDB Streams でのシャードの同時読み込み](#events-dynamodb-simultaneous-readers)
+ [イベントの例](#events-sample-dynamodb)
+ [Lambda で DynamoDB レコードを処理する](services-dynamodb-eventsourcemapping.md)
+ [DynamoDB と Lambda を使用した部分的なバッチレスポンスの設定](services-ddb-batchfailurereporting.md)
+ [Lambda で DynamoDB イベントソースの破棄されたレコードを保持する](services-dynamodb-errors.md)
+ [Lambda での ステートフル DynamoDB ストリーム処理の実装](services-ddb-windows.md)
+ [Amazon DynamoDB イベントソースマッピング用の Lambda パラメータ](services-ddb-params.md)
+ [DynamoDB イベントソースでのイベントフィルタリングの使用](with-ddb-filtering.md)
+ [チュートリアル: Amazon DynamoDB Streams で AWS Lambda を使用する](with-ddb-example.md)

## ポーリングストリームとバッチストリーム
<a name="dynamodb-polling-and-batching"></a>

Lambda は、レコードの DynamoDB ストリームにあるシャードを 1 秒あたり 4 回の基本レートでポーリングします。レコードが利用可能になると、Lambda は関数を呼び出し、結果を待機します。処理が成功すると、Lambda は、レコードをさらに受け取るまでポーリングを再開します。

デフォルトで、Lambda はレコードが使用可能になると同時に関数を呼び出します。Lambda がイベントソースから読み取るバッチにレコードが 1 つしかない場合、Lambda は関数に 1 つのレコードしか送信しません。少数のレコードで関数を呼び出さないようにするには、*バッチ処理ウィンドウ*を設定することで、最大 5 分間レコードをバッファリングするようにイベントソースに指示できます。関数を呼び出す前に、Lambda は、完全なバッチを収集する、バッチ処理ウィンドウの期限が切れる、またはバッチが 6 MB のペイロード制限に到達するまでイベントソースからのレコードの読み取りを継続します。詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

Lambda は、設定された[拡張機能](lambda-extensions.md)の完了を待たずに、次のバッチを処理のために送信します。つまり、Lambda がレコードの次のバッチを処理する間も拡張機能を実行し続けることができます。アカウントの[同時実行](lambda-concurrency.md)設定または制限に違反すると、スロットリングの問題が発生する可能性があります。これが潜在的な問題であるかどうかを検出するには、関数を監視し、イベントソースマッピングで予想よりも高い[同時実行メトリクス](monitoring-concurrency.md#general-concurrency-metrics)が表示されているかどうかを確認します。呼び出しの間隔が短いため、Lambda はシャードの数よりも高い同時実行使用量を一時的に報告する場合があります。これは、拡張機能のない Lambda 関数にも当てはまります。

DynamoDB ストリームの 1 つのシャードを複数の Lambda 呼び出しで同時に処理するには、[ParallelizationFactor](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-ParallelizationFactor) 設定を行います。Lambda がシャードからポーリングする同時バッチの数は、1 (デフォルト)～10 の並列化係数で指定できます。例えば、`ParallelizationFactor` を 2 に設定すると、最大 200 個の Lambda 呼び出しを同時に実行して、DynamoDB ストリームのシャードを 100 個処理できます (ただし、`ConcurrentExecutions` メトリクスに異なる値が表示される場合があります)。これにより、データボリュームが揮発性で [IteratorAge](monitoring-metrics-types.md#performance-metrics) が高い場合に、処理のスループットをスケールアップすることができます。シャードごとの同時実行バッチの数を増やしても、Lambda はアイテム (パーティションおよびソートキー) レベルで順序立った処理を確実に行います。

## ポーリングとストリームの開始位置
<a name="dyanmo-db-stream-poll"></a>

イベントソースマッピングの作成時および更新時のストリームのポーリングは、最終的に一貫性があることに注意してください。
+ イベントソースマッピングの作成時、ストリームからのイベントのポーリングが開始されるまでに数分かかる場合があります。
+ イベントソースマッピングの更新時、ストリームからのイベントのポーリングが停止および再開されるまでに数分かかる場合があります。

つまり、`LATEST` をストリームの開始位置として指定すると、イベントソースマッピングの作成または更新中にイベントを見逃す可能性があります。イベントを見逃さないようにするには、ストリームの開始位置を `TRIM_HORIZON` として指定します。

## DynamoDB Streams でのシャードの同時読み込み
<a name="events-dynamodb-simultaneous-readers"></a>

単一リージョンのテーブルがグローバルテーブルでない場合、同じ DynamoDB Streams のシャードから、同時に 2 つまでの Lambda 関数を読み込むように設計できます。この制限を超えると、リクエストのスロットリングが発生する場合があります。グローバルテーブルでは、リクエストのスロットリングを回避するために、同時関数の数を 1 に制限することをお勧めします。

## イベントの例
<a name="events-sample-dynamodb"></a>

**Example**  

```
{
  "Records": [
    {
      "eventID": "1",
      "eventVersion": "1.0",
      "dynamodb": {
        "Keys": {
          "Id": {
            "N": "101"
          }
        },
        "NewImage": {
          "Message": {
            "S": "New item!"
          },
          "Id": {
            "N": "101"
          }
        },
        "StreamViewType": "NEW_AND_OLD_IMAGES",
        "SequenceNumber": "111",
        "SizeBytes": 26
      },
      "awsRegion": "us-west-2",
      "eventName": "INSERT",
      "eventSourceARN": "arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2024-06-10T19:26:16.525",
      "eventSource": "aws:dynamodb"
    },
    {
      "eventID": "2",
      "eventVersion": "1.0",
      "dynamodb": {
        "OldImage": {
          "Message": {
            "S": "New item!"
          },
          "Id": {
            "N": "101"
          }
        },
        "SequenceNumber": "222",
        "Keys": {
          "Id": {
            "N": "101"
          }
        },
        "SizeBytes": 59,
        "NewImage": {
          "Message": {
            "S": "This item has changed"
          },
          "Id": {
            "N": "101"
          }
        },
        "StreamViewType": "NEW_AND_OLD_IMAGES"
      },
      "awsRegion": "us-west-2",
      "eventName": "MODIFY",
      "eventSourceARN": "arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2024-06-10T19:26:16.525",
      "eventSource": "aws:dynamodb"
    }
  ]}
```

# Lambda で DynamoDB レコードを処理する
<a name="services-dynamodb-eventsourcemapping"></a>

イベントソースマッピングを作成し、ストリームから Lambda 関数にレコードを送信するように Lambda に通知します。複数のイベントソースマッピングを作成することで、複数の Lambda 関数で同じデータを処理したり、1 つの関数で複数のストリームの項目を処理したりできます。

別の AWS アカウント のストリームからのレコードを処理するようにイベント ソース マッピングを構成できます。詳細については[クロスアカウントのイベントソースマッピングの作成](#services-dynamodb-eventsourcemapping-cross-account)を参照してください。

DynamoDB ストリームから読み取るように関数を設定するには、「[AWSLambdaDynamoDBExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaDynamoDBExecutionRole.html)」 AWS 管理ポリシーを実行ロールにアタッチし、**[DynamoDB]** トリガーを作成します。

**アクセス許可を追加してトリガーを作成するには**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 関数の名前を選択します。

1. **[設定]** タブを開き、次に **[アクセス権限]** をクリックします。

1. **[実行ロール]** で、実行ロールのリンクを選択します。このリンクを選択すると、IAM コンソールでロールが開きます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/execution-role.png)

1. **[アクセス許可を追加]**、**[ポリシーをアタッチ]** の順に選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/attach-policies.png)

1. [検索] フィールドに `AWSLambdaDynamoDBExecutionRole` を入力します。実行ロールにポリシーを追加 関数が DynamoDB ストリームから読み取るために必要な許可を含む AWS 管理ポリシーです。このポリシーの詳細については、「*AWS 管理ポリシーリファレンス*」の「[AWSLambdaDynamoDBExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaDynamoDBExecutionRole.html)」を参照してください。

1. Lambda コンソールの関数に戻ります。**[関数の概要]** で **[トリガーを追加]** をクリックします。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/add-trigger.png)

1. トリガーのタイプを選択します。

1. 必須のオプションを設定し、[**Add**] (追加) を選択します。

Lambda は、DynamoDB イベントソースの次のオプションをサポートしています。

**イベントソースオプション**
+ **DynamoDB テーブル** - レコードの読み取り元の DynamoDB テーブル。
+ **バッチサイズ** - 各バッチで関数に送信されるレコードの数。最大 10,000。Lambda は、イベントの合計サイズが同期呼び出しの[ペイロード上限](gettingstarted-limits.md) (6 MB) を超えない限り、バッチ内のすべてのレコードを単一の呼び出しで関数に渡します。
+ **バッチウィンドウ** - 関数を呼び出す前にレコードを収集する最大時間（秒数）を指定します。
+ **開始位置** - 新規レコードのみ、または既存のすべてのレコードを処理します。
  + **最新** - ストリームに追加された新しいレコードを処理します。
  + **水平トリム** - ストリーム内のすべてのレコードを処理します。

  既存のレコードを処理した後、関数に戻り、新しいレコードの処理が続行されます。
+ **[障害発生時の宛先]** — 処理できないレコードの標準 SQS キューまたは標準 SNS トピックです。Lambda は、古すぎる、または再試行回数の上限に達したレコードのバッチを廃棄すると、バッチに関する詳細をキューまたはトピックに送信します。
+ **再試行回数** - 関数がエラーを返したときに Lambda が再試行する回数の上限です。これは、バッチが関数に到達しなかったサービスエラーやスロットルには適用されません。
+ **レコードの最大有効期間** — Lambda が関数に送信するレコードの最大経過時間。
+ **エラー発生時のバッチ分割** — 関数がエラーを返した場合、再試行する前にバッチを 2 つに分割します。元のバッチサイズ設定は変更されません。
+ **シャードごとの同時バッチ** — 同じシャードからの複数のバッチを同時に処理します。
+ **有効** - イベントソースマッピングを有効にするには、true に設定します。レコードの処理を停止するには、false に設定します。Lambda は、処理された最新のレコードを追跡し、マッピングが再度有効になるとその時点から処理を再開します。

**注記**  
DynamoDB トリガーの一部として Lambda によって呼び出される GetRecords API コールに対しては、料金は発生しません。

後でイベントソース設定を管理するには、デザイナーでトリガーを選択します。

## クロスアカウントのイベントソースマッピングの作成
<a name="services-dynamodb-eventsourcemapping-cross-account"></a>

Amazon DynamoDB は、[リソースベースのポリシー](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/access-control-resource-based.html)をサポートするようになりました。この機能を使用すると、別のアカウントの Lambda 関数を使用して、DynamoDB ストリームからのデータを 1 つの AWS アカウント で処理できます。

別の AWS アカウント の DynamoDB ストリームを使用して Lambda 関数のイベントソースマッピングを作成するには、リソースベースのポリシーを使用してストリームを設定し、Lambda 関数にレコードを読み取るアクセス許可を付与する必要があります。クロスアカウントアクセスを許可するようにストリームを設定する方法については、「*Amazon DynamoDB デベロッパーガイド*」の「[クロスアカウントの Lambda 関数を使用したアクセスを共有する](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-cross-account-access.html#rbac-analyze-cross-account-lambda-access)」を参照してください。

Lambda 関数に必要なアクセス許可を付与するリソースベースのポリシーでストリームを設定したら、クロスアカウントストリーム ARN を使用してイベントソースマッピングを作成します。ストリーム ARN は、クロスアカウント DynamoDB コンソールのテーブルの **[エクスポートおよびストリーム]** タブにあります。

Lambda コンソールを使用する場合は、ストリーム ARN をイベントソースマッピング作成ページの DynamoDB テーブル入力フィールドに直接貼り付けます。

 **注:** クロスリージョントリガーはサポートされていません。

# DynamoDB と Lambda を使用した部分的なバッチレスポンスの設定
<a name="services-ddb-batchfailurereporting"></a>

イベントソースからストリーミングデータを使用および処理する場合、デフォルトでは、バッチが完全に成功した場合にのみ、バッチの最大シーケンス番号に Lambda チェックポイントが設定されます。Lambda は、他のすべての結果を完全な失敗として扱い、再試行の上限までバッチの処理を再試行します。ストリームからのバッチの処理中に部分的な成功を許可するには、`ReportBatchItemFailures`をオンにします 。部分的な成功を許可すると、レコードの再試行回数を減らすことができますが、成功したレコードの再試行の可能性を完全に妨げるわけではありません。

`ReportBatchItemFailures` をオンにするには、列挙値 **ReportBatchItemFailures** を [FunctionResponseTypes](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-FunctionResponseTypes) リストに含めます。このリストは、関数で有効になっているレスポンスタイプを示します。このリストは、イベントソースマッピングを[作成](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)または[更新](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)するときに設定できます。

**注記**  
関数コードが部分的なバッチ処理失敗レスポンスを返しても、イベントソースマッピングに対して `ReportBatchItemFailures` 機能が明示的に有効化されていなければ、Lambda はこれらのレスポンスを処理しません。

## レポートの構文
<a name="streams-batchfailurereporting-syntax"></a>

バッチアイテムの失敗に関するレポートを設定する場合、`StreamsEventResponse` クラスはバッチアイテムの失敗のリストとともに返されます。`StreamsEventResponse`オブジェクトを使用して、バッチ処理で最初に失敗したレコードのシーケンス番号を返すことができます。また、正しいレスポンスシンタックスを使用して、独自のカスタムクラスを作成することもできます。次の JSON 構造体は、必要な応答構文を示しています。

```
{ 
  "batchItemFailures": [ 
        {
            "itemIdentifier": "<SequenceNumber>"
        }
    ]
}
```

**注記**  
`batchItemFailures` 配列に複数の項目が含まれている場合、Lambda はシーケンス番号が最も小さいレコードをチェックポイントとして使用します。その後、Lambda はそのチェックポイントからすべてのレコードを再試行します。

## 成功条件と失敗の条件
<a name="streams-batchfailurereporting-conditions"></a>

次のいずれかを返すと、Lambda はバッチを完全な成功として処理します:
+ 空の`batchItemFailure`リストです。
+ null の `batchItemFailure` リスト
+ 空の `EventResponse`
+ ヌル `EventResponse`

次のいずれかを返すと、Lambda はバッチを完全な失敗として処理します:
+ 空の文字列`itemIdentifier`
+ ヌル `itemIdentifier`
+ `itemIdentifier`間違えているキー名

Lambda は、再試行戦略に基づいて失敗を再試行します。

## バッチを２分割します
<a name="streams-batchfailurereporting-bisect"></a>

呼び出しが失敗し、`BisectBatchOnFunctionError` オンになっている場合、バッチは`ReportBatchItemFailures`設定に関係なく２分割されます。

部分的なバッチ成功レスポンスを受信し、`BisectBatchOnFunctionError` と `ReportBatchItemFailures` の両方がオンになっている場合、バッチは返されたシーケンス番号で 2 分割され、Lambda は残りのレコードのみを再試行します。

部分的なバッチレスポンスロジックの実装を簡素化するには、Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)を使用することを検討してください。これらの複雑さが自動的に処理されます。

バッチで失敗したメッセージ ID のリストを返す関数コードの例を次に示します。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System.Text.Json;
using System.Text;
using Amazon.Lambda.Core;
using Amazon.Lambda.DynamoDBEvents;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace AWSLambda_DDB;

public class Function
{
    public StreamsEventResponse FunctionHandler(DynamoDBEvent dynamoEvent, ILambdaContext context)

    {
        context.Logger.LogInformation($"Beginning to process {dynamoEvent.Records.Count} records...");
        List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new List<StreamsEventResponse.BatchItemFailure>();
        StreamsEventResponse streamsEventResponse = new StreamsEventResponse();

        foreach (var record in dynamoEvent.Records)
        {
            try
            {
                var sequenceNumber = record.Dynamodb.SequenceNumber;
                context.Logger.LogInformation(sequenceNumber);
            }
            catch (Exception ex)
            {
                context.Logger.LogError(ex.Message);
                batchItemFailures.Add(new StreamsEventResponse.BatchItemFailure() { ItemIdentifier = record.Dynamodb.SequenceNumber });
            }
        }

        if (batchItemFailures.Count > 0)
        {
            streamsEventResponse.BatchItemFailures = batchItemFailures;
        }

        context.Logger.LogInformation("Stream processing complete.");
        return streamsEventResponse;
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main

import (
	"context"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type BatchItemFailure struct {
	ItemIdentifier string `json:"ItemIdentifier"`
}

type BatchResult struct {
	BatchItemFailures []BatchItemFailure `json:"BatchItemFailures"`
}

func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*BatchResult, error) {
	var batchItemFailures []BatchItemFailure
	curRecordSequenceNumber := ""

	for _, record := range event.Records {
		// Process your record
		curRecordSequenceNumber = record.Change.SequenceNumber
	}

	if curRecordSequenceNumber != "" {
		batchItemFailures = append(batchItemFailures, BatchItemFailure{ItemIdentifier: curRecordSequenceNumber})
	}
	
	batchResult := BatchResult{
		BatchItemFailures: batchItemFailures,
	}

	return &batchResult, nil
}

func main() {
	lambda.Start(HandleRequest)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での DynamoDB のバッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord;

import java.util.ArrayList;
import java.util.List;

public class ProcessDynamodbRecords implements RequestHandler<DynamodbEvent, StreamsEventResponse> {

    @Override
    public StreamsEventResponse handleRequest(DynamodbEvent input, Context context) {

        List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>();
        String curRecordSequenceNumber = "";

        for (DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord : input.getRecords()) {
          try {
                //Process your record
                StreamRecord dynamodbRecord = dynamodbStreamRecord.getDynamodb();
                curRecordSequenceNumber = dynamodbRecord.getSequenceNumber();
                
            } catch (Exception e) {
                /* Since we are working with streams, we can return the failed item immediately.
                   Lambda will immediately begin to retry processing from this failed item onwards. */
                batchItemFailures.add(new StreamsEventResponse.BatchItemFailure(curRecordSequenceNumber));
                return new StreamsEventResponse(batchItemFailures);
            }
        }
       
       return new StreamsEventResponse();   
    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
export const handler = async (event) => {
  const records = event.Records;
  let curRecordSequenceNumber = "";

  for (const record of records) {
    try {
      // Process your record
      curRecordSequenceNumber = record.dynamodb.SequenceNumber;
    } catch (e) {
      // Return failed record's sequence number
      return { batchItemFailures: [{ itemIdentifier: curRecordSequenceNumber }] };
    }
  }

  return { batchItemFailures: [] };
};
```
TypeScript を使用して Lambda で DynamoDB のバッチアイテム失敗をレポートする。  

```
import {
  DynamoDBBatchResponse,
  DynamoDBBatchItemFailure,
  DynamoDBStreamEvent,
} from "aws-lambda";

export const handler = async (
  event: DynamoDBStreamEvent
): Promise<DynamoDBBatchResponse> => {
  const batchItemFailures: DynamoDBBatchItemFailure[] = [];
  let curRecordSequenceNumber;

  for (const record of event.Records) {
    curRecordSequenceNumber = record.dynamodb?.SequenceNumber;

    if (curRecordSequenceNumber) {
      batchItemFailures.push({
        itemIdentifier: curRecordSequenceNumber,
      });
    }
  }

  return { batchItemFailures: batchItemFailures };
};
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での DynamoDB バッチ項目失敗のレポート。  

```
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\DynamoDb\DynamoDbEvent;
use Bref\Event\Handler as StdHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler implements StdHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws JsonException
     * @throws \Bref\Event\InvalidLambdaEvent
     */
    public function handle(mixed $event, Context $context): array
    {
        $dynamoDbEvent = new DynamoDbEvent($event);
        $this->logger->info("Processing records");

        $records = $dynamoDbEvent->getRecords();
        $failedRecords = [];
        foreach ($records as $record) {
            try {
                $data = $record->getData();
                $this->logger->info(json_encode($data));
                // TODO: Do interesting work based on the new data
            } catch (Exception $e) {
                $this->logger->error($e->getMessage());
                // failed processing the record
                $failedRecords[] = $record->getSequenceNumber();
            }
        }
        $totalRecords = count($records);
        $this->logger->info("Successfully processed $totalRecords records");

        // change format for the response
        $failures = array_map(
            fn(string $sequenceNumber) => ['itemIdentifier' => $sequenceNumber],
            $failedRecords
        );

        return [
            'batchItemFailures' => $failures
        ];
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def handler(event, context):
    records = event.get("Records")
    curRecordSequenceNumber = ""
    
    for record in records:
        try:
            # Process your record
            curRecordSequenceNumber = record["dynamodb"]["SequenceNumber"]
        except Exception as e:
            # Return failed record's sequence number
            return {"batchItemFailures":[{"itemIdentifier": curRecordSequenceNumber}]}

    return {"batchItemFailures":[]}
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
def lambda_handler(event:, context:)
    records = event["Records"]
    cur_record_sequence_number = ""
  
    records.each do |record|
      begin
        # Process your record
        cur_record_sequence_number = record["dynamodb"]["SequenceNumber"]
      rescue StandardError => e
        # Return failed record's sequence number
        return {"batchItemFailures" => [{"itemIdentifier" => cur_record_sequence_number}]}
      end
    end
  
    {"batchItemFailures" => []}
  end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用して Lambda で DynamoDB のバッチアイテム失敗のレポート。  

```
use aws_lambda_events::{
    event::dynamodb::{Event, EventRecord, StreamRecord},
    streams::{DynamoDbBatchItemFailure, DynamoDbEventResponse},
};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

/// Process the stream record
fn process_record(record: &EventRecord) -> Result<(), Error> {
    let stream_record: &StreamRecord = &record.change;

    // process your stream record here...
    tracing::info!("Data: {:?}", stream_record);

    Ok(())
}

/// Main Lambda handler here...
async fn function_handler(event: LambdaEvent<Event>) -> Result<DynamoDbEventResponse, Error> {
    let mut response = DynamoDbEventResponse {
        batch_item_failures: vec![],
    };

    let records = &event.payload.records;

    if records.is_empty() {
        tracing::info!("No records found. Exiting.");
        return Ok(response);
    }

    for record in records {
        tracing::info!("EventId: {}", record.event_id);

        // Couldn't find a sequence number
        if record.change.sequence_number.is_none() {
            response.batch_item_failures.push(DynamoDbBatchItemFailure {
                item_identifier: Some("".to_string()),
            });
            return Ok(response);
        }

        // Process your record here...
        if process_record(record).is_err() {
            response.batch_item_failures.push(DynamoDbBatchItemFailure {
                item_identifier: record.change.sequence_number.clone(),
            });
            /* Since we are working with streams, we can return the failed item immediately.
            Lambda will immediately begin to retry processing from this failed item onwards. */
            return Ok(response);
        }
    }

    tracing::info!("Successfully processed {} record(s)", records.len());

    Ok(response)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

## Powertools for AWS Lambda バッチプロセッサを使用する
<a name="services-ddb-batchfailurereporting-powertools"></a>

Powertools for AWS Lambda のバッチプロセッサユーティリティは、部分的なバッチレスポンスロジックを自動的に処理するため、バッチ障害レポートの実装の複雑さが軽減されます。バッチプロセッサを使用した例を次に示します。

**Python**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した DynamoDB ストリームレコードの処理。  

```
import json
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes import DynamoDBStreamEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

processor = BatchProcessor(event_type=EventType.DynamoDBStreams)
logger = Logger()

def record_handler(record):
    logger.info(record)
    # Your business logic here
    # Raise an exception to mark this record as failed
    
def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event, 
        record_handler=record_handler, 
        processor=processor,
        context=context
    )
```

**TypeScript**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.aws.amazon.com/powertools/typescript/latest/features/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した DynamoDB ストリームレコードの処理。  

```
import { BatchProcessor, EventType, processPartialResponse } from '@aws-lambda-powertools/batch';
import { Logger } from '@aws-lambda-powertools/logger';
import type { DynamoDBStreamEvent, Context } from 'aws-lambda';

const processor = new BatchProcessor(EventType.DynamoDBStreams);
const logger = new Logger();

const recordHandler = async (record: any): Promise<void> => {
    logger.info('Processing record', { record });
    // Your business logic here
    // Throw an error to mark this record as failed
};

export const handler = async (event: DynamoDBStreamEvent, context: Context) => {
    return processPartialResponse(event, recordHandler, processor, {
        context,
    });
};
```

**Java**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.powertools.aws.dev/lambda/java/latest/utilities/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した DynamoDB ストリームレコードの処理。  

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse;
import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder;
import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler;

public class DynamoDBStreamBatchHandler implements RequestHandler<DynamodbEvent, StreamsEventResponse> {

    private final BatchMessageHandler<DynamodbEvent, StreamsEventResponse> handler;

    public DynamoDBStreamBatchHandler() {
        handler = new BatchMessageHandlerBuilder()
                .withDynamoDbBatchHandler()
                .buildWithRawMessageHandler(this::processMessage);
    }

    @Override
    public StreamsEventResponse handleRequest(DynamodbEvent ddbEvent, Context context) {
        return handler.processBatch(ddbEvent, context);
    }

    private void processMessage(DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord, Context context) {
        // Process the change record
    }
}
```

**.NET**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.aws.amazon.com/powertools/dotnet/utilities/batch-processing/)を参照してください。
AWS Lambda バッチプロセッサを使用した DynamoDB ストリームレコードの処理。  

```
using System;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.DynamoDBEvents;
using Amazon.Lambda.Serialization.SystemTextJson;
using AWS.Lambda.Powertools.BatchProcessing;

[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]

namespace HelloWorld;

public class Customer
{
    public string? CustomerId { get; set; }
    public string? Name { get; set; }
    public string? Email { get; set; }
    public DateTime CreatedAt { get; set; }
}

internal class TypedDynamoDbRecordHandler : ITypedRecordHandler<Customer> 
{
    public async Task<RecordHandlerResult> HandleAsync(Customer customer, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(customer.Email)) 
        {
            throw new ArgumentException("Customer email is required");
        }

        return await Task.FromResult(RecordHandlerResult.None); 
    }
}

public class Function
{
    [BatchProcessor(TypedRecordHandler = typeof(TypedDynamoDbRecordHandler))]
    public BatchItemFailuresResponse HandlerUsingTypedAttribute(DynamoDBEvent _)
    {
        return TypedDynamoDbStreamBatchProcessor.Result.BatchItemFailuresResponse; 
    }
}
```

# Lambda で DynamoDB イベントソースの破棄されたレコードを保持する
<a name="services-dynamodb-errors"></a>

DynamoDB イベントソースマッピングのエラー処理は、エラーが関数の呼び出し前に発生するか、関数の呼び出し中に発生するかによって異なります。
+ **呼び出し前:** スロットリングまたはその他の問題によって Lambda イベントソースマッピングが関数を呼び出すことができない場合、レコードの有効期限が切れるか、イベントソースマッピングで設定された最大有効期間 ([MaximumRecordAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRecordAgeInSeconds)) を超えるまで再試行します。
+ **呼び出し中:** 関数は呼び出されたがエラーが返された場合、Lambda はレコードの有効期限が切れるか、最大有効期間 ([MaximumRecordAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRecordAgeInSeconds)) を超えるか、設定された再試行クォータ ([MaximumRetryAttempts](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRetryAttempts)) に達するまで再試行します。関数エラーの場合、[BisectBatchOnFunctionError](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-response-BisectBatchOnFunctionError) を設定することもできます。これは、失敗したバッチを 2 つの小さなバッチに分割し、不良レコードを分離してタイムアウトを回避します。バッチを分割しても、再試行クォータは消費されません。

エラー処理の対策に失敗すると、Lambda はレコードを破棄し、ストリームからのバッチ処理を継続します。デフォルト設定では、不良レコードによって、影響を受けるシャードでの処理が最大 1 日間ブロックされる可能性があります。これを回避するには、関数のイベントソースマッピングを、適切な再試行回数と、ユースケースに適合する最大レコード経過時間で設定します。

## 失敗した呼び出しの送信先の設定
<a name="dynamodb-on-failure-destination-console"></a>

失敗したイベントソースマッピング呼び出しの記録を保持するには、関数のイベントソースマッピングに送信先を追加します。送信先に送られる各レコードは、失敗した呼び出しに関するメタデータを含む JSON ドキュメントです。Amazon S3 送信先の場合、Lambda はメタデータと共に呼び出しレコード全体を送信します。任意の Amazon SNS トピック、Amazon SQS キュー、Amazon S3 バケット、または Kafka を送信先として設定できます。

Amazon S3 送信先を使用すると、[Amazon S3 イベント通知](https://docs.aws.amazon.com/)機能を使用して、オブジェクトが送信先 S3 バケットにアップロードされたときに通知を受け取ることができます。また、S3 イベント通知を設定して、失敗したバッチに対して別の Lambda 関数を呼び出し、自動処理を実行することもできます。

実行ロールには、送信先に対するアクセス許可が必要です。
+ **SQS 送信先の場合:** [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)
+ **SNS 送信先の場合:** [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)
+ **S3 送信先の場合:** [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) および [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/ListObjectsV2.html)
+ **Kafka 送信先の場合:** [kafka-cluster:WriteData](https://docs.aws.amazon.com/msk/latest/developerguide/kafka-actions.html)

Kafka トピックは、Kafka イベントソースマッピングの障害発生時の送信先として設定できます。再試行回数を超えた後、またはレコードが最大経過時間を超えた後に Lambda がレコードを処理できなくなると、Lambda は失敗したレコードを指定された Kafka トピックに送信して、後で処理します。「[Kafka トピックを障害発生時の送信先として使用する](kafka-on-failure-destination.md)」を参照してください。

S3 送信先に対して独自の KMS キーを使用した暗号化を有効にしている場合、関数の実行ロールには [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) を呼び出すためのアクセス許可も必要です。KMS キーと S3 バケットの送信先が Lambda 関数および実行ロールとは異なるアカウントにある場合は、kms:GenerateDataKey を許可するように実行ロールを信頼するように KMS キーを設定します。

障害発生時の送信先をコンソールを使用して設定するには、以下の手順に従います。

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. [**機能の概要 **] で、[**送信先を追加 **] を選択します。

1. **[ソース]** には、**[イベントソースマッピング呼び出し]** を選択します。

1. **[イベントソースマッピング]** では、この関数用に設定されているイベントソースを選択します。

1. **[条件]** には **[失敗時]** を選択します。イベントソースマッピング呼び出しでは、これが唯一受け入れられる条件です。

1. **[送信先タイプ]** では、Lambda が呼び出しレコードを送信する送信先タイプを選択します。

1. [**送信先**] で、リソースを選択します。

1. **[保存]** を選択します。

AWS Command Line Interface (AWS CLI) を使用して障害発生時の送信先を設定することもできます。例えば、次の [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドは、SQS を障害発生時の送信先として持つイベントソースマッピングを `MyFunction` に追加します。

```
aws lambda create-event-source-mapping \
--function-name "MyFunction" \
--event-source-arn arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2024-06-10T19:26:16.525 \
--destination-config '{"OnFailure": {"Destination": "arn:aws:sqs:us-east-1:123456789012:dest-queue"}}'
```

次の [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドは、2 回の再試行後、またはレコードが 1 時間以上経過した場合に失敗した呼び出しレコードを SNS 送信先に送信するように、イベントソースマッピングを更新します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--maximum-retry-attempts 2 \
--maximum-record-age-in-seconds 3600 \
--destination-config '{"OnFailure": {"Destination": "arn:aws:sns:us-east-1:123456789012:dest-topic"}}'
```

更新された設定は非同期に適用され、プロセスが完了するまで出力に反映されません。現在のステータスを表示するには、[get-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html) コマンドを使用します。

送信先を削除するには、`destination-config` パラメータの引数として空の文字列を指定します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--destination-config '{"OnFailure": {"Destination": ""}}'
```

### Amazon S3 送信先のセキュリティのベストプラクティス
<a name="ddb-s3-destination-security"></a>

関数の設定から送信先を削除せずに、送信先として設定された S3 バケットを削除すると、セキュリティリスクが発生する可能性があります。別のユーザーが送信先バケットの名前を知っている場合は、その AWS アカウントでバケットを再作成できます。失敗した呼び出しのレコードがそのバケットに送信され、関数からのデータが公開される可能性があります。

**警告**  
関数からの呼び出しレコードを別の AWS アカウントの S3 バケットに送信できないようにするには、`s3:PutObject` アクセス許可を自分アカウントのバケットに制限する条件を関数の実行ロールに追加します。

次の例は、関数の `s3:PutObject` アクセス許可を自分のアカウントのバケットに制限する IAM ポリシーを示しています。このポリシーは、送信先として S3 バケットを使用するために必要な `s3:ListBucket` アクセス許可も Lambda に付与します。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "S3BucketResourceAccountWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::*/*",
                "arn:aws:s3:::*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:ResourceAccount": "111122223333"
                }
            }
        }
    ]
}
```

AWS マネジメントコンソールまたは AWS CLI を使用して、関数の実行ロールにアクセス許可ポリシーを追加する場合は、次の手順を参照してください。

------
#### [ Console ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 実行ロールを変更する Lambda 関数を選択します。

1. **[構成]** タブで、**[アクセス許可]** を選択します。

1. **[実行ロール]** タブで、関数の **[ロール名]** を選択して、ロールの IAM コンソールページを開きます。

1. 次の手順を実行してアクセス許可ポリシーをロールに追加します。

   1. **[アクセス許可ポリシー]** ペインで、**[アクセス許可の追加]**、**[インラインポリシーを作成]** を選択します。

   1. **ポリシーエディタ**で、**[JSON]** を選択します。

   1. 追加するポリシーをエディタに貼り付け (既存の JSON を置き換える)、**[次へ]** を選択します。

   1. **[ポリシーの詳細]** で **[ポリシー名]** を入力します。

   1. [**Create policy**] (ポリシーの作成) を選択します。

------
#### [ AWS CLI ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (CLI)**

1. 必要なアクセス許可を持つ JSON ポリシードキュメントを作成し、ローカルディレクトリに保存します。

1. IAM `put-role-policy` CLI コマンドを使用して、関数の実行ロールにアクセス許可を追加します。JSON ポリシードキュメントを保存したディレクトリから次のコマンドを実行して、ロール名、ポリシー名、ポリシードキュメントを独自の値に置き換えます。

   ```
   aws iam put-role-policy \
   --role-name my_lambda_role \
   --policy-name LambdaS3DestinationPolicy \
   --policy-document file://my_policy.json
   ```

------

### Amazon SNS および Amazon SQS の呼び出しレコードの例
<a name="kinesis-on-failure-destination-example-sns-sqs"></a>

次の例は、DynamoDB ストリームに対して Lambda が SQS または SNS 送信先に送信する呼び出しレコードを示しています。

```
{
    "requestContext": {
        "requestId": "316aa6d0-8154-xmpl-9af7-85d5f4a6bc81",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted",
        "approximateInvokeCount": 1
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:13:49.717Z",
    "DDBStreamBatchInfo": {
        "shardId": "shardId-00000001573689847184-864758bb",
        "startSequenceNumber": "800000000003126276362",
        "endSequenceNumber": "800000000003126276362",
        "approximateArrivalOfFirstRecord": "2019-11-14T00:13:19Z",
        "approximateArrivalOfLastRecord": "2019-11-14T00:13:19Z",
        "batchSize": 1,
        "streamArn": "arn:aws:dynamodb:us-east-2:123456789012:table/mytable/stream/2019-11-14T00:04:06.388"
    }
}
```

この情報は、トラブルシューティングのためにストリームから影響を受けるレコードを取得する際に使用できます。実際のレコードは含まれていないので、有効期限が切れて失われる前に、このレコードを処理し、ストリームから取得する必要があります。

### Amazon S3 呼び出しレコードの例
<a name="kinesis-on-failure-destination-example-sns-sqs-s3"></a>

次の例は、DynamoDB ストリームに対して Lambda が S3 バケットに送信する呼び出しレコードを示しています。SQS と SNS の送信先に関する前例のすべてのフィールドに加えて、`payload` フィールドには元の呼び出しレコードがエスケープされた JSON 文字列として含まれています。

```
{
    "requestContext": {
        "requestId": "316aa6d0-8154-xmpl-9af7-85d5f4a6bc81",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted",
        "approximateInvokeCount": 1
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:13:49.717Z",
    "DDBStreamBatchInfo": {
        "shardId": "shardId-00000001573689847184-864758bb",
        "startSequenceNumber": "800000000003126276362",
        "endSequenceNumber": "800000000003126276362",
        "approximateArrivalOfFirstRecord": "2019-11-14T00:13:19Z",
        "approximateArrivalOfLastRecord": "2019-11-14T00:13:19Z",
        "batchSize": 1,
        "streamArn": "arn:aws:dynamodb:us-east-2:123456789012:table/mytable/stream/2019-11-14T00:04:06.388"
    },
    "payload": "<Whole Event>" // Only available in S3
}
```

呼び出しレコードを含む S3 オブジェクトでは、次の命名規則が使用されます。

```
aws/lambda/<ESM-UUID>/<shardID>/YYYY/MM/DD/YYYY-MM-DDTHH.MM.SS-<Random UUID>
```

# Lambda での ステートフル DynamoDB ストリーム処理の実装
<a name="services-ddb-windows"></a>

Lambda 関数は、連続ストリーム処理アプリケーションを実行できます。ストリームは、アプリケーションを継続的に流れる無限のデータを表します。この継続的に更新される入力からの情報を分析するために、時間に関して定義されたウィンドウを使用して、含まれるレコードをバインドできます。

タンブリングウィンドウは、一定の間隔で開閉する別個のタイムウィンドウです。ディフォルトでは、Lambda 呼び出しはステートレス — 外部データベースがない場合、複数の連続した呼び出しでデータを処理するために使用することはできません。ただし、タンブリングウィンドウを使用して、呼び出し間で状態を維持できます。この状態は、現在のウィンドウに対して以前に処理されたメッセージの集計結果が含まれます。状態は、シャードごとに最大 1 MB にすることができます。このサイズを超えると、Lambda はウィンドウを早期に終了します。

ストリームの各レコードは、特定のウィンドウに属しています。Lambda は各レコードを少なくとも 1 回処理しますが、各レコードが 1 回だけ処理される保証はありません。エラー処理などのまれなケースでは、一部のレコードが複数回処理されることがあります。レコードは常に最初から順番に処理されます。レコードが複数回処理される場合、順不同で処理されます。

## 集約と処理
<a name="streams-tumbling-processing"></a>

ユーザー管理関数は、集約と、その集約の最終結果を処理するために呼び出されます。Lambda は、ウィンドウで受信したすべてのレコードを集約します。これらのレコードは、個別の呼び出しとして複数のバッチで受け取ることができます。各呼び出しは状態を受け取ります。したがって、タンブリングウィンドウを使用する場合、Lambda 関数の応答に `state` プロパティが含まれている必要があります。応答に `state` プロパティが含まれてないと、Lambda はこれを失敗した呼び出しと見なします。この条件を満たすために、関数は次の JSON 形式の `TimeWindowEventResponse` オブジェクトを返すことができます。

**Example `TimeWindowEventResponse`値**  

```
{
    "state": {
        "1": 282,
        "2": 715
    },
    "batchItemFailures": []
}
```

**注記**  
Java 関数の場合は、`Map<String, String>`を使用して状態を表すことをお勧めします。

ウィンドウの最後で、フラグ`isFinalInvokeForWindow`が`true`に設定され、これが最終状態であり、処理の準備ができていることが示されます。処理が完了すると、ウィンドウが完了し、最終的な呼び出しが完了し、状態は削除されます。

ウィンドウの最後に、Lambda は集計結果に対するアクションの最終処理を使用します。最終処理が同期的に呼び出されます。呼び出しが成功すると、関数はシーケンス番号をチェックポイントし、ストリーム処理が続行されます。呼び出しが失敗した場合、Lambda 関数は呼び出しが成功するまで処理を一時停止します。

**Example DynamodbtimeWindowEvent**  

```
{
   "Records":[
      {
         "eventID":"1",
         "eventName":"INSERT",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "NewImage":{
               "Message":{
                  "S":"New item!"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"111",
            "SizeBytes":26,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      },
      {
         "eventID":"2",
         "eventName":"MODIFY",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "NewImage":{
               "Message":{
                  "S":"This item has changed"
               },
               "Id":{
                  "N":"101"
               }
            },
            "OldImage":{
               "Message":{
                  "S":"New item!"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"222",
            "SizeBytes":59,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      },
      {
         "eventID":"3",
         "eventName":"REMOVE",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "OldImage":{
               "Message":{
                  "S":"This item has changed"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"333",
            "SizeBytes":38,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      }
   ],
    "window": {
        "start": "2020-07-30T17:00:00Z",
        "end": "2020-07-30T17:05:00Z"
    },
    "state": {
        "1": "state1"
    },
    "shardId": "shard123456789",
    "eventSourceARN": "stream-ARN",
    "isFinalInvokeForWindow": false,
    "isWindowTerminatedEarly": false
}
```

## 設定
<a name="streams-tumbling-config"></a>

イベントソースマッピングを作成または更新するときに 、タンブリングウィンドウを設定できます。タンブリングウィンドウを設定するには、ウィンドウを秒単位で指定します ([TumblingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-TumblingWindowInSeconds))。次の例の AWS Command Line Interface (AWS CLI) コマンドは、タンブリングウィンドウが 120 秒に設定されたストリーミングイベントソースマッピングを作成します。集約と処理のために Lambda 関数が定義した関数の名前は `tumbling-window-example-function` です。

```
aws lambda create-event-source-mapping \
--event-source-arn arn:aws:dynamodb:us-east-2:123456789012:table/my-table/stream/2024-06-10T19:26:16.525 \
--function-name tumbling-window-example-function \
--starting-position TRIM_HORIZON \
--tumbling-window-in-seconds 120
```

Lambda は、レコードがストリームに挿入された時間に基づいて、タンブリングウィンドウの境界を決定します。すべてのレコードには、Lambda が境界の決定に使用するおおよそのタイムスタンプがあります。

ウィンドウの集合をタンブルしても、再共有はサポートされません。シャードが終了すると、Lambda はウィンドウが閉じているとみなし、子シャードは新しい状態で自身のウィンドウを開始します。

タンブルウィンドウは、既存の再試行ポリシー`maxRetryAttempts`および`maxRecordAge`を完全にサポートします。

**Example Handler.py - 集約と処理**  
次の Python 関数は、最終状態を集約して処理する方法を示しています。  

```
def lambda_handler(event, context):
    print('Incoming event: ', event)
    print('Incoming state: ', event['state'])

#Check if this is the end of the window to either aggregate or process.
    if event['isFinalInvokeForWindow']:
        # logic to handle final state of the window
        print('Destination invoke')
    else:
        print('Aggregate invoke')

#Check for early terminations
    if event['isWindowTerminatedEarly']:
        print('Window terminated early')

    #Aggregation logic
    state = event['state']
    for record in event['Records']:
        state[record['dynamodb']['NewImage']['Id']] = state.get(record['dynamodb']['NewImage']['Id'], 0) + 1

    print('Returning state: ', state)
    return {'state': state}
```

# Amazon DynamoDB イベントソースマッピング用の Lambda パラメータ
<a name="services-ddb-params"></a>

すべての Lambda イベントソースタイプは、同じ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションを共有しています。ただし、DynamoDB Streams に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | メモ | 
| --- | --- | --- | --- | 
|  BatchSize  |  N  |  100  |  最大: 10,000  | 
|  BisectBatchOnFunctionError  |  いいえ  |  false  | なし  | 
|  DestinationConfig  |  いいえ  | 該当なし  |  廃棄されたレコードの標準 Amazon SQS キューまたは標準 Amazon SNS トピックの送信先。  | 
|  有効  |  いいえ  |  true  | なし  | 
|  EventSourceArn  |  はい  | 該当なし |  データストリームまたはストリームコンシューマーの ARN。  | 
|  FilterCriteria  |  いいえ  | 該当なし  |  [Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)  | 
|  FunctionName  |  はい  | 該当なし  | なし  | 
|  FunctionResponseTypes  |  いいえ  | 該当なし |  関数がバッチ内の特定の失敗を報告できるようにするには、`FunctionResponseTypes` に値 `ReportBatchItemFailures` を含めます。詳細については、「[DynamoDB と Lambda を使用した部分的なバッチレスポンスの設定](services-ddb-batchfailurereporting.md)」を参照してください。  | 
|  MaximumBatchingWindowInSeconds  |  いいえ  |  0  | なし  | 
|  MaximumRecordAgeInSeconds  |  いいえ  |  -1  |  -1 は無制限を意味し、失敗したレコードは有効期限が切れるまで再試行されます。「[DynamoDB ストリームのデータ保持制限](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html#Streams.DataRetention)」は 24 時間です。 最小: -1 最大: 604,800  | 
|  MaximumRetryAttempts  |  いいえ  |  -1  |  -1 に設定すると無制限になり、失敗したレコードはレコードの有効期限が切れるまで再試行されます。 最小: 0 最大: 10,000  | 
|  ParallelizationFactor  |  いいえ  |  1  |  最大: 10  | 
|  StartingPosition  |  はい  | 該当なし  |  TRIM\$1HORIZON または LATEST  | 
|  TumblingWindowInSeconds  |  いいえ  | 該当なし  |  最小: 0 最大: 900  | 

# DynamoDB イベントソースでのイベントフィルタリングの使用
<a name="with-ddb-filtering"></a>

イベントフィルタリングを使用して、Lambda が関数に送信するストリームまたはキューからのレコードを制御することができます。イベントフィルタリングの仕組みに関する一般情報については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

このセクションでは、DynamoDB イベントソースのイベントフィルタリングに焦点を当てます。

**注記**  
DynamoDB イベントソースマッピングは、 `dynamodb` キーでのフィルタリングのみをサポートします。

**Topics**
+ [DynamoDB イベント](#filtering-ddb)
+ [テーブル属性でフィルタリングする](#filtering-ddb-attributes)
+ [ブール式でフィルタリングする](#filtering-ddb-boolean)
+ [Exists 演算子の使用](#filtering-ddb-exists)
+ [DynamoDB フィルタリングの JSON 形式](#filtering-ddb-JSON-format)

## DynamoDB イベント
<a name="filtering-ddb"></a>

プライマリキー `CustomerName`、属性 `AccountManager`、属性 `PaymentTerms` を含む DynamoDB テーブルがあるとします。次の内容では、DynamoDB テーブルのストリームからのレコード例が示されています。

```
{
      "eventID": "1",
      "eventVersion": "1.0",
      "dynamodb": {
          "ApproximateCreationDateTime": "1678831218.0",
          "Keys": {
              "CustomerName": {
                  "S": "AnyCompany Industries"
              }
          },
          "NewImage": {
              "AccountManager": {
                  "S": "Pat Candella"
              },
              "PaymentTerms": {
                  "S": "60 days"
              },
              "CustomerName": {
                  "S": "AnyCompany Industries"
              }
          },
          "SequenceNumber": "111",
          "SizeBytes": 26,
          "StreamViewType": "NEW_IMAGE"
      }
  }
```

DynamoDB テーブルのキーおよび属性値に基づいてフィルタリングするには、レコードで `dynamodb` キーを使用します。次のセクションでは、さまざまなフィルタータイプの例を示します。

### テーブルキーでフィルタリングする
<a name="filtering-ddb-keys"></a>

プライマリキー `CustomerName` が「AnyCompany Industries」のレコードのみを関数で処理するとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
     "Filters": [
          {
              "Pattern": "{ \"dynamodb\" : { \"Keys\" : { \"CustomerName\" : { \"S\" : [ \"AnyCompany Industries\" ] } } } }"
          }
      ]
 }
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
     "dynamodb": {
          "Keys": {
              "CustomerName": {
                  "S": [ "AnyCompany Industries" ]
                  }
              }
          }
 }
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "dynamodb" : { "Keys" : { "CustomerName" : { "S" : [ "AnyCompany Industries" ] } } } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:dynamodb:us-east-2:123456789012:table/my-table \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"Keys\" : { \"CustomerName\" : { \"S\" : [ \"AnyCompany Industries\" ] } } } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"Keys\" : { \"CustomerName\" : { \"S\" : [ \"AnyCompany Industries\" ] } } } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
   Filters:
     - Pattern: '{ "dynamodb" : { "Keys" : { "CustomerName" : { "S" : [ "AnyCompany Industries" ] } } } }'
```

------

## テーブル属性でフィルタリングする
<a name="filtering-ddb-attributes"></a>

DynamoDB を使用すると、`NewImage` および `OldImage` キーを使用して属性値をフィルタリングすることもできます。最新のテーブル画像の `AccountManager` 属性が「Pat Candella」または「Shirley Rodriguez」のレコードをフィルタリングするとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\", \"Shirley Rodriguez\" ] } } } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "dynamodb": {
        "NewImage": {
            "AccountManager": {
                "S": [ "Pat Candella", "Shirley Rodriguez" ]
            }
        }
    }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "dynamodb" : { "NewImage" : { "AccountManager" : { "S" : [ "Pat Candella", "Shirley Rodriguez" ] } } } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:dynamodb:us-east-2:123456789012:table/my-table \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\", \"Shirley Rodriguez\" ] } } } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\", \"Shirley Rodriguez\" ] } } } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "dynamodb" : { "NewImage" : { "AccountManager" : { "S" : [ "Pat Candella", "Shirley Rodriguez" ] } } } }'
```

------

## ブール式でフィルタリングする
<a name="filtering-ddb-boolean"></a>

ブール型 AND 式を使用してフィルターを作成することもできます。これらの式には、テーブルの主パラメータと属性パラメータの両方を含めることができます。`AccountManager` の `NewImage` の値が「Pat Candella」で、`OldImage` の値が「Terry Whitlock」であるレコードをフィルタリングするとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\" ] } } } , \"dynamodb\" : { \"OldImage\" : { \"AccountManager\" : { \"S\" : [ \"Terry Whitlock\" ] } } } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{ 
    "dynamodb" : { 
        "NewImage" : { 
            "AccountManager" : { 
                "S" : [ 
                    "Pat Candella" 
                ] 
            } 
        } 
    }, 
    "dynamodb": { 
        "OldImage": { 
            "AccountManager": { 
                "S": [ 
                    "Terry Whitlock" 
                ] 
            } 
        } 
    } 
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "dynamodb" : { "NewImage" : { "AccountManager" : { "S" : [ "Pat Candella" ] } } } , "dynamodb" : { "OldImage" : { "AccountManager" : { "S" : [ "Terry Whitlock" ] } } } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:dynamodb:us-east-2:123456789012:table/my-table \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\" ] } } } , \"dynamodb\" : { \"OldImage\" : { \"AccountManager\" : { \"S\" : [ \"Terry Whitlock\" ] } } } } "}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"dynamodb\" : { \"NewImage\" : { \"AccountManager\" : { \"S\" : [ \"Pat Candella\" ] } } } , \"dynamodb\" : { \"OldImage\" : { \"AccountManager\" : { \"S\" : [ \"Terry Whitlock\" ] } } } } "}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "dynamodb" : { "NewImage" : { "AccountManager" : { "S" : [ "Pat Candella" ] } } } , "dynamodb" : { "OldImage" : { "AccountManager" : { "S" : [ "Terry Whitlock" ] } } } }'
```

------

**注記**  
DynamoDB イベントフィルタリングは、数値演算子 (数値等式および数値範囲) の使用をサポートしていません。テーブルの項目が数値として保存されている場合でも、これらのパラメータは JSON レコードオブジェクトの文字列に変換されます。

## Exists 演算子の使用
<a name="filtering-ddb-exists"></a>

DynamoDB の JSON イベントオブジェクトは構造化されているため、EXISTS 演算子の使用には特別な注意が必要です。EXISTS 演算子はイベント JSON のリーフノードでのみ機能するため、フィルターパターンが EXISTS を使用して中間ノードをテストしても機能しません。次の DynamoDB テーブルの項目を考慮します。

```
{
  "UserID": {"S": "12345"},
  "Name": {"S": "John Doe"},
  "Organizations": {"L": [
      {"S":"Sales"},
      {"S":"Marketing"},
      {"S":"Support"}
    ]
  }
}
```

次のように、`"Organizations"` を含むイベントをテストするフィルターパターンを作成できます。

```
{ "dynamodb" : { "NewImage" : { "Organizations" : [ { "exists": true } ] } } }
```

ただし、`"Organizations"` はリーフノードではないため、このフィルターパターンに一致するものは返されません。次の例では、EXISTS 演算子を適切に使用して目的のフィルターパターンを作成する方法を示しています。

```
{ "dynamodb" : { "NewImage" : {"Organizations": {"L": {"S": [ {"exists": true } ] } } } } }
```

## DynamoDB フィルタリングの JSON 形式
<a name="filtering-ddb-JSON-format"></a>

DynamoDB ソースのイベントを適切にフィルタリングするには、データフィールドおよびデータフィールド (`dynamodb`) のフィルター条件の両方が有効な JSON 形式である必要があります。フィールドのどちらかが有効な JSON 形式ではない場合、Lambda はメッセージをドロップするか、例外をスローします。以下は、特定の動作を要約した表です。


| 着信データの形式 | データプロパティのフィルターパターンの形式 | 結果として生じるアクション | 
| --- | --- | --- | 
|  有効な JSON  |  有効な JSON  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  有効な JSON  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  JSON 以外  |  Lambda がイベントソースマッピングの作成または更新時に例外をスローします。データプロパティのフィルターパターンは、有効な JSON 形式である必要があります。  | 
|  JSON 以外  |  有効な JSON  |  Lambda がレコードをドロップします。  | 
|  JSON 以外  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  JSON 以外  |  JSON 以外  |  Lambda がイベントソースマッピングの作成または更新時に例外をスローします。データプロパティのフィルターパターンは、有効な JSON 形式である必要があります。  | 

# チュートリアル: Amazon DynamoDB Streams で AWS Lambda を使用する
<a name="with-ddb-example"></a>

 このチュートリアルでは、Amazon DynamoDB ストリームからのイベントを処理する Lambda 関数を作成します。

## 前提条件
<a name="with-ddb-prepare"></a>

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## 実行ロールを作成する
<a name="with-ddb-create-execution-role"></a>

AWS リソースにアクセスするためのアクセス権限を関数に付与する[実行ロール](lambda-intro-execution-role.md)を作成します。

**実行ロールを作成するには**

1. IAM コンソールの [[ロールページ](https://console.aws.amazon.com/iam/home#/roles)] を開きます。

1. [**ロールの作成**] を選択します。

1. 次のプロパティでロールを作成します。
   + **信頼されたエンティティ** – Lambda
   + **アクセス許可** - **AWSLambdaDynamoDBExecutionRole**
   + **ロール名** -**lambda-dynamodb-role** 

**AWSLambdaDynamoDBExecutionRole** には、DynamoDB から項目を読み取り、 に CloudWatch Logs ログを書き込むために、関数が必要とするアクセス許可があります。

## 関数を作成する
<a name="with-ddb-example-create-function"></a>

DynamoDB イベントを処理する Lambda 関数を作成します。関数コードは、受信イベントデータの一部を CloudWatch ログに書き込みます。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用して Lambda で DynamoDB イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System.Text.Json;
using System.Text;
using Amazon.Lambda.Core;
using Amazon.Lambda.DynamoDBEvents;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace AWSLambda_DDB;

public class Function
{
    public void FunctionHandler(DynamoDBEvent dynamoEvent, ILambdaContext context)
    {
        context.Logger.LogInformation($"Beginning to process {dynamoEvent.Records.Count} records...");

        foreach (var record in dynamoEvent.Records)
        {
            context.Logger.LogInformation($"Event ID: {record.EventID}");
            context.Logger.LogInformation($"Event Name: {record.EventName}");

            context.Logger.LogInformation(JsonSerializer.Serialize(record));
        }

        context.Logger.LogInformation("Stream processing complete.");
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用して Lambda で DynamoDB イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main

import (
	"context"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-lambda-go/events"
	"fmt"
)

func HandleRequest(ctx context.Context, event events.DynamoDBEvent) (*string, error) {
	if len(event.Records) == 0 {
		return nil, fmt.Errorf("received empty event")
	}

	for _, record := range event.Records {
	 	LogDynamoDBRecord(record)
	}

	message := fmt.Sprintf("Records processed: %d", len(event.Records))
	return &message, nil
}

func main() {
	lambda.Start(HandleRequest)
}

func LogDynamoDBRecord(record events.DynamoDBEventRecord){
	fmt.Println(record.EventID)
	fmt.Println(record.EventName)
	fmt.Printf("%+v\n", record.Change)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用して Lambda で DynamoDB イベントの消費。  

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent.DynamodbStreamRecord;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class example implements RequestHandler<DynamodbEvent, Void> {

    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();

    @Override
    public Void handleRequest(DynamodbEvent event, Context context) {
        System.out.println(GSON.toJson(event));
        event.getRecords().forEach(this::logDynamoDBRecord);
        return null;
    }

    private void logDynamoDBRecord(DynamodbStreamRecord record) {
        System.out.println(record.getEventID());
        System.out.println(record.getEventName());
        System.out.println("DynamoDB Record: " + GSON.toJson(record.getDynamodb()));
    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での DynamoDB イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
    console.log(JSON.stringify(event, null, 2));
    event.Records.forEach(record => {
        logDynamoDBRecord(record);
    });
};

const logDynamoDBRecord = (record) => {
    console.log(record.eventID);
    console.log(record.eventName);
    console.log(`DynamoDB Record: ${JSON.stringify(record.dynamodb)}`);
};
```
TypeScript を使用した Lambda での DynamoDB イベントの消費。  

```
export const handler = async (event, context) => {
    console.log(JSON.stringify(event, null, 2));
    event.Records.forEach(record => {
        logDynamoDBRecord(record);
    });
}
const logDynamoDBRecord = (record) => {
    console.log(record.eventID);
    console.log(record.eventName);
    console.log(`DynamoDB Record: ${JSON.stringify(record.dynamodb)}`);
};
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での DynamoDB イベントの消費。  

```
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\DynamoDb\DynamoDbEvent;
use Bref\Event\DynamoDb\DynamoDbHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler extends DynamoDbHandler
{
    private StderrLogger $logger;

    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws JsonException
     * @throws \Bref\Event\InvalidLambdaEvent
     */
    public function handleDynamoDb(DynamoDbEvent $event, Context $context): void
    {
        $this->logger->info("Processing DynamoDb table items");
        $records = $event->getRecords();

        foreach ($records as $record) {
            $eventName = $record->getEventName();
            $keys = $record->getKeys();
            $old = $record->getOldImage();
            $new = $record->getNewImage();
            
            $this->logger->info("Event Name:".$eventName."\n");
            $this->logger->info("Keys:". json_encode($keys)."\n");
            $this->logger->info("Old Image:". json_encode($old)."\n");
            $this->logger->info("New Image:". json_encode($new));
            
            // TODO: Do interesting work based on the new data

            // Any exception thrown will be logged and the invocation will be marked as failed
        }

        $totalRecords = count($records);
        $this->logger->info("Successfully processed $totalRecords items");
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用して Lambda で DynamoDB イベントの消費。  

```
import json

def lambda_handler(event, context):
    print(json.dumps(event, indent=2))

    for record in event['Records']:
        log_dynamodb_record(record)

def log_dynamodb_record(record):
    print(record['eventID'])
    print(record['eventName'])
    print(f"DynamoDB Record: {json.dumps(record['dynamodb'])}")
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用して Lambda で DynamoDB イベントの消費。  

```
def lambda_handler(event:, context:)
    return 'received empty event' if event['Records'].empty?
  
    event['Records'].each do |record|
      log_dynamodb_record(record)
    end
  
    "Records processed: #{event['Records'].length}"
  end
  
  def log_dynamodb_record(record)
    puts record['eventID']
    puts record['eventName']
    puts "DynamoDB Record: #{JSON.generate(record['dynamodb'])}"
  end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-ddb-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用して Lambda で DynamoDB イベントを利用します。  

```
use lambda_runtime::{service_fn, tracing, Error, LambdaEvent};
use aws_lambda_events::{
    event::dynamodb::{Event, EventRecord},
   };


// Built with the following dependencies:
//lambda_runtime = "0.11.1"
//serde_json = "1.0"
//tokio = { version = "1", features = ["macros"] }
//tracing = { version = "0.1", features = ["log"] }
//tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }
//aws_lambda_events = "0.15.0"

async fn function_handler(event: LambdaEvent<Event>) ->Result<(), Error> {
    
    let records = &event.payload.records;
    tracing::info!("event payload: {:?}",records);
    if records.is_empty() {
        tracing::info!("No records found. Exiting.");
        return Ok(());
    }

    for record in records{
        log_dynamo_dbrecord(record);
    }

    tracing::info!("Dynamo db records processed");

    // Prepare the response
    Ok(())

}

fn log_dynamo_dbrecord(record: &EventRecord)-> Result<(), Error>{
    tracing::info!("EventId: {}", record.event_id);
    tracing::info!("EventName: {}", record.event_name);
    tracing::info!("DynamoDB Record: {:?}", record.change );
    Ok(())

}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
    .with_max_level(tracing::Level::INFO)
    .with_target(false)
    .without_time()
    .init();

    let func = service_fn(function_handler);
    lambda_runtime::run(func).await?;
    Ok(())
    
}
```

------

**関数を作成するには**

1. サンプルコードを `example.js` という名前のファイルにコピーします。

1. デプロイパッケージを作成します。

   ```
   zip function.zip example.js
   ```

1. `create-function` コマンドを使用して Lambda 関数を作成します。

   ```
   aws lambda create-function --function-name ProcessDynamoDBRecords \
       --zip-file fileb://function.zip --handler example.handler --runtime nodejs24.x \
       --role arn:aws:iam::111122223333:role/lambda-dynamodb-role
   ```

## Lambda 関数をテストする
<a name="with-dbb-invoke-manually"></a>

このセットアップでは、`invoke`AWS Lambda の CLI コマンドと次のサンプルの DynamoDB イベントを使用して、Lambda 関数を手動で呼び出します。次の内容を `input.txt` という名前のファイルにコピーします。

**Example input.txt**  

```
{
   "Records":[
      {
         "eventID":"1",
         "eventName":"INSERT",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "NewImage":{
               "Message":{
                  "S":"New item!"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"111",
            "SizeBytes":26,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      },
      {
         "eventID":"2",
         "eventName":"MODIFY",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "NewImage":{
               "Message":{
                  "S":"This item has changed"
               },
               "Id":{
                  "N":"101"
               }
            },
            "OldImage":{
               "Message":{
                  "S":"New item!"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"222",
            "SizeBytes":59,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      },
      {
         "eventID":"3",
         "eventName":"REMOVE",
         "eventVersion":"1.0",
         "eventSource":"aws:dynamodb",
         "awsRegion":"us-east-1",
         "dynamodb":{
            "Keys":{
               "Id":{
                  "N":"101"
               }
            },
            "OldImage":{
               "Message":{
                  "S":"This item has changed"
               },
               "Id":{
                  "N":"101"
               }
            },
            "SequenceNumber":"333",
            "SizeBytes":38,
            "StreamViewType":"NEW_AND_OLD_IMAGES"
         },
         "eventSourceARN":"stream-ARN"
      }
   ]
}
```

次の `invoke` コマンドを実行します。

```
aws lambda invoke --function-name ProcessDynamoDBRecords \
    --cli-binary-format raw-in-base64-out \
    --payload file://input.txt outputfile.txt
```

AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。

この関数はレスポンス本文で文字列 `message` を返します。

`outputfile.txt` ファイルで出力を確認します。

## ストリーミングが有効になった DynamoDB テーブルを作成する
<a name="with-ddb-create-buckets"></a>

ストリーミングが有効な Amazon DynamoDB テーブルを作成します。

**DynamoDB テーブルを作成するには**

1. [DynamoDB コンソール](https://console.aws.amazon.com/dynamodb)を開きます。

1. [**Create table**] を選択します。

1. 次の設定でテーブルを作成します。
   + **テーブル名** – **lambda-dynamodb-stream**
   + **プライマリキー** – **id** (文字列)

1. [**作成**] を選択します。

**ストリームを有効化するには**

1. [DynamoDB コンソール](https://console.aws.amazon.com/dynamodb)を開きます。

1. [**テーブル**] を選択します。

1. [**lambda-dynamodb-stream**] テーブルを選択します。

1. [**Exports and streams**] (エクスポートとストリーミング)で、[**DynamoDB stream details**] (DynamoDB ストリーミングの詳細) を選択します。

1. **[オンにする]** を選択します。

1. **[ビュータイプ]** には、**[キー属性のみ]** を選択します。

1. **[ストリームをオンにする]** を選択します。

ストリーム ARN をメモします。こちらは、次のステップでストリームを Lambda 関数に関連付ける際に必要になります。ストリームの有効化の詳細については、「[DynamoDB Streams を使用したテーブルアクティビティのキャプチャ](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html)」を参照してください。

## AWS Lambda でイベントソースを追加する
<a name="with-ddb-attach-notification-configuration"></a>

AWS Lambda でイベントソースマッピングを作成します。このイベントソースのマッピングは、DynamoDB ストリームを Lambda 関数に関連付けます。このイベントソースのマッピングを作成すると、AWS Lambda はストリームのポーリングを開始します。

次の AWS CLI `create-event-source-mapping` コマンドを実行します。コマンドの実行後、UUID をメモします。この UUID は、イベントソースマッピングを削除するときなど、コマンドでイベントソースマッピングを参照する場合に必要になります。

```
aws lambda create-event-source-mapping --function-name ProcessDynamoDBRecords \
    --batch-size 100 --starting-position LATEST --event-source DynamoDB-stream-arn
```

 これにより、指定された DynamoDB ストリームと Lambda 関数の間にマッピングが作成されます。1 つの DynamoDB ストリームを複数の Lambda 関数と関連付けたり、1 つの Lambda 関数を複数のストリームに関連付けたりすることができます。ただし、Lambda 関数は、共有するストリーム用に、読み取りスループットを共有します。

次のコマンドを実行して、イベントソースのマッピングのリストを取得できます。

```
aws lambda list-event-source-mappings
```

このリストでは、作成済みのすべてのイベントソースのマッピングが返され、各マッピングに対して `LastProcessingResult` などが示されます。問題がある場合、このフィールドは情報メッセージを提供するために使用されます。`No records processed` (AWS Lambda がポーリングを開始していないか、ストリームにレコードがないことを示す) や、`OK` (AWS Lambda がストリームから正常にレコードを読み取り、Lambda 関数を呼び出したことを示す) などの値は、問題がないことを示しています。問題がある場合は、エラーメッセージが返されます。

イベントソースマッピングが多数ある場合、関数の name パラメータを使用して結果を絞り込みます。

```
aws lambda list-event-source-mappings --function-name ProcessDynamoDBRecords
```

## セットアップをテストする
<a name="with-ddb-final-integration-test-no-iam"></a>

エンドツーエンドエクスペリエンスをテストします。テーブルの更新を実行すると、DynamoDB はイベントレコードをストリームに書き込みます。ストリームをポーリングしている AWS Lambda は、ストリームで新しいレコードを検出し、イベントを Lambda 関数に渡して、ユーザーに代わって関数を実行します。

1. DynamoDB コンソールで、テーブルに項目を追加、更新、削除します。DynamoDB は、これらのアクションのレコードをストリームに書き込みます。

1. AWS Lambda は、ストリームをポーリングし、ストリームの更新を検出すると、ストリームで見つかったイベントデータを渡して Lambda 関数を呼び出します。

1. 関数が実行され、Amazon CloudWatch にログが作成されます。報告されたログは Amazon CloudWatch コンソールで確認できます。

## 次のステップ
<a name="with-ddb-next-steps"></a>

このチュートリアルでは、Lambda で DynamoDB ストリームイベントを処理するための基本について説明しました。本番ワークロードでは、部分的なバッチレスポンスロジックの実装を考慮し、個々のレコード障害処理の効率化を図ってください。Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)は、Python、TypeScript、.NET、Java で利用可能で、これに対する堅牢なソリューションを提供し、部分的なバッチレスポンスの複雑さを自動的に処理し、正常に処理されたレコードの再試行回数を減らします。

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[Delete]** (削除) を選択します。

**DynamoDB テーブルを削除するには**

1. DynamoDB コンソールで [[Tables (テーブル)] ページ](https://console.aws.amazon.com//dynamodb/home#tables:)を開きます。

1. 作成したテーブルを選択します。

1. [**削除**] を選択します。

1. テキストボックスに「**delete**」と入力します。

1. **[テーブルの削除]** を選択します。

# Lambda 関数を使用して Amazon EC2 のライフサイクルイベントを処理する
<a name="services-ec2"></a>

AWS Lambdaを使用して、Amazon Elastic Compute Cloud のライフサイクルイベントを処理し、Amazon EC2 リソースを管理します。Amazon EC2 は、インスタンスの状態が変化したとき、Amazon Elastic Block Store ボリュームのスナップショットが完了したとき、スポットインスタンスの終了が予定されているときなどの[ライフサイクルイベント](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-lifecycle.html)において、イベントを [Amazon EventBridge (CloudWatch Events)](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html) に送信します。これらのイベントを Lambda 関数に転送して処理を行うように、Eventbridge (CloudWatch Events) を設定します。

Eventbridge (CloudWatch Events) は、Amazon EC2 からのイベントドキュメントを使用して、Lambda 関数を非同期的に呼び出します。

**Example インスタンスのライフサイクルイベント**  

```
{
    "version": "0",
    "id": "b6ba298a-7732-2226-xmpl-976312c1a050",
    "detail-type": "EC2 Instance State-change Notification",
    "source": "aws.ec2",
    "account": "111122223333",
    "time": "2019-10-02T17:59:30Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:ec2:us-east-1:111122223333:instance/i-0c314xmplcd5b8173"
    ],
    "detail": {
        "instance-id": "i-0c314xmplcd5b8173",
        "state": "running"
    }
}
```

イベントの設定の詳細については、「[スケジュールに従って Lambda 関数を呼び出す](with-eventbridge-scheduler.md)」を参照してください。Amazon EBS スナップショット通知を処理する関数の例については、「[EventBridge Scheduler for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-cloud-watch-events.html)」を参照してください。

AWS SDK を使用して、Amazon EC2 API でインスタンスやその他のリソースを管理することもできます。

## EventBridge へのアクセス許可の付与 (CloudWatch Events)
<a name="services-ec2-permissions"></a>

Amazon EC2 のライフサイクルイベントを処理するには、Eventbridge (CloudWatch Events) で関数を呼び出すためのアクセス許可が必要です。このアクセス許可は、関数の[リソースベースのポリシー](access-control-resource-based.md)から取得します。Eventbridge (CloudWatch Events) コンソールを使用してイベントトリガーを設定する場合は、コンソールがユーザーに代わってリソースベースのポリシーを更新します。それ以外の場合は、次のようなステートメントを追加します。

**Example Amazon EC2 ライフサイクル通知に使用するリソースベースのポリシーステートメント**  

```
{
  "Sid": "ec2-events",
  "Effect": "Allow",
  "Principal": {
    "Service": "events.amazonaws.com"
  },
  "Action": "lambda:InvokeFunction",
  "Resource": "arn:aws:lambda:us-east-1:12456789012:function:my-function",
  "Condition": {
    "ArnLike": {
      "AWS:SourceArn": "arn:aws:events:us-east-1:12456789012:rule/*"
    }
  }
}
```

ステートメントを追加するには、`add-permission` AWS CLI コマンドを使用します。

```
aws lambda add-permission --action lambda:InvokeFunction --statement-id ec2-events \
--principal events.amazonaws.com --function-name my-function --source-arn 'arn:aws:events:us-east-1:12456789012:rule/*'
```

関数で AWS SDK を使用して Amazon EC2 リソースを管理する場合は、関数の[実行ロール](lambda-intro-execution-role.md)に Amazon EC2 アクセス許可を追加します。

# Lambda を使用した Application Load Balancer リクエストの処理
<a name="services-alb"></a>

Lambda 関数を使用すると、Application Load Balancer のリクエストを処理することができます。Elastic Load Balancing は、Application Load Balancer のターゲットとして Lambda 関数をサポートしています。パス、またはその他のヘッダー値に基づき、ロードバランサールールを使用して、HTTP リクエストを関数にルーティングします。リクエストを処理して、Lambda 関数の HTTP レスポンスを返します。

Elastic Load Balancing は、リクエストボディおよびメタデータを含むイベントを使用して、Lambda 関数を同期的に呼び出します。

**Example Application Load Balancer リクエストイベント**  

```
{
    "requestContext": {
        "elb": {
            "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
        }
    },
    "httpMethod": "GET",
    "path": "/lambda",
    "queryStringParameters": {
        "query": "1234ABCD"
    },
    "headers": {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "accept-encoding": "gzip",
        "accept-language": "en-US,en;q=0.9",
        "connection": "keep-alive",
        "host": "lambda-alb-123578498.us-east-1.elb.amazonaws.com",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
        "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
        "x-forwarded-for": "72.12.164.125",
        "x-forwarded-port": "80",
        "x-forwarded-proto": "http",
        "x-imforwards": "20"
    },
    "body": "",
    "isBase64Encoded": False
}
```

関数は、イベントを処理し、応答ドキュメントを JSON でロードバランサーに返します。Elastic Load Balancing は、このドキュメントを HTTP 成功またはエラーの応答に変換し、ユーザーに返します。

**Example レスポンスドキュメントの形式**  

```
{
    "statusCode": 200,
    "statusDescription": "200 OK",
    "isBase64Encoded": False,
    "headers": {
        "Content-Type": "text/html"
    },
    "body": "<h1>Hello from Lambda!</h1>"
}
```

Application Load Balancer を関数トリガーとして設定するには、まず、関数を実行するアクセス許可を Elastic Load Balancing に付与します。次に、リクエストを関数にルーティングするターゲットグループを作成し、リクエストをターゲットグループに送信するルールをロードバランサーに追加します。

`add-permission` コマンドを使用して、アクセス許可ステートメントを関数のリソースベースのポリシーに追加します。

```
aws lambda add-permission --function-name alb-function \
--statement-id load-balancer --action "lambda:InvokeFunction" \
--principal elasticloadbalancing.amazonaws.com
```

次のような出力が表示されます。

```
{
    "Statement": "{\"Sid\":\"load-balancer\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"elasticloadbalancing.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-west-2:123456789012:function:alb-function\"}"
}
```

Application Load Balancer のリスナーおよびターゲットグループの設定手順については、*Application Load Balancer ユーザーガイド*の[ターゲットとしての Lambda 関数](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html)を参照してください。

## Powertools for AWS Lambda のイベントハンドラー
<a name="services-alb-powertools"></a>

Powertools for AWS Lambda ツールキットのイベントハンドラーは、Application Load Balancer によって呼び出される Lambda 関数を記述する際に、ルーティング、ミドルウェア、CORS 設定、OpenAPI 仕様生成、リクエスト検証、エラー処理、その他の便利な機能を提供します。イベントハンドラーユーティリティは Python で使用可能です。詳細については、Powertools for AWS Lambda (Python) ドキュメントの「[イベントハンドラー REST API](https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/)」を参照してください。**

### Python
<a name="services-alb-powertools-python"></a>

```
import requests
from requests import Response

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import ALBResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = ALBResolver()


@app.get("/todos")
@tracer.capture_method
def get_todos():
    todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
    todos.raise_for_status()

    # for brevity, we'll limit to the first 10 only
    return {"todos": todos.json()[:10]}


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.APPLICATION_LOAD_BALANCER)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)
```

# スケジュールに従って Lambda 関数を呼び出す
<a name="with-eventbridge-scheduler"></a>

[Amazon EventBridge スケジューラ](https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html)はサーバーレススケジューラで、一元化されたマネージドサービスからタスクを作成、実行、管理できます。EventBridge スケジューラでは、繰り返しのパターンに cron やレート式を使ってスケジュールを作成したり、1回限りの呼び出しを設定したりできます。配信の時間枠を柔軟に設定したり、再試行制限を定義したり、未処理のイベントの最大保持時間を設定できます。

Lambda で EventBridge スケジューラを設定すると、EventBridge スケジューラは Lambda 関数を非同期的に呼び出します。このページでは、EventBridge スケジューラを使用してスケジュールに基づき Lambda 関数を呼び出す方法について説明します。

## 実行ロールを設定する
<a name="using-eventbridge-scheduler-execution-role"></a>

 新しいスケジュールを作成する場合、EventBridge スケジューラにはユーザーに代わってターゲット API オペレーションを呼び出すアクセス許可が必要です。*実行ロール*を使用して、これらのアクセス許可を EventBridge スケジューラに付与します。スケジュールの実行ロールにアタッチするアクセス許可ポリシーによって、必要なアクセス許可が定義されます。これらのアクセス許可は、EventBridge スケジューラが呼び出すターゲット API によって異なります。

 次の手順のように EventBridge スケジューラコンソールを使用してスケジュールを作成すると、EventBridge スケジューラは選択したターゲットに基づき実行ロールを自動的に設定します。EventBridge スケジューラ SDK、AWS CLI、または CloudFormation のいずれかを使用してスケジュールを作成する場合、EventBridge スケジューラがターゲットを呼び出すために必要なアクセス許可を付与する既存の実行ロールが必要です。スケジュールに合わせて実行ロールを手動で設定する方法についての詳細は、「EventBridge スケジューラユーザーガイド」の「[実行ロールを設定する](https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html#setting-up-execution-role)」を参照してください。

## 新しいスケジュールを作成する
<a name="using-eventbridge-scheduler-create"></a>

**コンソールを使用してスケジュールを作成するには**

1. Amazon EventBridge スケジューラコンソール ([https://console.aws.amazon.com/scheduler/home](https://console.aws.amazon.com/scheduler/home/)) を開きます。

1.  **[スケジュール]** ページで、**[スケジュールを作成]** を選択します。

1.  **[スケジュールの詳細を指定]** ページの **[スケジュールの名前と説明]** セクションで、次を実行します。

   1. **[スケジュール名]** で、スケジュールの名前を入力します。例えば、**MyTestSchedule** と指定します。

   1. (オプション) **[説明]** で、スケジュールの説明を入力します。例えば、**My first schedule** と指定します。

   1. **[スケジュールグループ]** で、ドロップダウンリストからスケジュールグループを選択します。グループがない場合は、**[デフォルト]** を選択します。スケジュールグループを作成するには、**[独自のスケジュールを作成]** を選択します。

      スケジュールグループを使用して、スケジュールのグループにタグを追加します。

1. 

   1. スケジュールオプションを選択します。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-eventbridge-scheduler.html)

1. (オプション) 前のステップで **[定期的なスケジュール]** を選択した場合は、**[時間枠]** セクションで次を実行します。

   1. **[タイムゾーン]** で、タイムゾーンを選択します。

   1. **[開始日時]** で、有効な日付を `YYYY/MM/DD` 形式で入力してから、タイムスタンプを 24 時間 (`hh:mm`) 形式で指定します。

   1. **[終了日時]** で、有効な日付を `YYYY/MM/DD` 形式で入力してから、タイムスタンプを 24 時間 (`hh:mm`) 形式で指定します。

1. [**Next**] を選択します。

1. **[ターゲットを選択]** ページで、EventBridge スケジューラが呼び出す AWS API オペレーションを選択します。

   1. **[AWS Lambda 呼び出し]** を選択します。

   1. **[呼び出し]** セクションで、関数を選択するか、**[新しい Lambda 関数を作成]** を選択します。

   1. (オプション) JSON ペイロードを入力します。ペイロードを入力しない場合、EventBridge スケジューラは空のイベントを使用して関数を呼び出します。

1. [**Next**] を選択します。

1. **[Settings]** (設定) ページで、以下の操作を行います。

   1. スケジュールをオンにするには、**[スケジュールの状態]** で **[スケジュールを有効にする]** をオンに切り替えます。

   1. スケジュールの再試行ポリシーを設定するには、**[再試行ポリシーとデッドレターキュー (DLQ)]** で次を実行します。
      + **[再試行]** を切り替えてオンにします。
      + **[イベントの最大有効期間]** で、EventBridge スケジューラが未処理のイベントを保持しなければならない最大の **[時間]** と **[分]** を入力します。
      + 最大 24 時間です。
      + **[最大再試行回数]** で、ターゲットがエラーを返した場合に EventBridge スケジューラがスケジュールを再試行する最大回数を入力します。

         再試行の最大値は 185 です。

      再試行ポリシーを使用すると、スケジュールがそのターゲットの呼び出しに失敗した場合、EventBridge スケジューラはスケジュールを再実行します。設定されている場合は、スケジュールの最大保持時間と再試行を設定する必要があります。

   1. EventBridge スケジューラが未配信のイベントを保存する場所を選択します。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-eventbridge-scheduler.html)

   1. カスタマーマネージドキーを使用してターゲットの入力を暗号化するには、**[暗号化]** で **[暗号化設定をカスタマイズする (高度)]** を選択します。

      このオプションを選択した場合は、既存の KMS キー ARN を入力するか、**[AWS KMS key を作成]** を選択して AWS KMS コンソールに移動します。EventBridge スケジューラが保管中のデータを暗号化する方法の詳細については、「Amazon EventBridge スケジューラユーザーガイド」の「[保管中の暗号化](https://docs.aws.amazon.com/scheduler/latest/UserGuide/encryption-rest.html)」を参照してください。

   1. EventBridge スケジューラに新しい実行ロールを作成させるには、**[このスケジュールの新しいロールを作成]** を選択します。その後、**[ロール名]** で名前を入力します。このオプションを選択すると、EventBridge スケジューラは、テンプレート化されたターゲットに必要な許可をロールにアタッチします。

1. [**Next**] を選択します。

1.  **[スケジュールの確認と作成]** ページで、スケジュールの詳細を確認します。各セクションで、そのステップに戻って詳細を編集するには、**[編集]** を選択します。

1. **[スケジュールを作成]** を選択します。

   **[スケジュール]** ページで、新規および既存のスケジュールのリストを表示できます。**[ステータス]** 列で、新しいスケジュールが **[有効]** になっていることを確認します。

EventBridge スケジューラが関数を呼び出したことを確認するには、[関数の Amazon CloudWatch ログを確認](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)してください。

## 関連リソース
<a name="using-eventbridge-scheduler-related-resources"></a>

 EventBridge スケジューラに関する詳細については、次を参照してください。
+ [EventBridge スケジューラユーザーガイド](https://docs.aws.amazon.com/scheduler/latest/UserGuide/what-is-scheduler.html)
+ [EventBridge スキーマ API リファレンス](https://docs.aws.amazon.com/scheduler/latest/APIReference/Welcome.html)
+ [EventBridge Scheduler Pricing](https://aws.amazon.com/eventbridge/pricing/#Scheduler)

# で AWS Lambda を使用するAWS IoT
<a name="services-iot"></a>

AWS IoT は、インターネットに接続されたデバイス (センサーなど) と AWS クラウドとの安全な通信を提供します。これにより、複数のデバイスからテレメトリデータを収集して保存および分析できます。

デバイスが AWS のサービスとやり取りするための AWS IoT ルールを作成できます。AWS IoT[ルールエンジン](https://docs.aws.amazon.com/iot/latest/developerguide/iot-rules.html)は、メッセージペイロードからデータを選択して他のサービス (Amazon S3、Amazon DynamoDB、AWS Lambda など) に送信するための SQL べ―スの言語を提供します。AWS の別のサービスやサードパーティーのサービスを呼び出す場合は、Lambda 関数を呼び出すためのルールを定義します。

着信 IoT メッセージによってルールがトリガーされると、AWS IoT は Lambda 関数を[非同期的に](invocation-async.md)呼び出し、IoT メッセージから関数にデータを渡します。

次の例は、温室センサーの湿度値を示しています。**row** 値と **pos** 値は、センサーの位置を識別します。このイベント例は、[AWS IoT ルールチュートリアル](https://docs.aws.amazon.com/iot/latest/developerguide/iot-rules-tutorial.html)の greenhouse タイプに基づいています。

**Example AWS IoT メッセージイベント**  

```
{
    "row" : "10",
    "pos" : "23",
    "moisture" : "75"
}
```

非同期呼び出しで、関数がエラーを返した場合、Lambda はメッセージをキューに入れ、エラーになった呼び出しを[再試行](invocation-retries.md)します。関数を設定するには、[送信先](invocation-async-retain-records.md#invocation-async-destinations)を使用して、関数が処理できなかったイベントを保持します。

Lambda 関数を呼び出すためのアクセス許可を AWS IoT サービスに付与する必要があります。`add-permission` コマンドを使用して、アクセス許可ステートメントを関数のリソースベースのポリシーに追加します。

```
aws lambda add-permission --function-name my-function \
--statement-id iot-events --action "lambda:InvokeFunction" --principal iot.amazonaws.com
```

次のような出力が表示されます。

```
{
    "Statement": "{\"Sid\":\"iot-events\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"iot.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:123456789012:function:my-function\"}"
}
```

AWS IoT で Lambda を使用する方法の詳細については、[AWS Lambda ルールの作成](https://docs.aws.amazon.com/iot/latest/developerguide/iot-lambda-rule.html)を参照してください。

# Lambda を使用して Amazon Kinesis Data Streams からのレコードを処理する
<a name="with-kinesis"></a>

Lambda 関数を使用して、[Amazon Kinesis データストリーム](https://docs.aws.amazon.com/streams/latest/dev/introduction.html)のレコードを処理できます。Lambda 関数を Kinesis Data Streams 共有スループットコンシューマー (標準イテレーター) にマップすることも、[拡張ファンアウト](https://docs.aws.amazon.com/kinesis/latest/dev/enhanced-consumers.html)を使用する専用スループットコンシューマーにマップすることもできます。標準イテレーターの場合、Lambda は HTTP プロトコルを使用して、Kinesis ストリームの各シャードにレコードがあるかどうかをポーリングします。イベントソースマッピングは、シャードの他のコンシューマーと読み取りスループットを共有します。

 Kinesis Data Streams の詳細については、[Reading Data from Amazon Kinesis Data Streams](https://docs.aws.amazon.com/kinesis/latest/dev/building-consumers.html) を参照してください。

**注記**  
Kinesis は、各シャードに対して課金し、拡張ファンアウトの場合はストリームから読み取られたデータに対して課金します。料金の詳細については、[Amazon Kinesis の料金](https://aws.amazon.com/kinesis/data-streams/pricing)を参照してください。

## ポーリングストリームとバッチストリーム
<a name="kinesis-polling-and-batching"></a>

Lambda はデータストリームからレコードを読み取り、関数を、ストリームのレコードを含むイベントと共に[同期的に](invocation-sync.md)呼び出します。Lambda はバッチ単位でレコードを読み取り、関数を呼び出してバッチからレコードを処理します。各バッチには、単一のシャード/データストリームのレコードが含まれます。

Lambda 関数は、データストリームのコンシューマーアプリケーションです。シャードごとに 1 つのレコードのバッチを一度に処理します。Lambda 関数を共有スループットコンシューマー (標準イテレーター) にマップすることも、拡張ファンアウトを使用する専用スループットコンシューマーにマップすることもできます。
+ **標準イテレーター:** Lambda は、レコードの Kinesis ストリームにある各シャードを 1 秒あたり 1 回の基本レートでポーリングします。利用可能なレコードが増えると、Lambda は関数がストリームに追いつくまでバッチを処理し続けます。イベントソースマッピングは、シャードの他のコンシューマーと読み取りスループットを共有します。
+ **拡張ファンアウト:** レイテンシーを最小限に抑え、読み取りスループットを最大化するには、[拡張ファンアウト](https://docs.aws.amazon.com/streams/latest/dev/enhanced-consumers.html)を使用してデータストリームコンシューマーを作成します。拡張ファンアウトを使用するコンシューマーは、ストリームから読み取る他のアプリケーションに影響を及ぼさないように、専用の接続を各シャードに割り当てます。ストリームのコンシューマーは HTTP/2 を使用して、長時間にわたる接続とリクエストヘッダーの圧縮でレコードを Lambda にプッシュすることによってレイテンシーを短縮します。ストリームコンシューマーは、Kinesis [RegisterStreamConsumer](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_RegisterStreamConsumer.html) API を使用して作成できます。

```
aws kinesis register-stream-consumer \
--consumer-name con1 \
--stream-arn arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream
```

次のような出力が表示されます。

```
{
    "Consumer": {
        "ConsumerName": "con1",
        "ConsumerARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream/consumer/con1:1540591608",
        "ConsumerStatus": "CREATING",
        "ConsumerCreationTimestamp": 1540591608.0
    }
}
```

関数がレコードを処理する速度を上げるには、[データストリームにシャードを追加します](https://repost.aws/knowledge-center/kinesis-data-streams-open-shards)。Lambda は、各シャードのレコードを順番に処理します。関数からエラーが返された場合、シャードのさらなるレコードの処理は停止されます。シャードが増えると、一度に処理されるバッチが増え、同時実行のエラーの影響を下げることができます。

同時実行のバッチの合計分を処理できるように関数をスケールアップできない場合は、関数の[クォータ引き上げをリクエスト](https://docs.aws.amazon.com/servicequotas/latest/userguide/request-quota-increase.html)するか、[同時実行数を予約](configuration-concurrency.md)します。

デフォルトで、Lambda はレコードが使用可能になると同時に関数を呼び出します。Lambda がイベントソースから読み取るバッチにレコードが 1 つしかない場合、Lambda は関数に 1 つのレコードしか送信しません。少数のレコードで関数を呼び出さないようにするには、*バッチ処理ウィンドウ*を設定することで、最大 5 分間レコードをバッファリングするようにイベントソースに指示できます。関数を呼び出す前に、Lambda は、完全なバッチを収集する、バッチ処理ウィンドウの期限が切れる、またはバッチが 6 MB のペイロード制限に到達するまでイベントソースからのレコードの読み取りを継続します。詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

Lambda は、設定された[拡張機能](lambda-extensions.md)の完了を待たずに、次のバッチを処理のために送信します。つまり、Lambda がレコードの次のバッチを処理する間も拡張機能を実行し続けることができます。アカウントの[同時実行](lambda-concurrency.md)設定または制限に違反すると、スロットリングの問題が発生する可能性があります。これが潜在的な問題であるかどうかを検出するには、関数を監視し、イベントソースマッピングで予想よりも高い[同時実行メトリクス](monitoring-concurrency.md#general-concurrency-metrics)が表示されているかどうかを確認します。呼び出しの間隔が短いため、Lambda はシャードの数よりも高い同時実行使用量を一時的に報告する場合があります。これは、拡張機能のない Lambda 関数にも当てはまります。

Kinesis データストリームの 1 つのシャードを複数の Lambda 呼び出しで同時に処理するには、[ParallelizationFactor](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-ParallelizationFactor) 設定を構成します。Lambda がシャードからポーリングする同時バッチの数は、1 (デフォルト)～10 の並列化係数で指定できます。例えば、`ParallelizationFactor` を 2 に設定すると、最大 200 個の Lambda 呼び出しを同時に実行して、100 個の Kinesis データシャードを処理できます (ただし、`ConcurrentExecutions` メトリクスに異なる値が表示される場合があります)。これにより、データボリュームが揮発性で `IteratorAge` が高いときに処理のスループットをスケールアップすることができます。シャードごとの同時実行バッチの数を増やしても、Lambda はパーティションキーレベルで順序立った処理を確実に行います。

Kinesis 集約で `ParallelizationFactor` を使用することもできます。イベントソースマッピングの動作は、[拡張ファンアウト](https://docs.aws.amazon.com/streams/latest/dev/enhanced-consumers.html)を使用しているかどうかによって異なります。
+ **拡張ファンアウトなし**: 集約イベント内のすべてのイベントは、同じパーティションキーを持つ必要があります。パーティションキーは、集約イベントのパーティションキーとも一致する必要があります。集約イベント内のイベントに異なるパーティションキーがある場合、Lambda ではパーティションキーによるイベントが順序通りに処理されないことがあります。
+ **拡張ファンアウトあり**: まず、Lambda は集約イベントを個々のイベントにデコードします。集約イベントには、含まれるイベントとは異なるパーティションキーを設定できます。ただし、パーティションキーに一致しないイベントは[削除され、失われ](https://github.com/awslabs/kinesis-aggregation/blob/master/potential_data_loss.md)ます。Lambda ではこれらのイベントは処理されず、設定された障害時の送信先には送信されません。

## イベントの例
<a name="services-kinesis-event-example"></a>

**Example**  

```
{
    "Records": [
        {
            "kinesis": {
                "kinesisSchemaVersion": "1.0",
                "partitionKey": "1",
                "sequenceNumber": "49590338271490256608559692538361571095921575989136588898",
                "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
                "approximateArrivalTimestamp": 1545084650.987
            },
            "eventSource": "aws:kinesis",
            "eventVersion": "1.0",
            "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898",
            "eventName": "aws:kinesis:record",
            "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role",
            "awsRegion": "us-east-2",
            "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream"
        },
        {
            "kinesis": {
                "kinesisSchemaVersion": "1.0",
                "partitionKey": "1",
                "sequenceNumber": "49590338271490256608559692540925702759324208523137515618",
                "data": "VGhpcyBpcyBvbmx5IGEgdGVzdC4=",
                "approximateArrivalTimestamp": 1545084711.166
            },
            "eventSource": "aws:kinesis",
            "eventVersion": "1.0",
            "eventID": "shardId-000000000006:49590338271490256608559692540925702759324208523137515618",
            "eventName": "aws:kinesis:record",
            "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role",
            "awsRegion": "us-east-2",
            "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream"
        }
    ]
}
```

# Lambda を使用した Amazon Kinesis Data Streams レコードの処理
<a name="services-kinesis-create"></a>

Lambda を使用して Amazon Kinesis Data Streams レコードを処理するには、Lambda イベントソースマッピングを作成します。Lambda 関数は標準イテレーターか、拡張ファンアウトコンシューマーにマッピングすることができます。詳細については、「[ポーリングストリームとバッチストリーム](with-kinesis.md#kinesis-polling-and-batching)」を参照してください。

## Kinesis イベントソースマッピングを作成する
<a name="services-kinesis-eventsourcemapping"></a>

データストリームからのレコードを使用して Lambda 関数を呼び出すには、[イベントソースマッピング](invocation-eventsourcemapping.md)を作成します。複数のイベントソースマッピングを作成することで、複数の Lambda 関数で同じデータを処理したり、1 つの関数で複数のデータストリームの項目を処理したりできます。複数のストリームから項目を処理する場合、各バッチには 1 つのシャードまたはストリームのレコードのみが含まれます。

別の AWS アカウント のストリームからのレコードを処理するようにイベント ソース マッピングを構成できます。詳細については[クロスアカウントのイベントソースマッピングの作成](#services-kinesis-eventsourcemapping-cross-account)を参照してください。

イベントソースマッピングを作成する前に、Kinesis データストリームから読み取るためのアクセス許可を Lambda 関数に付与する必要があります。Lambda には、Kinesis データストリームに関連するリソースを管理するために次のアクセス許可が必要です。
+ [kinesis:DescribeStream](https://docs.aws.amazon.com/lambda/latest/api/API_DescribeStream.html)
+ [kinesis:DescribeStreamSummary](https://docs.aws.amazon.com/lambda/latest/api/API_DescribeStreamSummary.html)
+ [kinesis:GetRecords](https://docs.aws.amazon.com/lambda/latest/api/API_GetRecords.html)
+ [kinesis:GetShardIterator](https://docs.aws.amazon.com/lambda/latest/api/API_GetShardIterator.html)
+ [kinesis:ListShards](https://docs.aws.amazon.com/lambda/latest/api/API_ListShards.html)
+ [kinesis:SubscribeToShard](https://docs.aws.amazon.com/lambda/latest/api/API_SubscribeToShard.html)

AWS マネージドポリシー [AWSLambdaKinesisExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaKinesisExecutionRole.html) には、これらのアクセス許可が含まれています。次の手順の説明に従って、この管理ポリシーを関数に追加します。

**注記**  
Kinesis のイベントソースマッピングを作成および管理するための `kinesis:ListStreams` アクセス許可は必要ありません。ただし、コンソールでイベントソースマッピングを作成し、このアクセス許可がない場合、ドロップダウンリストから Kinesis ストリームを選択できず、コンソールにエラーが表示されます。イベントソースマッピングを作成するには、ストリームの Amazon リソースネーム (ARN) を手動で入力する必要があります。
Lambda は、失敗した呼び出しを再試行する際に `kinesis:GetRecords` および `kinesis:GetShardIterator` API 呼び出しを行います。

------
#### [ AWS マネジメントコンソール ]

**関数に Kinesis アクセス許可を追加するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、関数を選択します。

1. **[構成]** タブで、**[アクセス許可]** を選択します。

1. **[実行ロール]** ペインの **[ロール名]** で、関数の実行ロールへのリンクを選択します。このリンクを選択すると、IAM コンソールでそのロールのページが開きます。

1. **[アクセス許可ポリシー]** ペインで、**[アクセス許可を追加]** を選択し、**[ポリシーをアタッチ]** を続けて選択します。

1. [検索] フィールドに **AWSLambdaKinesisExecutionRole** を入力します。

1. ポリシーの名前の横にあるチェックボックスを選択し、**[アクセス許可を追加]** を選択します。

------
#### [ AWS CLI ]

**関数に Kinesis アクセス許可を追加するには**
+ 次の CLI コマンドを実行して、`AWSLambdaKinesisExecutionRole` ポリシーを関数の実行ロールに追加します。

  ```
  aws iam attach-role-policy \
  --role-name MyFunctionRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaKinesisExecutionRole
  ```

------
#### [ AWS SAM ]

**関数に Kinesis アクセス許可を追加するには**
+ 関数の定義で、次の例に示すように `Policies` プロパティを追加します。

  ```
  Resources:
    MyFunction:
      Type: AWS::Serverless::Function
      Properties:
        CodeUri: ./my-function/
        Handler: index.handler
        Runtime: nodejs24.x
        Policies:
          - AWSLambdaKinesisExecutionRole
  ```

------

必要なアクセス許可を設定した後、イベントソースマッピングを作成します。

------
#### [ AWS マネジメントコンソール ]

**Kinesis イベントソースマッピングを作成するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、関数を選択します。

1. **[関数の概要]** ペインで、**[トリガーを追加]** を選択します。

1. **[トリガー設定]** で、ソースとして **[Kinesis]** を選択します。

1. イベントソースマッピングを作成する Kinesis ストリームを選択し、オプションでストリームのコンシューマーを選択します。

1. (オプション) イベントソースマッピングの**バッチサイズ** 、**開始位置**、**バッチウィンドウ**を編集します。

1. **[Add]** (追加) を選択します。

コンソールからイベントソースマッピングを作成する場合は、IAM ロールには [kinesis:ListStreams](https://docs.aws.amazon.com/lambda/latest/api/API_ListStreams.html) 権限と [kinesis:ListStreamConsumers](https://docs.aws.amazon.com/lambda/latest/api/API_ListStreamConsumers.html) 権限が必要です。

------
#### [ AWS CLI ]

**Kinesis イベントソースマッピングを作成するには**
+ 次の CLI コマンドを実行して、Kinesis イベントソースマッピングを作成します。ユースケースに応じて、独自のバッチサイズと開始位置を選択します。

  ```
  aws lambda create-event-source-mapping \
  --function-name MyFunction \
  --event-source-arn arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream \
  --starting-position LATEST \
  --batch-size 100
  ```

バッチ処理ウィンドウを指定するには、`--maximum-batching-window-in-seconds` オプションを追加します。このパラメータおよびその他のパラメータの使用の詳細については、「*AWS CLI コマンドリファレンス*」の「[create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html)」を参照してください。

------
#### [ AWS SAM ]

**Kinesis イベントソースマッピングを作成するには**
+ 関数の定義で、次の例に示すように `KinesisEvent` プロパティを追加します。

  ```
  Resources:
    MyFunction:
      Type: AWS::Serverless::Function
      Properties:
        CodeUri: ./my-function/
        Handler: index.handler
        Runtime: nodejs24.x
        Policies:
          - AWSLambdaKinesisExecutionRole
        Events:
          KinesisEvent:
            Type: Kinesis
            Properties:
              Stream: !GetAtt MyKinesisStream.Arn
              StartingPosition: LATEST
              BatchSize: 100
  
    MyKinesisStream:
      Type: AWS::Kinesis::Stream
      Properties:
        ShardCount: 1
  ```

AWS SAM で Kinesis Data Streams のイベントソースマッピングを作成する方法の詳細については、「*AWS Serverless Application Model デベロッパーガイド*」の「[Kinesis](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-kinesis.html)」を参照してください。

------

## ポーリングとストリームの開始位置
<a name="services-kinesis-stream-start-pos"></a>

イベントソースマッピングの作成時および更新時のストリームのポーリングは、最終的に一貫性があることに注意してください。
+ イベントソースマッピングの作成時、ストリームからのイベントのポーリングが開始されるまでに数分かかる場合があります。
+ イベントソースマッピングの更新時、ストリームからのイベントのポーリングが停止および再開されるまでに数分かかる場合があります。

つまり、`LATEST` をストリームの開始位置として指定すると、イベントソースマッピングの作成または更新中にイベントを見逃す可能性があります。イベントを見逃さないようにするには、ストリームの開始位置を `TRIM_HORIZON` または `AT_TIMESTAMP` として指定します。

## クロスアカウントのイベントソースマッピングの作成
<a name="services-kinesis-eventsourcemapping-cross-account"></a>

[Amazon Kinesis Data Streams](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html) は、リソースベースのポリシーをサポートします。このため、別のアカウントの Lambda 関数を使用して AWS アカウント のストリームに取り込まれたデータを処理できます。

別の AWS アカウント の Kinesis ストリームを使用して Lambda 関数のイベントソースマッピングを作成するには、リソースベースのポリシーを使用してストリームを設定し、Lambda 関数に項目を読み取るアクセス許可を付与する必要があります。クロスアカウントアクセスを許可するようにストリームを設定する方法については、「*Amazon Kinesis Streams デベロッパーガイド*」の「[クロスアカウント AWS Lambda 関数とアクセスを共有する](https://docs.aws.amazon.com/streams/latest/dev/resource-based-policy-examples.html#Resource-based-policy-examples-lambda)」を参照してください。

Lambda 関数に必要なアクセス許可を付与するリソースベースのポリシーでストリームを設定したら、前のセクションで説明した方法のいずれかを使用してイベントソースマッピングを作成します。

Lambda コンソールでイベントソースマッピングを作成する場合は、ストリームの ARN を入力フィールドに直接貼り付けます。ストリームにコンシューマーを指定する場合、コンシューマーの ARN を貼り付けると、ストリームフィールドが自動的に入力されます。

# Kinesis Data Streams と Lambda を使用した部分的なバッチレスポンスの設定
<a name="services-kinesis-batchfailurereporting"></a>

イベントソースからストリーミングデータを使用および処理する場合、デフォルトでは、バッチが完全に成功した場合にのみ、バッチの最大シーケンス番号に Lambda チェックポイントが設定されます。Lambda は、他のすべての結果を完全な失敗として扱い、再試行の上限までバッチの処理を再試行します。ストリームからのバッチの処理中に部分的な成功を許可するには、`ReportBatchItemFailures`をオンにします 。部分的な成功を許可すると、レコードの再試行回数を減らすことができますが、成功したレコードの再試行の可能性を完全に妨げるわけではありません。

`ReportBatchItemFailures` をオンにするには、列挙値 **ReportBatchItemFailures** を [FunctionResponseTypes](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-FunctionResponseTypes) リストに含めます。このリストは、関数で有効になっているレスポンスタイプを示します。このリストは、イベントソースマッピングを[作成](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)または[更新](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)するときに設定できます。

**注記**  
関数コードが部分的なバッチ処理失敗レスポンスを返しても、イベントソースマッピングに対して `ReportBatchItemFailures` 機能が明示的に有効化されていなければ、Lambda はこれらのレスポンスを処理しません。

## レポートの構文
<a name="streams-batchfailurereporting-syntax"></a>

バッチアイテムの失敗に関するレポートを設定する場合、`StreamsEventResponse` クラスはバッチアイテムの失敗のリストとともに返されます。`StreamsEventResponse`オブジェクトを使用して、バッチ処理で最初に失敗したレコードのシーケンス番号を返すことができます。また、正しいレスポンスシンタックスを使用して、独自のカスタムクラスを作成することもできます。次の JSON 構造体は、必要な応答構文を示しています。

```
{ 
  "batchItemFailures": [ 
        {
            "itemIdentifier": "<SequenceNumber>"
        }
    ]
}
```

**注記**  
`batchItemFailures` 配列に複数の項目が含まれている場合、Lambda はシーケンス番号が最も小さいレコードをチェックポイントとして使用します。その後、Lambda はそのチェックポイントからすべてのレコードを再試行します。

## 成功条件と失敗の条件
<a name="streams-batchfailurereporting-conditions"></a>

次のいずれかを返すと、Lambda はバッチを完全な成功として処理します:
+ 空の`batchItemFailure`リストです。
+ null の `batchItemFailure` リスト
+ 空の `EventResponse`
+ ヌル `EventResponse`

次のいずれかを返すと、Lambda はバッチを完全な失敗として処理します:
+ 空の文字列`itemIdentifier`
+ ヌル `itemIdentifier`
+ `itemIdentifier`間違えているキー名

Lambda は、再試行戦略に基づいて失敗を再試行します。

## バッチを２分割します
<a name="streams-batchfailurereporting-bisect"></a>

呼び出しが失敗し、`BisectBatchOnFunctionError` オンになっている場合、バッチは`ReportBatchItemFailures`設定に関係なく２分割されます。

部分的なバッチ成功レスポンスを受信し、`BisectBatchOnFunctionError` と `ReportBatchItemFailures` の両方がオンになっている場合、バッチは返されたシーケンス番号で 2 分割され、Lambda は残りのレコードのみを再試行します。

部分的なバッチレスポンスロジックの実装を簡素化するには、Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)を使用することを検討してください。これらの複雑さが自動的に処理されます。

バッチで失敗したメッセージ ID のリストを返す関数コードの例を次に示します。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
﻿using System.Text;
using System.Text.Json.Serialization;
using Amazon.Lambda.Core;
using Amazon.Lambda.KinesisEvents;
using AWS.Lambda.Powertools.Logging;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace KinesisIntegration;

public class Function
{
    // Powertools Logger requires an environment variables against your function
    // POWERTOOLS_SERVICE_NAME
    [Logging(LogEvent = true)]
    public async Task<StreamsEventResponse> FunctionHandler(KinesisEvent evnt, ILambdaContext context)
    {
        if (evnt.Records.Count == 0)
        {
            Logger.LogInformation("Empty Kinesis Event received");
            return new StreamsEventResponse();
        }

        foreach (var record in evnt.Records)
        {
            try
            {
                Logger.LogInformation($"Processed Event with EventId: {record.EventId}");
                string data = await GetRecordDataAsync(record.Kinesis, context);
                Logger.LogInformation($"Data: {data}");
                // TODO: Do interesting work based on the new data
            }
            catch (Exception ex)
            {
                Logger.LogError($"An error occurred {ex.Message}");
                /* Since we are working with streams, we can return the failed item immediately.
                   Lambda will immediately begin to retry processing from this failed item onwards. */
                return new StreamsEventResponse
                {
                    BatchItemFailures = new List<StreamsEventResponse.BatchItemFailure>
                    {
                        new StreamsEventResponse.BatchItemFailure { ItemIdentifier = record.Kinesis.SequenceNumber }
                    }
                };
            }
        }
        Logger.LogInformation($"Successfully processed {evnt.Records.Count} records.");
        return new StreamsEventResponse();
    }

    private async Task<string> GetRecordDataAsync(KinesisEvent.Record record, ILambdaContext context)
    {
        byte[] bytes = record.Data.ToArray();
        string data = Encoding.UTF8.GetString(bytes);
        await Task.CompletedTask; //Placeholder for actual async work
        return data;
    }
}

public class StreamsEventResponse
{
    [JsonPropertyName("batchItemFailures")]
    public IList<BatchItemFailure> BatchItemFailures { get; set; }
    public class BatchItemFailure
    {
        [JsonPropertyName("itemIdentifier")]
        public string ItemIdentifier { get; set; }
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main

import (
	"context"
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(ctx context.Context, kinesisEvent events.KinesisEvent) (map[string]interface{}, error) {
	batchItemFailures := []map[string]interface{}{}

	for _, record := range kinesisEvent.Records {
		curRecordSequenceNumber := ""

		// Process your record
		if /* Your record processing condition here */ {
			curRecordSequenceNumber = record.Kinesis.SequenceNumber
		}

		// Add a condition to check if the record processing failed
		if curRecordSequenceNumber != "" {
			batchItemFailures = append(batchItemFailures, map[string]interface{}{"itemIdentifier": curRecordSequenceNumber})
		}
	}

	kinesisBatchResponse := map[string]interface{}{
		"batchItemFailures": batchItemFailures,
	}
	return kinesisBatchResponse, nil
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class ProcessKinesisRecords implements RequestHandler<KinesisEvent, StreamsEventResponse> {

    @Override
    public StreamsEventResponse handleRequest(KinesisEvent input, Context context) {

        List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>();
        String curRecordSequenceNumber = "";

        for (KinesisEvent.KinesisEventRecord kinesisEventRecord : input.getRecords()) {
            try {
                //Process your record
                KinesisEvent.Record kinesisRecord = kinesisEventRecord.getKinesis();
                curRecordSequenceNumber = kinesisRecord.getSequenceNumber();

            } catch (Exception e) {
                /* Since we are working with streams, we can return the failed item immediately.
                   Lambda will immediately begin to retry processing from this failed item onwards. */
                batchItemFailures.add(new StreamsEventResponse.BatchItemFailure(curRecordSequenceNumber));
                return new StreamsEventResponse(batchItemFailures);
            }
        }
       
       return new StreamsEventResponse(batchItemFailures);   
    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/blob/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Javascript を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const record of event.Records) {
    try {
      console.log(`Processed Kinesis Event - EventID: ${record.eventID}`);
      const recordData = await getRecordDataAsync(record.kinesis);
      console.log(`Record Data: ${recordData}`);
      // TODO: Do interesting work based on the new data
    } catch (err) {
      console.error(`An error occurred ${err}`);
      /* Since we are working with streams, we can return the failed item immediately.
            Lambda will immediately begin to retry processing from this failed item onwards. */
      return {
        batchItemFailures: [{ itemIdentifier: record.kinesis.sequenceNumber }],
      };
    }
  }
  console.log(`Successfully processed ${event.Records.length} records.`);
  return { batchItemFailures: [] };
};

async function getRecordDataAsync(payload) {
  var data = Buffer.from(payload.data, "base64").toString("utf-8");
  await Promise.resolve(1); //Placeholder for actual async work
  return data;
}
```
TypeScript を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import {
  KinesisStreamEvent,
  Context,
  KinesisStreamHandler,
  KinesisStreamRecordPayload,
  KinesisStreamBatchResponse,
} from "aws-lambda";
import { Buffer } from "buffer";
import { Logger } from "@aws-lambda-powertools/logger";

const logger = new Logger({
  logLevel: "INFO",
  serviceName: "kinesis-stream-handler-sample",
});

export const functionHandler: KinesisStreamHandler = async (
  event: KinesisStreamEvent,
  context: Context
): Promise<KinesisStreamBatchResponse> => {
  for (const record of event.Records) {
    try {
      logger.info(`Processed Kinesis Event - EventID: ${record.eventID}`);
      const recordData = await getRecordDataAsync(record.kinesis);
      logger.info(`Record Data: ${recordData}`);
      // TODO: Do interesting work based on the new data
    } catch (err) {
      logger.error(`An error occurred ${err}`);
      /* Since we are working with streams, we can return the failed item immediately.
            Lambda will immediately begin to retry processing from this failed item onwards. */
      return {
        batchItemFailures: [{ itemIdentifier: record.kinesis.sequenceNumber }],
      };
    }
  }
  logger.info(`Successfully processed ${event.Records.length} records.`);
  return { batchItemFailures: [] };
};

async function getRecordDataAsync(
  payload: KinesisStreamRecordPayload
): Promise<string> {
  var data = Buffer.from(payload.data, "base64").toString("utf-8");
  await Promise.resolve(1); //Placeholder for actual async work
  return data;
}
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\Kinesis\KinesisEvent;
use Bref\Event\Handler as StdHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler implements StdHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws JsonException
     * @throws \Bref\Event\InvalidLambdaEvent
     */
    public function handle(mixed $event, Context $context): array
    {
        $kinesisEvent = new KinesisEvent($event);
        $this->logger->info("Processing records");
        $records = $kinesisEvent->getRecords();

        $failedRecords = [];
        foreach ($records as $record) {
            try {
                $data = $record->getData();
                $this->logger->info(json_encode($data));
                // TODO: Do interesting work based on the new data
            } catch (Exception $e) {
                $this->logger->error($e->getMessage());
                // failed processing the record
                $failedRecords[] = $record->getSequenceNumber();
            }
        }
        $totalRecords = count($records);
        $this->logger->info("Successfully processed $totalRecords records");

        // change format for the response
        $failures = array_map(
            fn(string $sequenceNumber) => ['itemIdentifier' => $sequenceNumber],
            $failedRecords
        );

        return [
            'batchItemFailures' => $failures
        ];
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def handler(event, context):
    records = event.get("Records")
    curRecordSequenceNumber = ""
    
    for record in records:
        try:
            # Process your record
            curRecordSequenceNumber = record["kinesis"]["sequenceNumber"]
        except Exception as e:
            # Return failed record's sequence number
            return {"batchItemFailures":[{"itemIdentifier": curRecordSequenceNumber}]}

    return {"batchItemFailures":[]}
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用して Lambda で Kinesis バッチアイテム失敗のレポートをします。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
require 'aws-sdk'

def lambda_handler(event:, context:)
  batch_item_failures = []

  event['Records'].each do |record|
    begin
      puts "Processed Kinesis Event - EventID: #{record['eventID']}"
      record_data = get_record_data_async(record['kinesis'])
      puts "Record Data: #{record_data}"
      # TODO: Do interesting work based on the new data
    rescue StandardError => err
      puts "An error occurred #{err}"
      # Since we are working with streams, we can return the failed item immediately.
      # Lambda will immediately begin to retry processing from this failed item onwards.
      return { batchItemFailures: [{ itemIdentifier: record['kinesis']['sequenceNumber'] }] }
    end
  end

  puts "Successfully processed #{event['Records'].length} records."
  { batchItemFailures: batch_item_failures }
end

def get_record_data_async(payload)
  data = Base64.decode64(payload['data']).force_encoding('utf-8')
  # Placeholder for actual async work
  sleep(1)
  data
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用した Lambda での Kinesis バッチアイテム失敗のレポート。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::{
    event::kinesis::KinesisEvent,
    kinesis::KinesisEventRecord,
    streams::{KinesisBatchItemFailure, KinesisEventResponse},
};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

async fn function_handler(event: LambdaEvent<KinesisEvent>) -> Result<KinesisEventResponse, Error> {
    let mut response = KinesisEventResponse {
        batch_item_failures: vec![],
    };

    if event.payload.records.is_empty() {
        tracing::info!("No records found. Exiting.");
        return Ok(response);
    }

    for record in &event.payload.records {
        tracing::info!(
            "EventId: {}",
            record.event_id.as_deref().unwrap_or_default()
        );

        let record_processing_result = process_record(record);

        if record_processing_result.is_err() {
            response.batch_item_failures.push(KinesisBatchItemFailure {
                item_identifier: record.kinesis.sequence_number.clone(),
            });
            /* Since we are working with streams, we can return the failed item immediately.
            Lambda will immediately begin to retry processing from this failed item onwards. */
            return Ok(response);
        }
    }

    tracing::info!(
        "Successfully processed {} records",
        event.payload.records.len()
    );

    Ok(response)
}

fn process_record(record: &KinesisEventRecord) -> Result<(), Error> {
    let record_data = std::str::from_utf8(record.kinesis.data.as_slice());

    if let Some(err) = record_data.err() {
        tracing::error!("Error: {}", err);
        return Err(Error::from(err));
    }

    let record_data = record_data.unwrap_or_default();

    // do something interesting with the data
    tracing::info!("Data: {}", record_data);

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

## Powertools for AWS Lambda バッチプロセッサを使用する
<a name="services-kinesis-batchfailurereporting-powertools"></a>

Powertools for AWS Lambda のバッチプロセッサユーティリティは、部分的なバッチレスポンスロジックを自動的に処理するため、バッチ障害レポートの実装の複雑さが軽減されます。バッチプロセッサを使用した例を次に示します。

**Python**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した Kinesis Data Streams ストリームレコードの処理。  

```
import json
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes import KinesisEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

processor = BatchProcessor(event_type=EventType.KinesisDataStreams)
logger = Logger()

def record_handler(record):
    logger.info(record)
    # Your business logic here
    # Raise an exception to mark this record as failed
    
def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event, 
        record_handler=record_handler, 
        processor=processor,
        context=context
    )
```

**TypeScript**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.aws.amazon.com/powertools/typescript/latest/features/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した Kinesis Data Streams ストリームレコードの処理。  

```
import { BatchProcessor, EventType, processPartialResponse } from '@aws-lambda-powertools/batch';
import { Logger } from '@aws-lambda-powertools/logger';
import type { KinesisEvent, Context } from 'aws-lambda';

const processor = new BatchProcessor(EventType.KinesisDataStreams);
const logger = new Logger();

const recordHandler = async (record: any): Promise<void> => {
    logger.info('Processing record', { record });
    // Your business logic here
    // Throw an error to mark this record as failed
};

export const handler = async (event: KinesisEvent, context: Context) => {
    return processPartialResponse(event, recordHandler, processor, {
        context,
    });
};
```

**Java**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.powertools.aws.dev/lambda/java/latest/utilities/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した Kinesis Data Streams ストリームレコードの処理。  

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse;
import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder;
import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler;

public class KinesisStreamBatchHandler implements RequestHandler<KinesisEvent, StreamsEventResponse> {

    private final BatchMessageHandler<KinesisEvent, StreamsEventResponse> handler;

    public KinesisStreamBatchHandler() {
        handler = new BatchMessageHandlerBuilder()
                .withKinesisBatchHandler()
                .buildWithRawMessageHandler(this::processMessage);
    }

    @Override
    public StreamsEventResponse handleRequest(KinesisEvent kinesisEvent, Context context) {
        return handler.processBatch(kinesisEvent, context);
    }

    private void processMessage(KinesisEvent.KinesisEventRecord kinesisEventRecord, Context context) {
        // Process the stream record
    }
}
```

**.NET**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.aws.amazon.com/powertools/dotnet/utilities/batch-processing/)を参照してください。
AWS Lambda バッチプロセッサを使用した Kinesis Data Streams ストリームレコードの処理。  

```
using System;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.KinesisEvents;
using Amazon.Lambda.Serialization.SystemTextJson;
using AWS.Lambda.Powertools.BatchProcessing;

[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]

namespace HelloWorld;

public class OrderEvent
{
    public string? OrderId { get; set; }
    public string? CustomerId { get; set; }
    public decimal Amount { get; set; }
    public DateTime OrderDate { get; set; }
}

internal class TypedKinesisRecordHandler : ITypedRecordHandler<OrderEvent> 
{
    public async Task<RecordHandlerResult> HandleAsync(OrderEvent orderEvent, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(orderEvent.OrderId)) 
        {
            throw new ArgumentException("Order ID is required");
        }

        return await Task.FromResult(RecordHandlerResult.None); 
    }
}

public class Function
{
    [BatchProcessor(TypedRecordHandler = typeof(TypedKinesisRecordHandler))]
    public BatchItemFailuresResponse HandlerUsingTypedAttribute(KinesisEvent _)
    {
        return TypedKinesisStreamBatchProcessor.Result.BatchItemFailuresResponse; 
    }
}
```

# Lambda で Kinesis Data Streams イベントソースの破棄されたバッチレコードを保持する
<a name="kinesis-on-failure-destination"></a>

Kinesis イベントソースマッピングのエラー処理は、エラーが関数の呼び出し前に発生するか、関数の呼び出し中に発生するかによって異なります。
+ **呼び出し前:** スロットリングまたはその他の問題によって Lambda イベントソースマッピングが関数を呼び出すことができない場合、レコードの有効期限が切れるか、イベントソースマッピングで設定された最大有効期間 ([MaximumRecordAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRecordAgeInSeconds)) を超えるまで再試行します。
+ **呼び出し中:** 関数は呼び出されたがエラーが返された場合、Lambda はレコードの有効期限が切れるか、最大有効期間 ([MaximumRecordAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRecordAgeInSeconds)) を超えるか、設定された再試行クォータ ([MaximumRetryAttempts](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRetryAttempts)) に達するまで再試行します。関数エラーの場合、[BisectBatchOnFunctionError](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-response-BisectBatchOnFunctionError) を設定することもできます。これは、失敗したバッチを 2 つの小さなバッチに分割し、不良レコードを分離してタイムアウトを回避します。バッチを分割しても、再試行クォータは消費されません。

エラー処理の対策に失敗すると、Lambda はレコードを破棄し、ストリームからのバッチ処理を継続します。デフォルト設定では、不良レコードによって、影響を受けるシャードでの処理が最大 1 週間ブロックされる可能性があります。これを回避するには、関数のイベントソースマッピングを、適切な再試行回数と、ユースケースに適合する最大レコード経過時間で設定します。

## 失敗した呼び出しの送信先の設定
<a name="kinesis-on-failure-destination-console"></a>

失敗したイベントソースマッピング呼び出しの記録を保持するには、関数のイベントソースマッピングに送信先を追加します。送信先に送られる各レコードは、失敗した呼び出しに関するメタデータを含む JSON ドキュメントです。Amazon S3 送信先の場合、Lambda はメタデータと共に呼び出しレコード全体を送信します。任意の Amazon SNS トピック、Amazon SQS キュー、Amazon S3 バケット、または Kafka を送信先として設定できます。

Amazon S3 送信先を使用すると、[Amazon S3 イベント通知](https://docs.aws.amazon.com/)機能を使用して、オブジェクトが送信先 S3 バケットにアップロードされたときに通知を受け取ることができます。また、S3 イベント通知を設定して、失敗したバッチに対して別の Lambda 関数を呼び出し、自動処理を実行することもできます。

実行ロールには、送信先に対するアクセス許可が必要です。
+ **SQS 送信先の場合:** [sqs:SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)
+ **SNS 送信先の場合:** [sns:Publish](https://docs.aws.amazon.com/sns/latest/api/API_Publish.html)
+ **S3 送信先の場合:** [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) および [s3:ListBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/ListObjectsV2.html)
+ **Kafka 送信先の場合:** [kafka-cluster:WriteData](https://docs.aws.amazon.com/msk/latest/developerguide/kafka-actions.html)

Kafka トピックは、Kafka イベントソースマッピングの障害発生時の送信先として設定できます。再試行回数を超えた後、またはレコードが最大経過時間を超えた後に Lambda がレコードを処理できなくなると、Lambda は失敗したレコードを指定された Kafka トピックに送信して、後で処理します。「[Kafka トピックを障害発生時の送信先として使用する](kafka-on-failure-destination.md)」を参照してください。

S3 送信先に対して独自の KMS キーを使用した暗号化を有効にしている場合、関数の実行ロールには [kms:GenerateDataKey](https://docs.aws.amazon.com/kms/latest/APIReference/API_GenerateDataKey.html) を呼び出すためのアクセス許可も必要です。KMS キーと S3 バケットの送信先が Lambda 関数および実行ロールとは異なるアカウントにある場合は、kms:GenerateDataKey を許可するように実行ロールを信頼するように KMS キーを設定します。

障害発生時の送信先をコンソールを使用して設定するには、以下の手順に従います。

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. [**機能の概要 **] で、[**送信先を追加 **] を選択します。

1. **[ソース]** には、**[イベントソースマッピング呼び出し]** を選択します。

1. **[イベントソースマッピング]** では、この関数用に設定されているイベントソースを選択します。

1. **[条件]** には **[失敗時]** を選択します。イベントソースマッピング呼び出しでは、これが唯一受け入れられる条件です。

1. **[送信先タイプ]** では、Lambda が呼び出しレコードを送信する送信先タイプを選択します。

1. [**送信先**] で、リソースを選択します。

1. **[保存]** を選択します。

AWS Command Line Interface (AWS CLI) を使用して障害発生時の送信先を設定することもできます。例えば、次の [create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) コマンドは、SQS を障害発生時の送信先として持つイベントソースマッピングを `MyFunction` に追加します。

```
aws lambda create-event-source-mapping \
--function-name "MyFunction" \
--event-source-arn arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream \
--destination-config '{"OnFailure": {"Destination": "arn:aws:sqs:us-east-1:123456789012:dest-queue"}}'
```

次の [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドは、2 回の再試行後、またはレコードが 1 時間以上経過した場合に失敗した呼び出しレコードを SNS 送信先に送信するように、イベントソースマッピングを更新します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--maximum-retry-attempts 2 \
--maximum-record-age-in-seconds 3600 \
--destination-config '{"OnFailure": {"Destination": "arn:aws:sns:us-east-1:123456789012:dest-topic"}}'
```

更新された設定は非同期に適用され、プロセスが完了するまで出力に反映されません。現在のステータスを表示するには、[get-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html) コマンドを使用します。

送信先を削除するには、`destination-config` パラメータの引数として空の文字列を指定します。

```
aws lambda update-event-source-mapping \
--uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
--destination-config '{"OnFailure": {"Destination": ""}}'
```

### Amazon S3 送信先のセキュリティのベストプラクティス
<a name="kinesis-s3-destination-security"></a>

関数の設定から送信先を削除せずに、送信先として設定された S3 バケットを削除すると、セキュリティリスクが発生する可能性があります。別のユーザーが送信先バケットの名前を知っている場合は、その AWS アカウントでバケットを再作成できます。失敗した呼び出しのレコードがそのバケットに送信され、関数からのデータが公開される可能性があります。

**警告**  
関数からの呼び出しレコードを別の AWS アカウントの S3 バケットに送信できないようにするには、`s3:PutObject` アクセス許可を自分アカウントのバケットに制限する条件を関数の実行ロールに追加します。

次の例は、関数の `s3:PutObject` アクセス許可を自分のアカウントのバケットに制限する IAM ポリシーを示しています。このポリシーは、送信先として S3 バケットを使用するために必要な `s3:ListBucket` アクセス許可も Lambda に付与します。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "S3BucketResourceAccountWrite",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::*/*",
                "arn:aws:s3:::*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:ResourceAccount": "111122223333"
                }
            }
        }
    ]
}
```

AWS マネジメントコンソールまたは AWS CLI を使用して、関数の実行ロールにアクセス許可ポリシーを追加する場合は、次の手順を参照してください。

------
#### [ Console ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 実行ロールを変更する Lambda 関数を選択します。

1. **[構成]** タブで、**[アクセス許可]** を選択します。

1. **[実行ロール]** タブで、関数の **[ロール名]** を選択して、ロールの IAM コンソールページを開きます。

1. 次の手順を実行してアクセス許可ポリシーをロールに追加します。

   1. **[アクセス許可ポリシー]** ペインで、**[アクセス許可の追加]**、**[インラインポリシーを作成]** を選択します。

   1. **ポリシーエディタ**で、**[JSON]** を選択します。

   1. 追加するポリシーをエディタに貼り付け (既存の JSON を置き換える)、**[次へ]** を選択します。

   1. **[ポリシーの詳細]** で **[ポリシー名]** を入力します。

   1. [**Create policy**] (ポリシーの作成) を選択します。

------
#### [ AWS CLI ]

**関数の実行ロールにアクセス許可ポリシーを追加するには (CLI)**

1. 必要なアクセス許可を持つ JSON ポリシードキュメントを作成し、ローカルディレクトリに保存します。

1. IAM `put-role-policy` CLI コマンドを使用して、関数の実行ロールにアクセス許可を追加します。JSON ポリシードキュメントを保存したディレクトリから次のコマンドを実行して、ロール名、ポリシー名、ポリシードキュメントを独自の値に置き換えます。

   ```
   aws iam put-role-policy \
   --role-name my_lambda_role \
   --policy-name LambdaS3DestinationPolicy \
   --policy-document file://my_policy.json
   ```

------

### Amazon SNS および Amazon SQS の呼び出しレコードの例
<a name="kinesis-on-failure-destination-example-sns-sqs"></a>

以下の例は、Kinesis イベントソース呼び出しが失敗した場合に Lambda が SQS キューまたは SNS トピックに送信する内容を示しています。Lambda はこれらの送信先タイプにメタデータのみを送信するため、元のレコード全体を取得するには、`streamArn`、`shardId`、`startSequenceNumber`、`endSequenceNumber` の各フィールドを使用します。`KinesisBatchInfo` プロパティに表示されるフィールドはすべて常に存在します。

```
{
    "requestContext": {
        "requestId": "c9b8fa9f-5a7f-xmpl-af9c-0c604cde93a5",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted",
        "approximateInvokeCount": 1
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:38:06.021Z",
    "KinesisBatchInfo": {
        "shardId": "shardId-000000000001",
        "startSequenceNumber": "49601189658422359378836298521827638475320189012309704722",
        "endSequenceNumber": "49601189658422359378836298522902373528957594348623495186",
        "approximateArrivalOfFirstRecord": "2019-11-14T00:38:04.835Z",
        "approximateArrivalOfLastRecord": "2019-11-14T00:38:05.580Z",
        "batchSize": 500,
        "streamArn": "arn:aws:kinesis:us-east-2:123456789012:stream/mystream"
    }
}
```

この情報は、トラブルシューティングのためにストリームから影響を受けるレコードを取得する際に使用できます。実際のレコードは含まれていないので、有効期限が切れて失われる前に、このレコードを処理し、ストリームから取得する必要があります。

### Amazon S3 呼び出しレコードの例
<a name="kinesis-on-failure-destination-example-sns-sqs-s3"></a>

次の例は、Kinesis イベントソースの呼び出しが失敗した場合に Amazon S3 バケットに送信する内容を示しています。SQS と SNS の送信先に関する前例のすべてのフィールドに加えて、`payload` フィールドには元の呼び出しレコードがエスケープされた JSON 文字列として含まれています。

```
{
    "requestContext": {
        "requestId": "c9b8fa9f-5a7f-xmpl-af9c-0c604cde93a5",
        "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:myfunction",
        "condition": "RetryAttemptsExhausted",
        "approximateInvokeCount": 1
    },
    "responseContext": {
        "statusCode": 200,
        "executedVersion": "$LATEST",
        "functionError": "Unhandled"
    },
    "version": "1.0",
    "timestamp": "2019-11-14T00:38:06.021Z",
    "KinesisBatchInfo": {
        "shardId": "shardId-000000000001",
        "startSequenceNumber": "49601189658422359378836298521827638475320189012309704722",
        "endSequenceNumber": "49601189658422359378836298522902373528957594348623495186",
        "approximateArrivalOfFirstRecord": "2019-11-14T00:38:04.835Z",
        "approximateArrivalOfLastRecord": "2019-11-14T00:38:05.580Z",
        "batchSize": 500,
        "streamArn": "arn:aws:kinesis:us-east-2:123456789012:stream/mystream"
    },
    "payload": "<Whole Event>" // Only available in S3
}
```

呼び出しレコードを含む S3 オブジェクトでは、次の命名規則が使用されます。

```
aws/lambda/<ESM-UUID>/<shardID>/YYYY/MM/DD/YYYY-MM-DDTHH.MM.SS-<Random UUID>
```

# Lambda でのステートフル Kinesis Data Streams 処理の実装
<a name="services-kinesis-windows"></a>

Lambda 関数は、連続ストリーム処理アプリケーションを実行できます。ストリームは、アプリケーションを継続的に流れる無限のデータを表します。この継続的に更新される入力からの情報を分析するために、時間に関して定義されたウィンドウを使用して、含まれるレコードをバインドできます。

タンブリングウィンドウは、一定の間隔で開閉する別個のタイムウィンドウです。ディフォルトでは、Lambda 呼び出しはステートレス — 外部データベースがない場合、複数の連続した呼び出しでデータを処理するために使用することはできません。ただし、タンブリングウィンドウを使用して、呼び出し間で状態を維持できます。この状態は、現在のウィンドウに対して以前に処理されたメッセージの集計結果が含まれます。状態は、シャードごとに最大 1 MB にすることができます。このサイズを超えると、Lambda はウィンドウを早期に終了します。

ストリームの各レコードは、特定のウィンドウに属しています。Lambda は各レコードを少なくとも 1 回処理しますが、各レコードが 1 回だけ処理される保証はありません。エラー処理などのまれなケースでは、一部のレコードが複数回処理されることがあります。レコードは常に最初から順番に処理されます。レコードが複数回処理される場合、順不同で処理されます。

## 集約と処理
<a name="streams-tumbling-processing"></a>

ユーザー管理関数は、集約と、その集約の最終結果を処理するために呼び出されます。Lambda は、ウィンドウで受信したすべてのレコードを集約します。これらのレコードは、個別の呼び出しとして複数のバッチで受け取ることができます。各呼び出しは状態を受け取ります。したがって、タンブリングウィンドウを使用する場合、Lambda 関数の応答に `state` プロパティが含まれている必要があります。応答に `state` プロパティが含まれてないと、Lambda はこれを失敗した呼び出しと見なします。この条件を満たすために、関数は次の JSON 形式の `TimeWindowEventResponse` オブジェクトを返すことができます。

**Example `TimeWindowEventResponse`値**  

```
{
    "state": {
        "1": 282,
        "2": 715
    },
    "batchItemFailures": []
}
```

**注記**  
Java 関数の場合は、`Map<String, String>`を使用して状態を表すことをお勧めします。

ウィンドウの最後で、フラグ`isFinalInvokeForWindow`が`true`に設定され、これが最終状態であり、処理の準備ができていることが示されます。処理が完了すると、ウィンドウが完了し、最終的な呼び出しが完了し、状態は削除されます。

ウィンドウの最後に、Lambda は集計結果に対するアクションの最終処理を使用します。最終処理が同期的に呼び出されます。呼び出しが成功すると、関数はシーケンス番号をチェックポイントし、ストリーム処理が続行されます。呼び出しが失敗した場合、Lambda 関数は呼び出しが成功するまで処理を一時停止します。

**Example kinesisTimeWindowEvent**  

```
{
    "Records": [
        {
            "kinesis": {
                "kinesisSchemaVersion": "1.0",
                "partitionKey": "1",
                "sequenceNumber": "49590338271490256608559692538361571095921575989136588898",
                "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
                "approximateArrivalTimestamp": 1607497475.000
            },
            "eventSource": "aws:kinesis",
            "eventVersion": "1.0",
            "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898",
            "eventName": "aws:kinesis:record",
            "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-kinesis-role",
            "awsRegion": "us-east-1",
            "eventSourceARN": "arn:aws:kinesis:us-east-1:123456789012:stream/lambda-stream"
        }
    ],
    "window": {
        "start": "2020-12-09T07:04:00Z",
        "end": "2020-12-09T07:06:00Z"
    },
    "state": {
        "1": 282,
        "2": 715
    },
    "shardId": "shardId-000000000006",
    "eventSourceARN": "arn:aws:kinesis:us-east-1:123456789012:stream/lambda-stream",
    "isFinalInvokeForWindow": false,
    "isWindowTerminatedEarly": false
}
```

## 設定
<a name="streams-tumbling-config"></a>

イベントソースマッピングを作成または更新するときに 、タンブリングウィンドウを設定できます。タンブリングウィンドウを設定するには、ウィンドウを秒単位で指定します ([TumblingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-TumblingWindowInSeconds))。次の例の AWS Command Line Interface (AWS CLI) コマンドは、タンブリングウィンドウが 120 秒に設定されたストリーミングイベントソースマッピングを作成します。集約と処理のために Lambda 関数が定義した関数の名前は `tumbling-window-example-function` です。

```
aws lambda create-event-source-mapping \
--event-source-arn arn:aws:kinesis:us-east-1:123456789012:stream/lambda-stream \
--function-name tumbling-window-example-function \
--starting-position TRIM_HORIZON \
--tumbling-window-in-seconds 120
```

Lambda は、レコードがストリームに挿入された時間に基づいて、タンブリングウィンドウの境界を決定します。すべてのレコードには、Lambda が境界の決定に使用するおおよそのタイムスタンプがあります。

ウィンドウの集合をタンブルしても、再共有はサポートされません。シャードが終了すると、Lambda はウィンドウが閉じられると見なし、子シャードは新しい状態で独自のウィンドウを開始します。現在のウィンドウに新しいレコードが追加されていない場合、Lambda は最大で 2 分間待機してから、ウィンドウが終了したと見なします。これにより、レコードが断続的に追加された場合でも、関数は現在のウィンドウ内のすべてのレコードを読み取ることができます。

タンブルウィンドウは、既存の再試行ポリシー`maxRetryAttempts`および`maxRecordAge`を完全にサポートします。

**Example Handler.py - 集約と処理**  
次の Python 関数は、最終状態を集約して処理する方法を示しています。  

```
def lambda_handler(event, context):
    print('Incoming event: ', event)
    print('Incoming state: ', event['state'])

#Check if this is the end of the window to either aggregate or process.
    if event['isFinalInvokeForWindow']:
        # logic to handle final state of the window
        print('Destination invoke')
    else:
        print('Aggregate invoke')

#Check for early terminations
    if event['isWindowTerminatedEarly']:
        print('Window terminated early')

    #Aggregation logic
    state = event['state']
    for record in event['Records']:
        state[record['kinesis']['partitionKey']] = state.get(record['kinesis']['partitionKey'], 0) + 1

    print('Returning state: ', state)
    return {'state': state}
```

# Amazon Kinesis Data Streams イベントソースマッピングの Lambda パラメータ
<a name="services-kinesis-parameters"></a>

すべての Lambda イベントソースマッピングで、同じ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションが共有されます。ただし、Kinesis に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | メモ | 
| --- | --- | --- | --- | 
|  [BatchSize](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-BatchSize)  |  N  |  100  |  最大: 10,000  | 
|  [BisectBatchOnFunctionError](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-BisectBatchOnFunctionError)  |  N  |  false  |  なし | 
|  [DestinationConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-DestinationConfig)  |  N  | 該当なし |  破棄されたレコードの Amazon SQS キューまたは Amazon SNS トピックの送信先。詳細については、「[失敗した呼び出しの送信先の設定](kinesis-on-failure-destination.md#kinesis-on-failure-destination-console)」を参照してください。  | 
|  [[Enabled]](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-Enabled) (有効)  |  N  |  true  |  なし | 
|  [EventSourceArn](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-EventSourceArn)  |  Y  | 該当なし |  データストリームまたはストリームコンシューマーの ARN。  | 
|  [FunctionName](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-FunctionName)  |  Y  | 該当なし |  なし | 
|  [FunctionResponseTypes](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-FunctionResponseTypes)  |  N  |  該当なし |  関数がバッチ内の特定の失敗を報告できるようにするには、`FunctionResponseTypes` に値 `ReportBatchItemFailures` を含めます。詳細については、「[Kinesis Data Streams と Lambda を使用した部分的なバッチレスポンスの設定](services-kinesis-batchfailurereporting.md)」を参照してください。  | 
|  [MaximumBatchingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumBatchingWindowInSeconds)  |  N  |  0  |  なし | 
|  [MaximumRecordAgeInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRecordAgeInSeconds)  |  N  |  -1  |  -1 は無制限を意味します: Lambda はレコードを破棄しません ([Kinesis Data Streams データ保持設定](https://docs.aws.amazon.com/streams/latest/dev/kinesis-extended-retention.html)は引き続き適用されます) 最小: -1 最大: 604,800  | 
|  [MaximumRetryAttempts](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-MaximumRetryAttempts)  |  N  |  -1  |  -1 に設定すると無制限になり、失敗したレコードはレコードの有効期限が切れるまで再試行されます。 最小: -1 最大: 10,000  | 
|  [ParallelizationFactor](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-ParallelizationFactor)  |  N  |  1  |  最大: 10  | 
|  [StartingPosition](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-StartingPosition)  |  Y  |  該当なし |  AT\$1TIMESTAMP、TRIM\$1HORIZON、または LATEST  | 
|  [StartingPositionTimestamp](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-StartingPositionTimestamp)  |  N  |  該当なし |  StartingPosition が AT\$1TIMESTAMP に設定されている場合にのみ有効です。Unix タイム秒単位で読み取りをスタートする時間  | 
|  [TumblingWindowInSeconds](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html#lambda-CreateEventSourceMapping-request-TumblingWindowInSeconds)  |  N  |  該当なし |  最小: 0 最大: 900  | 

# Kinesis イベントソースでのイベントフィルタリングの使用
<a name="with-kinesis-filtering"></a>

イベントフィルタリングを使用して、Lambda が関数に送信するストリームまたはキューからのレコードを制御することができます。イベントフィルタリングの仕組みに関する一般情報については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

このセクションでは、Kinesis イベントソースのイベントフィルタリングに焦点を当てます。

**注記**  
Kinesis イベントソースマッピングは、 `data` キーでのフィルタリングのみをサポートします。

**Topics**
+ [Kinesis イベントフィルタリングの基本](#filtering-kinesis)
+ [Kinesis 集約レコードのフィルタリング](#filtering-kinesis-efo)

## Kinesis イベントフィルタリングの基本
<a name="filtering-kinesis"></a>

プロデューサーが JSON 形式のデータを Kinesis データストリームに入力するとします。レコードの例は次のようになり、`data` フィールドで JSON データが Base64 でエンコードされた文字列に変換されます。

```
{
    "kinesis": {
        "kinesisSchemaVersion": "1.0",
        "partitionKey": "1",
        "sequenceNumber": "49590338271490256608559692538361571095921575989136588898",
        "data": "eyJSZWNvcmROdW1iZXIiOiAiMDAwMSIsICJUaW1lU3RhbXAiOiAieXl5eS1tbS1kZFRoaDptbTpzcyIsICJSZXF1ZXN0Q29kZSI6ICJBQUFBIn0=",
        "approximateArrivalTimestamp": 1545084650.987
        },
    "eventSource": "aws:kinesis",
    "eventVersion": "1.0",
    "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898",
    "eventName": "aws:kinesis:record",
    "invokeIdentityArn": "arn:aws:iam::123456789012:role/lambda-role",
    "awsRegion": "us-east-2",
    "eventSourceARN": "arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream"
}
```

プロデューサーがストリームに入力するデータが有効な JSON である限り、イベントフィルタリングを使用して `data` キーを使用するレコードをフィルタリングできます。プロデューサーが次の JSON 形式でレコードを Kinesis ストリームに入力するとします。

```
{
    "record": 12345,
    "order": {
        "type": "buy",
        "stock": "ANYCO",
        "quantity": 1000
        }
}
```

注文タイプが「購入」のレコードのみをフィルタリングするには、`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"data\" : { \"order\" : { \"type\" : [ \"buy\" ] } } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "data": {
        "order": {
            "type": [ "buy" ]
            }
      }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "data" : { "order" : { "type" : [ "buy" ] } } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:kinesis:us-east-2:123456789012:stream/my-stream \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : { \"order\" : { \"type\" : [ \"buy\" ] } } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : { \"order\" : { \"type\" : [ \"buy\" ] } } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "data" : { "order" : { "type" : [ "buy" ] } } }'
```

------

Kinesis ソースからイベントを適切にフィルタリングするには、データフィールドおよびデータフィールドのフィルター条件の両方が有効な JSON 形式である必要があります。フィールドのどちらかが有効な JSON 形式ではない場合、Lambda はメッセージをドロップするか、例外をスローします。以下は、特定の動作を要約した表です。


| 着信データの形式 | データプロパティのフィルターパターンの形式 | 結果として生じるアクション | 
| --- | --- | --- | 
|  有効な JSON  |  有効な JSON  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  有効な JSON  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  JSON 以外  |  Lambda がイベントソースマッピングの作成または更新時に例外をスローします。データプロパティのフィルターパターンは、有効な JSON 形式である必要があります。  | 
|  JSON 以外  |  有効な JSON  |  Lambda がレコードをドロップします。  | 
|  JSON 以外  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  JSON 以外  |  JSON 以外  |  Lambda がイベントソースマッピングの作成または更新時に例外をスローします。データプロパティのフィルターパターンは、有効な JSON 形式である必要があります。  | 

## Kinesis 集約レコードのフィルタリング
<a name="filtering-kinesis-efo"></a>

Kinesis を使用すると、複数のレコードを 1 つの Kinesis データストリームレコードに集約し、データスループットを増加させることができます。Lambda は、Kinesis 「[拡張ファンアウト](https://docs.aws.amazon.com/streams/latest/dev/enhanced-consumers.html)」を使用する場合に限り、集約レコードにフィルター条件を適用できます。標準 Kinesis による集約レコードのフィルタリングはサポートされていません。拡張ファンアウトを使用するときは、Kinesis 専用スループットコンシューマーが Lambda 関数のトリガーとして機能するように設定します。次に、Lambda は集約されたレコードをフィルタリングし、フィルター条件を満たすレコードのみを渡します。

Kinesis レコード集約の詳細については、「Kinesis プロデューサーライブラリ (KPL) のキーコンセプト」ページの「[集約](https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-concepts.html#kinesis-kpl-concepts-aggretation)」セクションを参照してください。Kinesis 拡張ファンアウトを用いた Lambda の使用に関する詳細については、「AWS コンピュートブログ」の「[Amazon Kinesis Data Streams 拡張ファンアウトおよび AWS Lambda でのリアルタイムストリーム処理パフォーマンスの向上](https://aws.amazon.com/blogs/compute/increasing-real-time-stream-processing-performance-with-amazon-kinesis-data-streams-enhanced-fan-out-and-aws-lambda/)」を参照してください。

# チュートリアル: Lambda を Kinesis Data Streams で使用する
<a name="with-kinesis-example"></a>

このチュートリアルでは、Amazon Kinesis データストリームのイベントを処理する Lambda 関数を作成します。

1. カスタムアプリケーションがストリームにレコードを書き込みます。

1. AWS Lambda はストリームをポーリングし、ストリームで新しいレコードを検出すると Lambda 関数を呼び出します。

1. AWS Lambda は、Lambda 関数の作成時に指定した実行ロールを引き受けることにより、Lambda 関数を実行します。

## 前提条件
<a name="with-kinesis-prepare"></a>

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## 実行ロールを作成する
<a name="with-kinesis-example-create-iam-role"></a>

AWS リソースにアクセスするためのアクセス権限を関数に付与する[実行ロール](lambda-intro-execution-role.md)を作成します。

**実行ロールを作成するには**

1. IAM コンソールの [[ロールページ](https://console.aws.amazon.com/iam/home#/roles)] を開きます。

1. [**ロールの作成**] を選択します。

1. 次のプロパティでロールを作成します。
   + **信頼されたエンティティ** - **AWS Lambda**
   + **アクセス許可** - **AWSLambdaKinesisExecutionRole**。
   + **Role name** – **lambda-kinesis-role**。

**AWSLambdaKinesisExecutionRole** ポリシーには、Kinesis から項目を読み取り、CloudWatch Logs にログを書き込むために関数が必要とするアクセス許可があります。

## 関数を作成する
<a name="with-kinesis-example-create-function"></a>

Kinesis メッセージを処理する Lambda 関数を作成します。この関数コードは、Kinesis レコードのイベント ID とイベントデータを CloudWatch Logs にログ記録します。

このチュートリアルでは Node.js 24 ランタイムを使用しますが、他のランタイム言語のサンプルコードも提供しています。次のボックスでタブを選択すると、関心のあるランタイムのコードが表示されます。このステップで使用する JavaScript コードは、**[JavaScript]** タブに表示されている最初のサンプルにあります。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
﻿using System.Text;
using Amazon.Lambda.Core;
using Amazon.Lambda.KinesisEvents;
using AWS.Lambda.Powertools.Logging;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace KinesisIntegrationSampleCode;

public class Function
{
    // Powertools Logger requires an environment variables against your function
    // POWERTOOLS_SERVICE_NAME
    [Logging(LogEvent = true)]
    public async Task FunctionHandler(KinesisEvent evnt, ILambdaContext context)
    {
        if (evnt.Records.Count == 0)
        {
            Logger.LogInformation("Empty Kinesis Event received");
            return;
        }

        foreach (var record in evnt.Records)
        {
            try
            {
                Logger.LogInformation($"Processed Event with EventId: {record.EventId}");
                string data = await GetRecordDataAsync(record.Kinesis, context);
                Logger.LogInformation($"Data: {data}");
                // TODO: Do interesting work based on the new data
            }
            catch (Exception ex)
            {
                Logger.LogError($"An error occurred {ex.Message}");
                throw;
            }
        }
        Logger.LogInformation($"Successfully processed {evnt.Records.Count} records.");
    }

    private async Task<string> GetRecordDataAsync(KinesisEvent.Record record, ILambdaContext context)
    {
        byte[] bytes = record.Data.ToArray();
        string data = Encoding.UTF8.GetString(bytes);
        await Task.CompletedTask; //Placeholder for actual async work
        return data;
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main

import (
	"context"
	"log"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(ctx context.Context, kinesisEvent events.KinesisEvent) error {
	if len(kinesisEvent.Records) == 0 {
		log.Printf("empty Kinesis event received")
		return nil
	}

	for _, record := range kinesisEvent.Records {
		log.Printf("processed Kinesis event with EventId: %v", record.EventID)
		recordDataBytes := record.Kinesis.Data
		recordDataText := string(recordDataBytes)
		log.Printf("record data: %v", recordDataText)
		// TODO: Do interesting work based on the new data
	}
	log.Printf("successfully processed %v records", len(kinesisEvent.Records))
	return nil
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;

public class Handler implements RequestHandler<KinesisEvent, Void> {
    @Override
    public Void handleRequest(final KinesisEvent event, final Context context) {
        LambdaLogger logger = context.getLogger();
        if (event.getRecords().isEmpty()) {
            logger.log("Empty Kinesis Event received");
            return null;
        }
        for (KinesisEvent.KinesisEventRecord record : event.getRecords()) {
            try {
                logger.log("Processed Event with EventId: "+record.getEventID());
                String data = new String(record.getKinesis().getData().array());
                logger.log("Data:"+ data);
                // TODO: Do interesting work based on the new data
            }
            catch (Exception ex) {
                logger.log("An error occurred:"+ex.getMessage());
                throw ex;
            }
        }
        logger.log("Successfully processed:"+event.getRecords().size()+" records");
        return null;
    }

}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/blob/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const record of event.Records) {
    try {
      console.log(`Processed Kinesis Event - EventID: ${record.eventID}`);
      const recordData = await getRecordDataAsync(record.kinesis);
      console.log(`Record Data: ${recordData}`);
      // TODO: Do interesting work based on the new data
    } catch (err) {
      console.error(`An error occurred ${err}`);
      throw err;
    }
  }
  console.log(`Successfully processed ${event.Records.length} records.`);
};

async function getRecordDataAsync(payload) {
  var data = Buffer.from(payload.data, "base64").toString("utf-8");
  await Promise.resolve(1); //Placeholder for actual async work
  return data;
}
```
TypeScript を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import {
  KinesisStreamEvent,
  Context,
  KinesisStreamHandler,
  KinesisStreamRecordPayload,
} from "aws-lambda";
import { Buffer } from "buffer";
import { Logger } from "@aws-lambda-powertools/logger";

const logger = new Logger({
  logLevel: "INFO",
  serviceName: "kinesis-stream-handler-sample",
});

export const functionHandler: KinesisStreamHandler = async (
  event: KinesisStreamEvent,
  context: Context
): Promise<void> => {
  for (const record of event.Records) {
    try {
      logger.info(`Processed Kinesis Event - EventID: ${record.eventID}`);
      const recordData = await getRecordDataAsync(record.kinesis);
      logger.info(`Record Data: ${recordData}`);
      // TODO: Do interesting work based on the new data
    } catch (err) {
      logger.error(`An error occurred ${err}`);
      throw err;
    }
    logger.info(`Successfully processed ${event.Records.length} records.`);
  }
};

async function getRecordDataAsync(
  payload: KinesisStreamRecordPayload
): Promise<string> {
  var data = Buffer.from(payload.data, "base64").toString("utf-8");
  await Promise.resolve(1); //Placeholder for actual async work
  return data;
}
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\Kinesis\KinesisEvent;
use Bref\Event\Kinesis\KinesisHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler extends KinesisHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws JsonException
     * @throws \Bref\Event\InvalidLambdaEvent
     */
    public function handleKinesis(KinesisEvent $event, Context $context): void
    {
        $this->logger->info("Processing records");
        $records = $event->getRecords();
        foreach ($records as $record) {
            $data = $record->getData();
            $this->logger->info(json_encode($data));
            // TODO: Do interesting work based on the new data

            // Any exception thrown will be logged and the invocation will be marked as failed
        }
        $totalRecords = count($records);
        $this->logger->info("Successfully processed $totalRecords records");
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda での Kinesis イベントの消費。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
import base64
def lambda_handler(event, context):

    for record in event['Records']:
        try:
            print(f"Processed Kinesis Event - EventID: {record['eventID']}")
            record_data = base64.b64decode(record['kinesis']['data']).decode('utf-8')
            print(f"Record Data: {record_data}")
            # TODO: Do interesting work based on the new data
        except Exception as e:
            print(f"An error occurred {e}")
            raise e
    print(f"Successfully processed {len(event['Records'])} records.")
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda での Kinesis イベントの消費。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
require 'aws-sdk'

def lambda_handler(event:, context:)
  event['Records'].each do |record|
    begin
      puts "Processed Kinesis Event - EventID: #{record['eventID']}"
      record_data = get_record_data_async(record['kinesis'])
      puts "Record Data: #{record_data}"
      # TODO: Do interesting work based on the new data
    rescue => err
      $stderr.puts "An error occurred #{err}"
      raise err
    end
  end
  puts "Successfully processed #{event['Records'].length} records."
end

def get_record_data_async(payload)
  data = Base64.decode64(payload['data']).force_encoding('UTF-8')
  # Placeholder for actual async work
  # You can use Ruby's asynchronous programming tools like async/await or fibers here.
  return data
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-kinesis-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用した Lambda での Kinesis イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::event::kinesis::KinesisEvent;
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

async fn function_handler(event: LambdaEvent<KinesisEvent>) -> Result<(), Error> {
    if event.payload.records.is_empty() {
        tracing::info!("No records found. Exiting.");
        return Ok(());
    }

    event.payload.records.iter().for_each(|record| {
        tracing::info!("EventId: {}",record.event_id.as_deref().unwrap_or_default());

        let record_data = std::str::from_utf8(&record.kinesis.data);

        match record_data {
            Ok(data) => {
                // log the record data
                tracing::info!("Data: {}", data);
            }
            Err(e) => {
                tracing::error!("Error: {}", e);
            }
        }
    });

    tracing::info!(
        "Successfully processed {} records",
        event.payload.records.len()
    );

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

**関数を作成するには**

1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

   ```
   mkdir kinesis-tutorial
   cd kinesis-tutorial
   ```

1. サンプル JavaScript コードを `index.js` という名前の新しいファイルにコピーします。

1. デプロイパッケージを作成します。

   ```
   zip function.zip index.js
   ```

1. `create-function` コマンドを使用して Lambda 関数を作成します。

   ```
   aws lambda create-function --function-name ProcessKinesisRecords \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/lambda-kinesis-role
   ```

## Lambda 関数をテストする
<a name="walkthrough-kinesis-events-adminuser-create-test-function-upload-zip-test-manual-invoke"></a>

`invoke`AWS Lambda CLI コマンドおよびサンプルの Kinesis イベントを使用して、手動で Lambda 関数を呼び出します。

**Lambda 関数をテストするには**

1. 以下の JSON をファイルにコピーし、`input.txt` という名前で保存します。

   ```
   {
       "Records": [
           {
               "kinesis": {
                   "kinesisSchemaVersion": "1.0",
                   "partitionKey": "1",
                   "sequenceNumber": "49590338271490256608559692538361571095921575989136588898",
                   "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==",
                   "approximateArrivalTimestamp": 1545084650.987
               },
               "eventSource": "aws:kinesis",
               "eventVersion": "1.0",
               "eventID": "shardId-000000000006:49590338271490256608559692538361571095921575989136588898",
               "eventName": "aws:kinesis:record",
               "invokeIdentityArn": "arn:aws:iam::111122223333:role/lambda-kinesis-role",
               "awsRegion": "us-east-2",
               "eventSourceARN": "arn:aws:kinesis:us-east-2:111122223333:stream/lambda-stream"
           }
       ]
   }
   ```

1. `invoke` コマンドを使用して、関数にイベントを送信します。

   ```
   aws lambda invoke --function-name ProcessKinesisRecords \
   --cli-binary-format raw-in-base64-out \
   --payload file://input.txt outputfile.txt
   ```

   AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、バージョン 2 の AWS Command Line Interface ユーザーガイドの「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。

   レスポンスは `out.txt` に保存されます。

## Kinesis Stream を作成する
<a name="with-kinesis-example-configure-event-source-create"></a>

`create-stream ` コマンドを使用して、スキーマを作成します。

```
aws kinesis create-stream --stream-name lambda-stream --shard-count 1
```

次の `describe-stream` コマンドを実行して、ストリーム ARN を取得します。

```
aws kinesis describe-stream --stream-name lambda-stream
```

次のような出力が表示されます。

```
{
    "StreamDescription": {
        "Shards": [
            {
                "ShardId": "shardId-000000000000",
                "HashKeyRange": {
                    "StartingHashKey": "0",
                    "EndingHashKey": "340282366920746074317682119384634633455"
                },
                "SequenceNumberRange": {
                    "StartingSequenceNumber": "49591073947768692513481539594623130411957558361251844610"
                }
            }
        ],
        "StreamARN": "arn:aws:kinesis:us-east-1:111122223333:stream/lambda-stream",
        "StreamName": "lambda-stream",
        "StreamStatus": "ACTIVE",
        "RetentionPeriodHours": 24,
        "EnhancedMonitoring": [
            {
                "ShardLevelMetrics": []
            }
        ],
        "EncryptionType": "NONE",
        "KeyId": null,
        "StreamCreationTimestamp": 1544828156.0
    }
}
```

次のステップで Lambda 関数にストリームを関連付けるために、ストリーム ARN を使用します。

## AWS Lambda でイベントソースを追加する
<a name="with-kinesis-example-configure-event-source-add-event-source"></a>

次の AWS CLI `add-event-source` コマンドを実行します。

```
aws lambda create-event-source-mapping --function-name ProcessKinesisRecords \
--event-source  arn:aws:kinesis:us-east-1:111122223333:stream/lambda-stream \
--batch-size 100 --starting-position LATEST
```

後で使用するために、マッピング ID をメモしておきます。`list-event-source-mappings` コマンドを実行して、イベントソースマッピングのリストを取得できます。

```
aws lambda list-event-source-mappings --function-name ProcessKinesisRecords \
--event-source arn:aws:kinesis:us-east-1:111122223333:stream/lambda-stream
```

レスポンスでは、ステータス値が `enabled` であることを確認できます。イベントソースマッピングを無効にすると、レコードを失うことなくポーリングを一時停止できます。

## セットアップをテストする
<a name="with-kinesis-example-configure-event-source-test-end-to-end"></a>

イベントソースマッピングをテストするには、イベントレコードを Kinesis ストリームに追加します。`--data` 値は、文字列を Kinesis に送信する前に CLI で base64 にエンコードされる文字列です。同じコマンドを複数回実行して、複数のレコードをストリームに追加することができます。

```
aws kinesis put-record --stream-name lambda-stream --partition-key 1 \
--data "Hello, this is a test."
```

Lambda は実行ロールを使用して、ストリームからレコードを読み取ります。次に、Lambda 関数を呼び出し、レコードのバッチを渡します。この関数は、各レコードからデータをデコードしてログ記録し、出力を CloudWatch Logs に送信します。[CloudWatch コンソール](https://console.aws.amazon.com/cloudwatch)でログを表示する

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[Delete]** (削除) を選択します。

**Kinesis ストリームを削除するには**

1. AWS マネジメントコンソール にサインインし、Kinesis コンソール ([https://console.aws.amazon.com/kinesis](https://console.aws.amazon.com/kinesis)) を開きます。

1. 作成したストリームを選択します。

1. [** Actions**] で、[**Delete **] を選択します。

1. テキスト入力フィールドに **delete** を入力します。

1. **[Delete]** (削除) をクリックします。

# Kubernetes で Lambda を使用する
<a name="with-kubernetes"></a>

[AWS Controllers for Kubernetes (ACK)](https://aws-controllers-k8s.github.io/community/docs/community/overview/) または [Crossplane](https://docs.crossplane.io/latest/packages/providers/) を使用して、Kubernetes API で Lambda 関数をデプロイおよび管理できます。

## AWS Controllers for Kubernetes (ACK)
<a name="kubernetes-ack"></a>

ACK を使用すると、Kubernetes API からの AWS リソースのデプロイおよび管理を行うことができます。ACK を通じて、AWS は Lambda、Amazon Elastic Container Registry (Amazon ECR)、Amazon Simple Storage Service (Amazon S3)、Amazon SageMaker AI などの AWS サービス用にオープンソースのカスタムコントローラーを提供します。サポートされている各 AWS サービスには、独自のカスタムコントローラーがあります。Kubernetes クラスターに、使用する各 AWS サービス用のコントローラーをインストールします。次に、[カスタムリソース定義 (CRD)](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/) を作成して、AWS リソースを定義します。

[Helm 3.8 またはそれ以降](https://helm.sh/docs/intro/install/)を使用して ACK コントローラーをインストールすることをお勧めします。すべての ACK コントローラーには、コントローラー、CRD、および Kubernetes RBAC ルールをインストールする独自の Helm チャートが付属しています。詳細については、「ACK ドキュメント」の「[Install an ACK Controller](https://aws-controllers-k8s.github.io/community/docs/user-docs/install/)」を参照してください。

ACK カスタムリソースは、作成後、他の組み込み Kubernetes オブジェクトと同様に使用できます。例えば、[kubectl](https://kubernetes.io/docs/reference/kubectl/) などのお好みの Kubernetes ツールチェーンで Lambda 関数をデプロイして管理できます。

ACK を使用して Lambda 関数をプロビジョニングするユースケースの例を次に示します。
+ 組織で [ロールベースアクセス制御 (RBAC)](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) および[サービスアカウントの IAM ロール](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)を使用して、アクセス許可の境界を作成する。ACK を使用すると、新しいユーザーやポリシーを作成しなくても、このセキュリティモデルを Lambda に再利用できます。
+ 組織に、Kubernetes マニフェストを使用して Amazon Elastic Kubernetes Service (Amazon EKS) クラスターにリソースをデプロイする DevOps プロセスがある。ACK を使用すると、コードテンプレートとして個別のインフラストラクチャを作成しなくても、マニフェストを使用して Lambda 関数をプロビジョニングできます。

ACK の使用に関する詳細については、[ACK ドキュメントの Lambda チュートリアル](https://aws-controllers-k8s.github.io/community/docs/tutorials/lambda-oci-example/)を参照してください。

## Crossplane
<a name="kubernetes-crossplane"></a>

[Crossplane](https://docs.crossplane.io/latest/packages/providers/) は、Kubernetes を使用してクラウドインフラストラクチャリソースを管理する、クラウドネイティブコンピューティング財団 (CNCF) のオープンソースのプロジェクトです。Crossplane を使用すると、デベロッパーはインフラストラクチャの複雑さを理解しなくてもインフラストラクチャをリクエストできます。プラットフォームチームは、インフラストラクチャのプロビジョニングおよび管理方法を制御できます。

Crossplane を使用すると、Kubernetes にマニフェストをデプロイできる任意の CI/CD パイプラインや [kubectl](https://kubernetes.io/docs/reference/kubectl/) のようなお好みの Kubernetes ツールチェーンで Lambda 関数をデプロイして管理できます。Crossplane を使用して Lambda 関数をプロビジョニングするユースケースの例を次に示します。
+ 組織が、Lambda 関数に正しい[タグ](configuration-tags.md)があることを確認することでコンプライアンスを強化したいと考えている。プラットフォームチームは、[Crossplane Compositions](https://docs.crossplane.io/latest/get-started/get-started-with-composition/) を使用し、API 抽象化を通じてこのポリシーを定義できます。その後、デベロッパーはこれらの抽象化を使用してタグ付きの Lambda 関数をデプロイできます。
+ プロジェクトに、Kubernetes で GitOps を使用している。このモデルでは、Kubernetes は git リポジトリ (望ましい状態) とクラスター内で実行されているリソース (現在の状態) を継続的に照合します。相違がある場合、GitOps プロセスによって自動的にクラスターに変更が加えられます。Kubernetes で GitOps を使用すると、使い慣れた Kubernetes ツールや [CRD](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)、[Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) のような概念を使用して、Crossplane を通じて Lambda 関数のデプロイおよび管理を行うことができます。

Lambda で Crossplane を使用する方法の詳細については、次を参照してください。
+ [AWS Blueprints for Crossplane](https://github.com/awslabs/crossplane-on-eks/blob/main/examples/upbound-aws-provider/README.md#deploy-the-examples): このリポジトリには、Crossplane を使用して Lambda 関数などの AWS リソースをデプロイする方法の例が含まれています。
**注記**  
AWS Blueprints for Crossplane は現在開発中であり、本番環境では使用することはできません。
+ [Deploying Lambda with Amazon EKS and Crossplane](https://www.youtube.com/watch?v=m-9KLq29K4k): この動画では、Crossplane を使用した AWS サーバーレスアーキテクチャの高度なデプロイの例が紹介されており、デベロッパーとプラットフォームの両方の観点から設計が検討されています。

# Amazon MQ で Lambda を使用する
<a name="with-mq"></a>

**注記**  
Lambda 関数以外のターゲットにデータを送信したい、または送信する前にデータをエンリッチしたいという場合は、「[Amazon EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html)」を参照してください。

Amazon MQ は、[Apache ActiveMQ](https://activemq.apache.org/) および [RabbitMQ](https://www.rabbitmq.com) 用のマネージドメッセージブローカーサービスです。*メッセージブローカー*を使用すると、ソフトウェアアプリケーションおよびコンポーネントは、さまざまなプログラミング言語、オペレーティングシステム、および、トピックまたはキューイベント送信先を介した正式なメッセージングプロトコルを使って、通信できるようになります。

また Amazon MQ は、ActiveMQ か RabbitMQ ブローカーをインストールすることにより、もしくは、異なるネットワークトポロジやその他のインフラストラクチャのニーズを提供することにより、ユーザーに代わって Amazon Elastic Compute Cloud (Amazon EC2)インスタンスを管理することもできます。

Lambda 関数を使用することで、Amazon MQ メッセージブローカーからのレコードを処理できます。Lambda は、ブローカーからメッセージを読み取り関数を[同期的に](invocation-sync.md)呼び出す Lambda リソース、[イベントソースマッピング](invocation-eventsourcemapping.md)によって関数を呼び出します。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

Amazon MQ イベントソースマッピングには、次の設定制限があります。
+ 同時実行数 — Amazon MQ イベントソースマッピングを使用する Lambda 関数には、デフォルトの最大[同時実行数](lambda-concurrency.md)設定があります。ActiveMQ の場合、Lambda サービスは同時実行環境の数を Amazon MQ イベントソースマッピングごとに 5 つに制限します。RabbitMQ の場合、同時実行環境の数は Amazon MQ イベントソースマッピングごとに 1 つに制限されます。関数の予約またはプロビジョニングされる同時実行数設定を変更しても、Lambda サービスはこれ以上実行環境を利用できるようにしません。単一の Amazon MQ イベントソースマッピングのデフォルトの最大同時実行数の引き上げをリクエストするには、イベントソースマッピング UUID とリージョンを サポート に連絡してください。引き上げはアカウントレベルやリージョンレベルではなく、特定のイベントソースマッピングレベルで適用されるため、イベントソースマッピングごとにスケーリングの引き上げを手動でリクエストする必要があります。
+ クロスアカウント - Lambda はクロスアカウント処理をサポートしていません。Lambda を使用して、別の AWS アカウント にある Amazon MQ メッセージブローカーからのレコードを処理することはできません。
+ 認証 - ActiveMQ では、ActiveMQ [SimpleAuthenticationPlugin](https://activemq.apache.org/security#simple-authentication-plugin) のみサポートされています。RabbitMQ の場合、[PLAIN](https://www.rabbitmq.com/access-control.html#mechanisms) 認証メカニズムのみサポートされています。ユーザーは、資格情報の管理には AWS Secrets Manager を使用します。ActiveMQ 認証の詳細については、*Amazon MQ デベロッパーガイド*の [Integrating ActiveMQ brokers with LDAP](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/security-authentication-authorization.html) を参照してください。
+ 接続クォータ - ブローカーは、ワイヤレベルプロトコルごとに最大の接続可能数を持っています。このクォータは、ブローカーインスタンスタイプに基づいています。これらの制限の詳細については、*Amazon MQ デベロッパーガイド*の **Quotas in Amazon MQ** の [Brokers](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-limits.html#broker-limits) のセクションを参照してください。
+ 接続 - ブローカーをパブリックまたはプライベートの Virtual Private Cloud (VPC) に作成できます。プライベート VPC の場合、Lambda 関数が VPC にアクセスしてメッセージを受信する必要があります。詳細については、このセクションで後述する[ネットワークセキュリティを設定する](process-mq-messages-with-lambda.md#process-mq-messages-with-lambda-networkconfiguration)を参照してください。
+ イベント送信先 - キューの送信先のみがサポートされます。ただし、仮想トピックを使用することができます。仮想トピックは、内部的にトピックとして動作し、キューとして Lambda と対話しながら動作します。詳細については、Apache ActiveMQ ウェブサイトの [Virtual Destinations](https://activemq.apache.org/virtual-destinations) および RabbitMQ ウェブサイトの [Virtual Hosts](https://www.rabbitmq.com/vhosts.html)を参照してください。
+ ネットワークトポロジ - ActiveMQ の場合、イベントソースマッピングごとに、１つの単一インスタンスまたはスタンバイブローカーがサポートされます。RabbitMQ の場合、イベントソースマッピングごとに、単一インスタンスブローカーまたはクラスターデプロイメントがサポートされます。単一インスタンスブローカーには、フェイルオーバーエンドポイントが必要です。これらのブローカーデプロイメントモードの詳細については、*Amazon MQ デベロッパーガイド*の [Active MQ Broker Architecture](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-broker-architecture.html) および [Rabbit MQ Broker Architecture](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/rabbitmq-broker-architecture.html) を参照してください。
+ プロトコル — サポートされるプロトコルは、Amazon MQ の統合のタイプによって異なります。
  + ActiveMQ 統合の場合、Lambda は OpenWire/Java Message Service (JMS) プロトコルを使用してメッセージを使用します。その他のプロトコルは、メッセージの使用をサポートしていません。JMS プロトコル内では、[https://activemq.apache.org/components/cms/api_docs/activemqcpp-3.6.0/html/classactivemq_1_1commands_1_1_active_m_q_text_message.html](https://activemq.apache.org/components/cms/api_docs/activemqcpp-3.6.0/html/classactivemq_1_1commands_1_1_active_m_q_text_message.html) および [https://activemq.apache.org/components/cms/api_docs/activemqcpp-3.9.0/html/classactivemq_1_1commands_1_1_active_m_q_bytes_message.html](https://activemq.apache.org/components/cms/api_docs/activemqcpp-3.9.0/html/classactivemq_1_1commands_1_1_active_m_q_bytes_message.html) のみがサポートされています。Lambda は、JMS カスタムプロパティもサポートしています。OpenWire プロトコルの詳細については、Apache ActiveMQ ウェブサイトの [ OpenWire ](https://activemq.apache.org/openwire.html) を参照してください。
  + RabbitMQ 統合の場合、Lambda は AMQP 0-9-1 プロトコルを使ってメッセージを使用します。その他のプロトコルは、メッセージの使用をサポートしていません。RabbitMQ による AMQP 0-9-1 プロトコルの実装の詳細については、RabbitMQ ウェブサイトの [AMQP 0-9-1 Complete Reference Guide](https://www.rabbitmq.com/amqp-0-9-1-reference.html) を参照してください。

Lambda は、Amazon MQ がサポートする ActiveMQ および RabbitMQ の最新バージョンを自動的にサポートします。サポートされている最新バージョンについては、*Amazon MQ デベロッパーガイド*の [Amazon MQ リリースノート](https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-release-notes.html)を参照してください。

**注記**  
デフォルトでは、Amazon MQ には毎週、ブローカー用のメンテナンスウィンドウがあります。その期間中、ブローカーは利用できません。スタンバイのないブローカーの場合、Lambda はそのウィンドウ中にメッセージを処理できません。

**Topics**
+ [Amazon MQ の Lambda コンシューマーグループについて理解する](#services-mq-configure)
+ [Lambda での Amazon MQ イベントソースの設定](process-mq-messages-with-lambda.md)
+ [イベントソースマッピングパラメータ](services-mq-params.md)
+ [Amazon MQ イベントソースからのイベントをフィルタリングする](with-mq-filtering.md)
+ [Amazon MQ イベントソースマッピングエラーのトラブルシューティング](services-mq-errors.md)

## Amazon MQ の Lambda コンシューマーグループについて理解する
<a name="services-mq-configure"></a>

Amazon MQ と対話するため、Lambda は、Amazon MQ ブローカーから読み取ることができるコンシューマーグループを作成します。コンシューマーグループは、イベントソースマッピング UUID と同じ ID で作成されます。

Amazon MQ イベントソースの場合、Lambda はレコードをまとめてバッチ処理し、それらを単一のペイロードで関数に送信します。動作を制御するには、バッチ処理ウィンドウとバッチサイズを設定できます。Lambda は、最大 6 MB のペイロードサイズを処理する、バッチ処理ウィンドウの期限が切れる、またはレコード数が完全なバッチサイズに到達するまで、メッセージをプルします。詳細については、「[バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)」を参照してください。

コンシューマーグループは、メッセージをバイトの BLOB として取得し、それらを base64 でエンコードして単一の JSON ペイロードに変換してから、関数を呼び出します。関数がバッチ内のいずれかのメッセージに対してエラーを返すと、Lambda は、処理が成功するかメッセージが期限切れになるまでメッセージのバッチ全体を再試行します。

**注記**  
Lambda 関数の最大タイムアウト制限は通常 15 分ですが、Amazon MSK、自己管理型 Apache Kafka、Amazon DocumentDB、および ActiveMQ と RabbitMQ 向け Amazon MQ のイベントソースマッピングでは、最大タイムアウト制限が 14 分の関数のみがサポートされます。この制約により、イベントソースマッピングは関数エラーと再試行を適切に処理できます。

Amazon CloudWatch の `ConcurrentExecutions` メトリクスを使用して、特定の関数の同時実行使用率を監視できます。同時実行の詳細については、「[関数に対する予約済み同時実行数の設定](configuration-concurrency.md)」を参照してください。

**Example Amazon MQ レコードイベント**  

```
{
   "eventSource": "aws:mq",
   "eventSourceArn": "arn:aws:mq:us-east-2:111122223333:broker:test:b-9bcfa592-423a-4942-879d-eb284b418fc8",
   "messages": [
      { 
        "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1---mq---us-east-2.amazonaws.com.rproxy.goskope.com-37557-1234520418293-4:1:1:1:1", 
        "messageType": "jms/text-message",
        "deliveryMode": 1,
        "replyTo": null,
        "type": null,
        "expiration": "60000",
        "priority": 1,
        "correlationId": "myJMSCoID",
        "redelivered": false,
        "destination": { 
          "physicalName": "testQueue" 
        },
        "data":"QUJDOkFBQUE=",
        "timestamp": 1598827811958,
        "brokerInTime": 1598827811958, 
        "brokerOutTime": 1598827811959, 
        "properties": {
          "index": "1",
          "doAlarm": "false",
          "myCustomProperty": "value"
        }
      },
      { 
        "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1---mq---us-east-2.amazonaws.com.rproxy.goskope.com-37557-1234520418293-4:1:1:1:1",
        "messageType": "jms/bytes-message",
        "deliveryMode": 1,
        "replyTo": null,
        "type": null,
        "expiration": "60000",
        "priority": 2,
        "correlationId": "myJMSCoID1",
        "redelivered": false,
        "destination": { 
          "physicalName": "testQueue" 
        },
        "data":"LQaGQ82S48k=",
        "timestamp": 1598827811958,
        "brokerInTime": 1598827811958, 
        "brokerOutTime": 1598827811959, 
        "properties": {
          "index": "1",
          "doAlarm": "false",
          "myCustomProperty": "value"
        }
      }
   ]
}
```

```
{
  "eventSource": "aws:rmq",
  "eventSourceArn": "arn:aws:mq:us-east-2:111122223333:broker:pizzaBroker:b-9bcfa592-423a-4942-879d-eb284b418fc8",
  "rmqMessagesByQueue": {
    "pizzaQueue::/": [
      {
        "basicProperties": {
          "contentType": "text/plain",
          "contentEncoding": null,
          "headers": {
            "header1": {
              "bytes": [
                118,
                97,
                108,
                117,
                101,
                49
              ]
            },
            "header2": {
              "bytes": [
                118,
                97,
                108,
                117,
                101,
                50
              ]
            },
            "numberInHeader": 10
          },
          "deliveryMode": 1,
          "priority": 34,
          "correlationId": null,
          "replyTo": null,
          "expiration": "60000",
          "messageId": null,
          "timestamp": "Jan 1, 1970, 12:33:41 AM",
          "type": null,
          "userId": "AIDACKCEVSQ6C2EXAMPLE",
          "appId": null,
          "clusterId": null,
          "bodySize": 80
        },
        "redelivered": false,
        "data": "eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ=="
      }
    ]
  }
}
```
RabbitMQ の例では、`pizzaQueue` は RabbitMQ キューの名前、`/` は仮想ホストの名前です。メッセージを受信すると、イベントソースは `pizzaQueue::/` の下にメッセージを一覧表示します。

# Lambda での Amazon MQ イベントソースの設定
<a name="process-mq-messages-with-lambda"></a>

**Topics**
+ [ネットワークセキュリティを設定する](#process-mq-messages-with-lambda-networkconfiguration)
+ [イベントソースマッピングを作成するには](#services-mq-eventsourcemapping)

## ネットワークセキュリティを設定する
<a name="process-mq-messages-with-lambda-networkconfiguration"></a>

イベントソースマッピングを通じて Lambda に Amazon MQ へのフルアクセスを許可するには、ブローカーがパブリックエンドポイント (パブリック IP アドレス) を使用するか、ブローカーを作成した Amazon VPC へのアクセスを提供する必要があります。

Lambda で Amazon MQ を使用する場合は、関数に Amazon VPC 内のリソースへのアクセスを付与する [AWS PrivateLink VPC エンドポイント](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html)を作成します。

**注記**  
イベントポーラーにデフォルト (オンデマンド) モードを使用するイベントソースマッピングを持つ関数には、AWS PrivateLink VPC エンドポイントが必要です。イベントソースマッピングが[プロビジョンドモード](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)を使用している場合は、AWS PrivateLink VPC エンドポイントを設定する必要はありません。

エンドポイントを作成して、次のリソースへのアクセスを提供します。
+  Lambda — Lambda サービスプリンシパルのエンドポイントを作成します。
+  AWS STS — サービスプリンシパルがユーザーに代わってロールを引き受けるために、AWS STS のエンドポイントを作成します。
+  Secrets Manager — ブローカーが Secrets Manager を使用して認証情報を保存する場合は、Secrets Manager のエンドポイントを作成します。

または、Amazon VPC の各パブリックサブネットに NAT ゲートウェイを設定します。詳細については、「[VPC に接続された Lambda 関数にインターネットアクセスを有効にする](configuration-vpc-internet.md)」を参照してください。

Amazon MQ のイベントソースマッピングを作成すると、Lambda は Amazon VPC に設定されたサブネットおよびセキュリティグループに Elastic Network Interface (ENI) が既に存在するかどうかを確認します。Lambda が既存の ENI を検出した場合、再利用しようとします。それ以外の場合、Lambda は新しい ENI を作成し、イベントソースに接続して関数を呼び出します。

**注記**  
Lambda 関数は、Lambda サービスが所有する VPC 内で常に実行されます。関数の VPC 設定はイベントソースマッピングに影響しません。Lambda がイベントソースに接続する方法を判定するのは、イベントソースのネットワーク設定のみです。

ブローカーを含む Amazon VPC のセキュリティグループを設定します。デフォルトでは、Amazon MQ は以下のポートを使用します。`61617` (Amazon MQ for ActiveMQ)、および `5671` (Amazon MQ for RabbitMQ)。
+ インバウンドルール – イベントソースに関連付けられたセキュリティグループに対してデフォルトのブローカーポート上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、同じセキュリティグループ内のインスタンスからのアクセスを許可することもできます。
+ アウトバウンドルール – 関数が AWS サービスと通信する必要がある場合、外部送信先のポート `443` 上のすべてのトラフィックを許可します。または、自己参照セキュリティグループルールを使用して、他の AWS サービスと通信する必要がない場合は、ブローカーへのアクセスを制限することもできます。
+ Amazon VPC エンドポイントのインバウンドルール – Amazon VPC エンドポイントを使用している場合、Amazon VPC エンドポイントに関連付けられたセキュリティグループで、ブローカーのセキュリティグループからポート `443` でインバウンドトラフィックを許可する必要があります。

ブローカーが認証を使用する場合、Secrets Manager エンドポイントのエンドポイントポリシーを制限することもできます。Secrets Manager API を呼び出す場合、Lambda は Lambda サービスプリンシパルではなく、関数ロールを使用します。

**Example VPC エンドポイントポリシー – Secrets Manager エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "secretsmanager:GetSecretValue",
              "Effect": "Allow",
              "Principal": {
                  "AWS": [
                      "arn:aws::iam::123456789012:role/my-role"
                  ]
              },
              "Resource": "arn:aws::secretsmanager:us-west-2:123456789012:secret:my-secret"
          }
      ]
  }
```

Amazon VPC エンドポイントを使用する場合、AWS は API コールをルーティングし、エンドポイントの Elastic Network Interface (ENI) を使用して関数を呼び出します。Lambda サービスプリンシパルは、これらの ENI を使用するすべてのロールおよび関数に対して `lambda:InvokeFunction` を呼び出す必要があります。

デフォルトでは、Amazon VPC エンドポイントには、リソースへの広範なアクセスを許可するオープンな IAM ポリシーが適用されています。そのエンドポイントを使用して必要なアクションを実行するためのベストプラクティスは、これらのポリシーを制限することです。イベントソースマッピングが Lambda 関数を呼び出せるようにするには、VPC エンドポイントポリシーで、Lambda サービスプリンシパルが `sts:AssumeRole` および `lambda:InvokeFunction` を呼び出すことを許可する必要があります。組織内で発生する API コールのみを許可するように VPC エンドポイントポリシーを制限すると、イベントソースマッピングが正しく機能しなくなるため、これらのポリシーには `"Resource": "*"` が必要です。

次の VPC エンドポイントポリシーの例では、AWS STS および Lambda エンドポイントに Lambda サービスプリンシパルの必要なアクセスを付与する方法について示しています。

**Example VPC エンドポイントポリシー - AWS STS エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
    }
```

**Example VPC エンドポイントポリシー – Lambda エンドポイント**  

```
{
      "Statement": [
          {
              "Action": "lambda:InvokeFunction",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
  }
```

## イベントソースマッピングを作成するには
<a name="services-mq-eventsourcemapping"></a>

[イベントソースマッピング](invocation-eventsourcemapping.md)を作成し、Amazon MQ ブローカーから Lambda 関数にレコードを送信するよう Lambda に通知します。複数のイベントソースマッピングを作成することで、複数の関数で同じデータを処理したり、単一の関数で複数のソースから項目を処理したりできます。

Amazon MQ から読み取るように関数を設定するには、必要なアクセス許可を追加し Lambda コンソールで **MQ** トリガーを作成します。

Amazon MQ ブローカーからレコードを読み取るには、Lambda 関数に次のアクセス許可が必要です。関数[実行ロール](lambda-intro-execution-role.md)にアクセス許可ステートメントを追加して、Lambda に Amazon MQ ブローカーとその基盤となるリソースとやり取りするためのアクセス許可を付与します。
+ [ mq:DescribeBroker ](https://docs.aws.amazon.com/amazon-mq/latest/api-reference/brokers-broker-id.html#brokers-broker-id-http-methods)
+ [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)
+ [ec2:CreateNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
+ [ec2:DeleteNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
+ [ec2:DescribeNetworkInterfaces](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
+ [ec2:DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
+ [ec2:DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
+ [ec2:DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
+ [logs:CreateLogGroup](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html)
+ [logs:CreateLogStream](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogStream.html)
+ [logs:PutLogEvents](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html)

**注記**  
暗号化されたカスタマー管理キーを使用する場合は、`[kms:Decrypt](https://docs.aws.amazon.com/msk/1.0/apireference/clusters-clusterarn-bootstrap-brokers.html#clusters-clusterarn-bootstrap-brokersget)` 権限も追加します。

**アクセス許可を追加してトリガーを作成するには**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 関数の名前を選択します。

1. **[設定]** タブを開き、次に **[アクセス権限]** をクリックします。

1. **[実行ロール]** で、実行ロールのリンクを選択します。このリンクを選択すると、IAM コンソールでロールが開きます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/execution-role.png)

1. **[アクセス権限を追加]**、**[インラインポリシーを作成]** の順に選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/inline-policy.png)

1. **[ポリシーエディター]** で、**[JSON]** を選択します。以下のポリシーを入力します。Amazon MQ ブローカーから読み取るには、関数にこれらのアクセス許可が必要です。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
         {
           "Effect": "Allow",
           "Action": [
             "mq:DescribeBroker",
             "secretsmanager:GetSecretValue",
             "ec2:CreateNetworkInterface",
             "ec2:DeleteNetworkInterface",
             "ec2:DescribeNetworkInterfaces", 
             "ec2:DescribeSecurityGroups",
             "ec2:DescribeSubnets",
             "ec2:DescribeVpcs",
             "logs:CreateLogGroup",
             "logs:CreateLogStream", 
             "logs:PutLogEvents"		
           ],
           "Resource": "*"
         }
       ]
     }
   ```

------
**注記**  
暗号化されたカスタマー管理キーを使用する場合は、`kms:Decrypt` アクセス許可も追加する必要があります。

1. [**次へ**] を選択します。ポリシー名を入力し、**[ポリシーの作成]** を選択します。

1. Lambda コンソールの関数に戻ります。**[関数の概要]** で **[トリガーを追加]** をクリックします。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/add-trigger.png)

1. **MQ**トリガータイプを選択します。

1. 必須のオプションを設定し、**[追加]** を選択します。

Lambda では、Amazon MQ イベントソースの以下のオプションがサポートされています。
+ **MQ ブローカー** — Amazon MQ ブローカーを選択します。
+ **バッチサイズ** - 単一のバッチで取得するメッセージの最大数を設定します。
+ **キュー名** - 使用する Amazon MQ キューを入力します。
+ **ソースアクセス設定** — 仮想ホスト情報とブローカーの認証情報を保存する Secrets Manager のシークレットを入力します。
+ **トリガーの有効化** - レコードの処理を停止するトリガーを無効にします。

トリガーを有効または無効にする（または削除する）には、 ** MQ ** トリガーをデザイナーで選択します。トリガーを再設定するには、イベントソースマッピング API 操作を使用します。

# イベントソースマッピングパラメータ
<a name="services-mq-params"></a>

すべての Lambda イベントソースタイプは、同じ[CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションを共有しています。ただし、Amazon MQ と RabbitMQ に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | メモ | 
| --- | --- | --- | --- | 
|  BatchSize  |  N  |  100  |  最大: 10,000  | 
|  有効  |  N  |  true  | なし | 
|  FunctionName  |  Y  | 該当なし  | なし | 
|  FilterCriteria  |  N  |  該当なし   |  [Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)  | 
|  MaximumBatchingWindowInSeconds  |  N  |  500 ミリ秒  |  [バッチ処理動作](invocation-eventsourcemapping.md#invocation-eventsourcemapping-batching)  | 
|  キュー  |  N  | 該当なし |  消費する Amazon MQ ブローカーの送信先キューの名前。  | 
|  SourceAccessConfigurations  |  N  | 該当なし  |  ActiveMQ の場合、BASIC\$1AUTH 認証情報です。RabbitMQ の場合、BASIC\$1AUTH 認証情報と VIRTUAL\$1HOST 情報の両方を含めることができます。  | 

# Amazon MQ イベントソースからのイベントをフィルタリングする
<a name="with-mq-filtering"></a>

イベントフィルタリングを使用して、Lambda が関数に送信するストリームまたはキューからのレコードを制御することができます。イベントフィルタリングの仕組みに関する一般情報については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

このセクションでは、Amazon MQ イベントソースのイベントフィルタリングに焦点を当てます。

**注記**  
Amazon MQ イベントソースマッピングは、 `data` キーでのフィルタリングのみをサポートします。

**Topics**
+ [Amazon MQ イベントフィルタリングの基本](#filtering-AMQ)

## Amazon MQ イベントフィルタリングの基本
<a name="filtering-AMQ"></a>

Amazon MQ メッセージキューには、有効な JSON 形式またはプレーン文字列でメッセージが含まれているとします。レコードの例は次のようになり、`data` フィールドでデータが Base64 でエンコードされた文字列に変換されます。

------
#### [ ActiveMQ ]

```
{ 
    "messageID": "ID:b-9bcfa592-423a-4942-879d-eb284b418fc8-1---mq---us-east-2.amazonaws.com.rproxy.goskope.com-37557-1234520418293-4:1:1:1:1", 
    "messageType": "jms/text-message",
    "deliveryMode": 1,
    "replyTo": null,
    "type": null,
    "expiration": "60000",
    "priority": 1,
    "correlationId": "myJMSCoID",
    "redelivered": false,
    "destination": { 
      "physicalName": "testQueue" 
    },
    "data":"QUJDOkFBQUE=",
    "timestamp": 1598827811958,
    "brokerInTime": 1598827811958, 
    "brokerOutTime": 1598827811959, 
    "properties": {
      "index": "1",
      "doAlarm": "false",
      "myCustomProperty": "value"
    }
}
```

------
#### [ RabbitMQ ]

```
{
    "basicProperties": {
        "contentType": "text/plain",
        "contentEncoding": null,
        "headers": {
            "header1": {
                "bytes": [
                  118,
                  97,
                  108,
                  117,
                  101,
                  49
                ]
            },
            "header2": {
                "bytes": [
                  118,
                  97,
                  108,
                  117,
                  101,
                  50
                ]
            },
            "numberInHeader": 10
        },
        "deliveryMode": 1,
        "priority": 34,
        "correlationId": null,
        "replyTo": null,
        "expiration": "60000",
        "messageId": null,
        "timestamp": "Jan 1, 1970, 12:33:41 AM",
        "type": null,
        "userId": "AIDACKCEVSQ6C2EXAMPLE",
        "appId": null,
        "clusterId": null,
        "bodySize": 80
        },
    "redelivered": false,
    "data": "eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ=="
}
```

------

Active MQ および Rabbit MQ ブローカーの両方では、イベントフィルタリングを使用して `data` キーを使用するレコードをフィルタリングできます。Amazon MQ キューに次の JSON 形式のメッセージが含まれているとします。

```
{
    "timeout": 0,
    "IPAddress": "203.0.113.254"
}
```

`timeout` フィールドが 0 より大きいレコードのみをフィルタリングするには、`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"data\" : { \"timeout\" : [ { \"numeric\": [ \">\", 0] } } ] } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "data": {
        "timeout": [ { "numeric": [ ">", 0 ] } ]
        }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従い、**[フィルター条件]** に次の文字列を入力します。

```
{ "data" : { "timeout" : [ { "numeric": [ ">", 0 ] } ] } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:mq:us-east-2:123456789012:broker:my-broker:b-8ac7cc01-5898-482d-be2f-a6b596050ea8 \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : { \"timeout\" : [ { \"numeric\": [ \">\", 0 ] } ] } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : { \"timeout\" : [ { \"numeric\": [ \">\", 0 ] } ] } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : { \"timeout\" : [ { \"numeric\": [ \">\", 0 ] } ] } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "data" : { "timeout" : [ { "numeric": [ ">", 0 ] } ] } }'
```

------

Amazon MQ を使用すると、メッセージがプレーン文字列のレコードをフィルタリングすることもできます。メッセージが「Result:」で始まるレコードのみを処理するとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"data\" : [ { \"prefix\": \"Result: \" } ] }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "data": [
        {
        "prefix": "Result: "
        }
    ]
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "data" : [ { "prefix": "Result: " } ] }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:mq:us-east-2:123456789012:broker:my-broker:b-8ac7cc01-5898-482d-be2f-a6b596050ea8 \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : [ { \"prefix\": \"Result: \" } ] }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"data\" : [ { \"prefix\": \"Result: \" } ] }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "data" : [ { "prefix": "Result " } ] }'
```

------

Amazon MQ メッセージは UTF-8 でエンコードされた文字列 (プレーン文字列または JSON 形式) である必要があります。これは、Lambda がフィルター条件を適用する前に Amazon MQ のバイト配列を UTF-8 にデコードするためです。メッセージが UTF-16 や ASCII などの別のエンコーディングを使用している場合、またはメッセージ形式が `FilterCriteria` 形式と一致しない場合、Lambda はメタデータフィルターのみを処理します。以下は、特定の動作を要約した表です。


| 着信メッセージの形式 | メッセージプロパティのフィルターパターン形式 | 結果として生じるアクション | 
| --- | --- | --- | 
|  プレーン文字列  |  プレーン文字列  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  プレーン文字列  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  プレーン文字列  |  有効な JSON  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  プレーン文字列  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  有効な JSON  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  UTF-8 以外でエンコードされた文字  |  JSON、プレーン文字列、またはパターンなし  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 

# Amazon MQ イベントソースマッピングエラーのトラブルシューティング
<a name="services-mq-errors"></a>

Lambda 関数で回復不可能なエラーが発生すると、Amazon MQ コンシューマーはレコードの処理を停止します。他のコンシューマーは、同じエラーが発生しない限り、処理を続行できます。コンシューマーが停止した原因を特定するには、`StateTransitionReason` から返された詳細の `EventSourceMapping` フィールドをチェックし、以下のいずれかのコードを探します。

**`ESM_CONFIG_NOT_VALID`**  
イベントソースマッピングの設定が無効です。

**`EVENT_SOURCE_AUTHN_ERROR`**  
Lambda がイベントソースの認証に失敗しました。

**`EVENT_SOURCE_AUTHZ_ERROR`**  
Lambda にイベントソースへのアクセス許可がありません。

**`FUNCTION_CONFIG_NOT_VALID`**  
関数の設定が無効です。

レコードは、サイズが原因で Lambda が削除した場合も、未処理になります。Lambda レコードのサイズ上限は 6 MB です。関数エラー時にメッセージを再配信するには、デッドレターキュー（DLQ）を使用します。詳細については、Apache ActiveMQ ウェブサイトの [Message Redelivery and DLQ Handling](https://activemq.apache.org/message-redelivery-and-dlq-handling) および RabbitMQ ウェブサイトの [Reliability Guide](https://www.rabbitmq.com/reliability.html) を参照してください。

**注記**  
Lambda はカスタム再配信ポリシーをサポートしていません。代わりに Lambda は、Apache ActiveMQ ウェブサイトの [Redelivery Policy](https://activemq.apache.org/redelivery-policy) ページのデフォルト値のポリシーを使用し、`maximumRedeliveries` は 6 に設定します。

# Amazon RDS で AWS Lambda 使用する
<a name="services-rds"></a>

Lambda 関数は、Amazon Relational Database Service (Amazon RDS) データベースに直接接続することも、Amazon RDS Proxy 経由で接続することもできます。単純なシナリオでは直接接続が有効で、本番環境ではプロキシの使用が推奨されます。データベースプロキシは、共有されたデータベース接続のプールを管理します。これを使用することで、データベース接続を消耗することなく、関数の同時実行レベルを上げることができます。

データベースへの短時間の接続を頻繁に実行したり、多数のデータベースへの接続を開閉したりする Lambda 関数には、Amazon RDS Proxy を使用することをお勧めします。詳細については、「Amazon Relational Database Service デベロッパーガイド」の「[Lambda 関数と DB インスタンスを自動的に接続する](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/lambda-rds-connect.html)」を参照してください。

**ヒント**  
Lambda 関数を Amazon RDS データベースにすばやく接続するには、コンソール内ガイドウィザードを使用できます。ウィザードを開くには、次の操作を行います。  
Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。
データベースを接続する関数を選択します。
**[設定]** タブで **[RDS データベース]** を選択します。
**[RDS データベースに接続]** を選択します。
関数をデータベースに接続したら、**[プロキシの追加]** を選択してプロキシを作成できます。

## RDS リソースを操作するように関数を設定する
<a name="rds-configuration"></a>

Lambda コンソールでは、Amazon RDS データベースのインスタンスおよびプロキシリソースのプロビジョニングおよび設定することができます。これを行うには、**[設定]** タブの **[RDS データベース]** に移動します。または、Amazon RDS コンソールで Lambda 関数への接続を作成して設定することもできます。Lambda で使用するように RDS データベースインスタンスを設定するときは、次の条件に注意してください。
+ データベースに接続するには、関数をデータベースが実行されているものと同じ Amazon VPC に置く必要があります。
+ Amazon RDS データベースは、MySQL、MariaDB、PostgreSQL、または Microsoft SQL Server エンジンで使用できます。
+ また、MySQL または PostgreSQL エンジンでは、Aurora DB クラスターも使用できます。
+ データベース認証用の Secrets Manager シークレットを用意する必要があります。
+ IAM ロールはシークレットを使用するためのアクセス許可を付与する必要があり、信頼ポリシーは Amazon RDS にロールの引き受けを許可する必要があります。
+  コンソールを使用して Amazon RDS リソースを設定し、それを関数に接続する IAM プリンシパルには、次のアクセス許可が必要です。

### アクセス許可ポリシーの例。
<a name="rds-lambda-permissions"></a>

**注記**  
 Amazon RDS Proxy のアクセス許可は、データベース接続のプールを管理するように Amazon RDS Proxy を設定する場合にのみ必要です。

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateSecurityGroup",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSubnets",
        "ec2:DescribeVpcs",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:AuthorizeSecurityGroupEgress",
        "ec2:RevokeSecurityGroupEgress",
        "ec2:CreateNetworkInterface",
        "ec2:DeleteNetworkInterface",
        "ec2:DescribeNetworkInterfaces"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds-db:connect",
        "rds:CreateDBProxy",
        "rds:CreateDBInstance",
        "rds:CreateDBSubnetGroup",
        "rds:DescribeDBClusters",
        "rds:DescribeDBInstances",
        "rds:DescribeDBSubnetGroups",
        "rds:DescribeDBProxies",
        "rds:DescribeDBProxyTargets",
        "rds:DescribeDBProxyTargetGroups",
        "rds:RegisterDBProxyTargets",
        "rds:ModifyDBInstance",
        "rds:ModifyDBProxy"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "lambda:CreateFunction",
        "lambda:ListFunctions",
        "lambda:UpdateFunctionConfiguration"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:AttachRolePolicy",
        "iam:CreateRole",
        "iam:CreatePolicy"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetResourcePolicy",
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret",
        "secretsmanager:ListSecretVersionIds",
        "secretsmanager:CreateSecret"
      ],
      "Resource": "*"
    }
  ]
}
```

------

Amazon RDS は、データベースインスタンスのサイズに基づいたプロキシの料金が時間単位で請求されます。詳細については、「[RDS プロキシの料金](https://aws.amazon.com/rds/proxy/pricing/)」をご覧ください。プロキシ接続についての全般的な詳細は、Amazon RDS User Guide の「[Using Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)」を参照してください。

### Amazon RDS 接続の SSL/TLS 要件
<a name="rds-lambda-certificates"></a>

Amazon RDS データベースインスタンスへの安全な SSL/TLS 接続を行うには、Lambda 関数が信頼できる証明書を使用してデータベースサーバーの ID を検証する必要があります。Lambda は、デプロイパッケージタイプに応じてこれらの証明書を異なる方法で処理します。
+ [.zip ファイルアーカイブ](configuration-function-zip.md): 証明書の処理はランタイムによって異なります。
  + **Node.js 18 以前**: Lambda には CA 証明書と RDS 証明書が自動的に含まれます。
  + **Node.js 20 以降**: Lambda でデフォルトで追加の CA 証明書がロードされなくなりました。`NODE_EXTRA_CA_CERTS` 環境変数を `/var/runtime/ca-cert.pem` に設定します。

  新しい AWS リージョン の Amazon RDS 証明書が Lambda マネージドランタイムに追加されるまでに、最大 4 週間かかる場合があります。
+ [コンテナイメージ](images-create.md): AWS ベースイメージには CA 証明書のみが含まれます。関数が Amazon RDS データベースインスタンスに接続する場合は、コンテナイメージに適切な証明書を含める必要があります。Dockerfile で、[データベースをホストする AWS リージョンに対応する証明書バンドルをダウンロードします。](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html#UsingWithRDS.SSL.CertificatesDownload)例:

  ```
  RUN curl https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem -o /us-east-1-bundle.pem
  ```

このコマンドは、Amazon RDS 証明書バンドルをダウンロードし、コンテナのルートディレクトリの絶対パス `/us-east-1-bundle.pem` に保存します。関数コードでデータベース接続を設定するときは、このパスを正確に参照する必要があります。例:

------
#### [ Node.js ]

Node.js データベースクライアントは、証明書ファイルへのパスだけでなく、メモリ内の実際の証明書コンテンツを必要とするため、`readFileSync` 関数が必要です。`readFileSync` がない場合、クライアントはパス文字列を証明書コンテンツとして解釈し、「証明書チェーン内の自己署名証明書」エラーが発生します。

**Example OCI 関数の Node.js 接続設定**  

```
import { readFileSync } from 'fs';

// ...

let connectionConfig = {
    host: process.env.ProxyHostName,
    user: process.env.DBUserName,
    password: token,
    database: process.env.DBName,
    ssl: {
        ca: readFileSync('/us-east-1-bundle.pem') // Load RDS certificate content from file into memory
    }
};
```

------
#### [ Python ]

**Example OCI 関数の Python 接続設定**  

```
connection = pymysql.connect(
    host=proxy_host_name,
    user=db_username,
    password=token,
    db=db_name,
    port=port,
    ssl={'ca': '/us-east-1-bundle.pem'}  #Path to the certificate in container
)
```

------
#### [ Java ]

JDBC 接続を使用する Java 関数の場合、接続文字列には以下を含める必要があります。
+ `useSSL=true`
+ `requireSSL=true`
+ コンテナイメージ内の Amazon RDS 証明書の場所を指す `sslCA` パラメータ

**Example OCI 関数の Java 接続文字列**  

```
// Define connection string
String connectionString = String.format("jdbc:mysql://%s:%s/%s?useSSL=true&requireSSL=true&sslCA=/us-east-1-bundle.pem", // Path to the certificate in container
        System.getenv("ProxyHostName"),
        System.getenv("Port"),
        System.getenv("DBName"));
```

------
#### [ .NET ]

**Example OCI 関数での MySQL 接続の .NET 接続文字列**  

```
/// Build the Connection String with the Token 
string connectionString = $"Server={Environment.GetEnvironmentVariable("RDS_ENDPOINT")};" +
                         $"Port={Environment.GetEnvironmentVariable("RDS_PORT")};" +
                         $"Uid={Environment.GetEnvironmentVariable("RDS_USERNAME")};" +
                         $"Pwd={authToken};" +
                         "SslMode=Required;" +
                         "SslCa=/us-east-1-bundle.pem";  // Path to the certificate in container
```

------
#### [ Go ]

MySQL 接続を使用する Go 関数の場合、Amazon RDS 証明書を証明書プールにロードし、MySQL ドライバーに登録します。次に、接続文字列は `tls` パラメータを使用してこの設定を参照する必要があります。

**Example OCI 関数での MySQL 接続の Go コード**  

```
import (
    "crypto/tls"
    "crypto/x509"
    "os"
    "github.com/go-sql-driver/mysql"
)

...

// Create certificate pool and register TLS config
rootCertPool := x509.NewCertPool()
pem, err := os.ReadFile("/us-east-1-bundle.pem")  // Path to the certificate in container
if err != nil {
    panic("failed to read certificate file: " + err.Error())
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
    panic("failed to append PEM")
}

mysql.RegisterTLSConfig("custom", &tls.Config{
    RootCAs: rootCertPool,
})

dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?allowCleartextPasswords=true&tls=custom",
    dbUser, authenticationToken, dbEndpoint, dbName,
)
```

------
#### [ Ruby ]

**Example OCI 関数の Ruby 接続設定**  

```
conn = Mysql2::Client.new(
    host: endpoint,
    username: user,
    password: token,
    port: port,
    database: db_name,
    sslca: '/us-east-1-bundle.pem',  # Path to the certificate in container
    sslverify: true
)
```

------

## Lambda 関数での Amazon RDS データベースへの接続
<a name="rds-connection"></a>

次のコード例は、Amazon RDS データベースに接続する Lambda 関数を実装する方法を示しています。この関数は、シンプルなデータベースリクエストを実行し、結果を返します。

**注記**  
これらのコード例は、[.zip デプロイパッケージ](configuration-function-zip.md)でのみ有効です。[コンテナイメージ](images-create.md)を使用して関数をデプロイする場合は、[前のセクション](#oci-certificate)で説明したように、関数コードで Amazon RDS 証明書ファイルを指定する必要があります。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda 関数での Amazon RDS データベースへの接続。  

```
using System.Data;
using System.Text.Json;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using MySql.Data.MySqlClient;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace aws_rds;

public class InputModel
{
    public string key1 { get; set; }
    public string key2 { get; set; }
}

public class Function
{
    /// <summary>
    // Handles the Lambda function execution for connecting to RDS using IAM authentication.
    /// </summary>
    /// <param name="input">The input event data passed to the Lambda function</param>
    /// <param name="context">The Lambda execution context that provides runtime information</param>
    /// <returns>A response object containing the execution result</returns>

    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        // Sample Input: {"body": "{\"key1\":\"20\", \"key2\":\"25\"}"}
        var input = JsonSerializer.Deserialize<InputModel>(request.Body);

        /// Obtain authentication token
        var authToken = RDSAuthTokenGenerator.GenerateAuthToken(
            Environment.GetEnvironmentVariable("RDS_ENDPOINT"),
            Convert.ToInt32(Environment.GetEnvironmentVariable("RDS_PORT")),
            Environment.GetEnvironmentVariable("RDS_USERNAME")
        );

        /// Build the Connection String with the Token 
        string connectionString = $"Server={Environment.GetEnvironmentVariable("RDS_ENDPOINT")};" +
                                  $"Port={Environment.GetEnvironmentVariable("RDS_PORT")};" +
                                  $"Uid={Environment.GetEnvironmentVariable("RDS_USERNAME")};" +
                                  $"Pwd={authToken};";


        try
        {
            await using var connection = new MySqlConnection(connectionString);
            await connection.OpenAsync();

            const string sql = "SELECT @param1 + @param2 AS Sum";

            await using var command = new MySqlCommand(sql, connection);
            command.Parameters.AddWithValue("@param1", int.Parse(input.key1 ?? "0"));
            command.Parameters.AddWithValue("@param2", int.Parse(input.key2 ?? "0"));

            await using var reader = await command.ExecuteReaderAsync();
            if (await reader.ReadAsync())
            {
                int result = reader.GetInt32("Sum");

                //Sample Response: {"statusCode":200,"body":"{\"message\":\"The sum is: 45\"}","isBase64Encoded":false}
                return new APIGatewayProxyResponse
                {
                    StatusCode = 200,
                    Body = JsonSerializer.Serialize(new { message = $"The sum is: {result}" })
                };
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }

        return new APIGatewayProxyResponse
        {
            StatusCode = 500,
            Body = JsonSerializer.Serialize(new { error = "Internal server error" })
        };
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
/*
Golang v2 code here.
*/

package main

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"os"

	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/feature/rds/auth"
	_ "github.com/go-sql-driver/mysql"
)

type MyEvent struct {
	Name string `json:"name"`
}

func HandleRequest(event *MyEvent) (map[string]interface{}, error) {

	var dbName string = os.Getenv("DatabaseName")
	var dbUser string = os.Getenv("DatabaseUser")
	var dbHost string = os.Getenv("DBHost") // Add hostname without https
	var dbPort int = os.Getenv("Port")      // Add port number
	var dbEndpoint string = fmt.Sprintf("%s:%d", dbHost, dbPort)
	var region string = os.Getenv("AWS_REGION")

	cfg, err := config.LoadDefaultConfig(context.TODO())
	if err != nil {
		panic("configuration error: " + err.Error())
	}

	authenticationToken, err := auth.BuildAuthToken(
		context.TODO(), dbEndpoint, region, dbUser, cfg.Credentials)
	if err != nil {
		panic("failed to create authentication token: " + err.Error())
	}

	dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=true&allowCleartextPasswords=true",
		dbUser, authenticationToken, dbEndpoint, dbName,
	)

	db, err := sql.Open("mysql", dsn)
	if err != nil {
		panic(err)
	}

	defer db.Close()

	var sum int
	err = db.QueryRow("SELECT ?+? AS sum", 3, 2).Scan(&sum)
	if err != nil {
		panic(err)
	}
	s := fmt.Sprint(sum)
	message := fmt.Sprintf("The selected sum is: %s", s)

	messageBytes, err := json.Marshal(message)
	if err != nil {
		return nil, err
	}

	messageString := string(messageBytes)
	return map[string]interface{}{
		"statusCode": 200,
		"headers":    map[string]string{"Content-Type": "application/json"},
		"body":       messageString,
	}, nil
}

func main() {
	lambda.Start(HandleRequest)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rdsdata.RdsDataClient;
import software.amazon.awssdk.services.rdsdata.model.ExecuteStatementRequest;
import software.amazon.awssdk.services.rdsdata.model.ExecuteStatementResponse;
import software.amazon.awssdk.services.rdsdata.model.Field;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class RdsLambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();

        try {
            // Obtain auth token
            String token = createAuthToken();

            // Define connection configuration
            String connectionString = String.format("jdbc:mysql://%s:%s/%s?useSSL=true&requireSSL=true",
                    System.getenv("ProxyHostName"),
                    System.getenv("Port"),
                    System.getenv("DBName"));

            // Establish a connection to the database
            try (Connection connection = DriverManager.getConnection(connectionString, System.getenv("DBUserName"), token);
                 PreparedStatement statement = connection.prepareStatement("SELECT ? + ? AS sum")) {

                statement.setInt(1, 3);
                statement.setInt(2, 2);

                try (ResultSet resultSet = statement.executeQuery()) {
                    if (resultSet.next()) {
                        int sum = resultSet.getInt("sum");
                        response.setStatusCode(200);
                        response.setBody("The selected sum is: " + sum);
                    }
                }
            }

        } catch (Exception e) {
            response.setStatusCode(500);
            response.setBody("Error: " + e.getMessage());
        }

        return response;
    }

    private String createAuthToken() {
        // Create RDS Data Service client
        RdsDataClient rdsDataClient = RdsDataClient.builder()
                .region(Region.of(System.getenv("AWS_REGION")))
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();

        // Define authentication request
        ExecuteStatementRequest request = ExecuteStatementRequest.builder()
                .resourceArn(System.getenv("ProxyHostName"))
                .secretArn(System.getenv("DBUserName"))
                .database(System.getenv("DBName"))
                .sql("SELECT 'RDS IAM Authentication'")
                .build();

        // Execute request and obtain authentication token
        ExecuteStatementResponse response = rdsDataClient.executeStatement(request);
        Field tokenField = response.records().get(0).get(0);

        return tokenField.stringValue();
    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
/* 
Node.js code here.
*/
// ES6+ example
import { Signer } from "@aws-sdk/rds-signer";
import mysql from 'mysql2/promise';

async function createAuthToken() {
  // Define connection authentication parameters
  const dbinfo = {

    hostname: process.env.ProxyHostName,
    port: process.env.Port,
    username: process.env.DBUserName,
    region: process.env.AWS_REGION,

  }

  // Create RDS Signer object
  const signer = new Signer(dbinfo);

  // Request authorization token from RDS, specifying the username
  const token = await signer.getAuthToken();
  return token;
}

async function dbOps() {

  // Obtain auth token
  const token = await createAuthToken();
  // Define connection configuration
  let connectionConfig = {
    host: process.env.ProxyHostName,
    user: process.env.DBUserName,
    password: token,
    database: process.env.DBName,
    ssl: 'Amazon RDS'
  }
  // Create the connection to the DB
  const conn = await mysql.createConnection(connectionConfig);
  // Obtain the result of the query
  const [res,] = await conn.execute('select ?+? as sum', [3, 2]);
  return res;

}

export const handler = async (event) => {
  // Execute database flow
  const result = await dbOps();
  // Return result
  return {
    statusCode: 200,
    body: JSON.stringify("The selected sum is: " + result[0].sum)
  }
};
```
TypeScript を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
import { Signer } from "@aws-sdk/rds-signer";
import mysql from 'mysql2/promise';

// RDS settings
// Using '!' (non-null assertion operator) to tell the TypeScript compiler that the DB settings are not null or undefined,
const proxy_host_name = process.env.PROXY_HOST_NAME!
const port = parseInt(process.env.PORT!)
const db_name = process.env.DB_NAME!
const db_user_name = process.env.DB_USER_NAME!
const aws_region = process.env.AWS_REGION!


async function createAuthToken(): Promise<string> {

    // Create RDS Signer object
    const signer = new Signer({
        hostname: proxy_host_name,
        port: port,
        region: aws_region,
        username: db_user_name
    });

    // Request authorization token from RDS, specifying the username
    const token = await signer.getAuthToken();
    return token;
}

async function dbOps(): Promise<mysql.QueryResult | undefined> {
    try {
        // Obtain auth token
        const token = await createAuthToken();
        const conn = await mysql.createConnection({
            host: proxy_host_name,
            user: db_user_name,
            password: token,
            database: db_name,
            ssl: 'Amazon RDS' // Ensure you have the CA bundle for SSL connection
        });
        const [rows, fields] = await conn.execute('SELECT ? + ? AS sum', [3, 2]);
        console.log('result:', rows);
        return rows;
    }
    catch (err) {
        console.log(err);
    }
}

export const lambdaHandler = async (event: any): Promise<{ statusCode: number; body: string }> => {
    // Execute database flow
    const result = await dbOps();

    // Return error is result is undefined
    if (result == undefined)
        return {
            statusCode: 500,
            body: JSON.stringify(`Error with connection to DB host`)
        }

    // Return result
    return {
        statusCode: 200,
        body: JSON.stringify(`The selected sum is: ${result[0].sum}`)
    };
};
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
<?php
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\Handler as StdHandler;
use Bref\Logger\StderrLogger;
use Aws\Rds\AuthTokenGenerator;
use Aws\Credentials\CredentialProvider;

require __DIR__ . '/vendor/autoload.php';

class Handler implements StdHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }


    private function getAuthToken(): string {
        // Define connection authentication parameters
        $dbConnection = [
            'hostname' => getenv('DB_HOSTNAME'),
            'port' => getenv('DB_PORT'),
            'username' => getenv('DB_USERNAME'),
            'region' => getenv('AWS_REGION'),
        ];

        // Create RDS AuthTokenGenerator object
        $generator = new AuthTokenGenerator(CredentialProvider::defaultProvider());

        // Request authorization token from RDS, specifying the username
        return $generator->createToken(
            $dbConnection['hostname'] . ':' . $dbConnection['port'],
            $dbConnection['region'],
            $dbConnection['username']
        );
    }

    private function getQueryResults() {
        // Obtain auth token
        $token = $this->getAuthToken();

        // Define connection configuration
        $connectionConfig = [
            'host' => getenv('DB_HOSTNAME'),
            'user' => getenv('DB_USERNAME'),
            'password' => $token,
            'database' => getenv('DB_NAME'),
        ];

        // Create the connection to the DB
        $conn = new PDO(
            "mysql:host={$connectionConfig['host']};dbname={$connectionConfig['database']}",
            $connectionConfig['user'],
            $connectionConfig['password'],
            [
                PDO::MYSQL_ATTR_SSL_CA => '/path/to/rds-ca-2019-root.pem',
                PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => true,
            ]
        );

        // Obtain the result of the query
        $stmt = $conn->prepare('SELECT ?+? AS sum');
        $stmt->execute([3, 2]);

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    /**
     * @param mixed $event
     * @param Context $context
     * @return array
     */
    public function handle(mixed $event, Context $context): array
    {
        $this->logger->info("Processing query");

        // Execute database flow
        $result = $this->getQueryResults();

        return [
            'sum' => $result['sum']
        ];
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
import json
import os
import boto3
import pymysql

# RDS settings
proxy_host_name = os.environ['PROXY_HOST_NAME']
port = int(os.environ['PORT'])
db_name = os.environ['DB_NAME']
db_user_name = os.environ['DB_USER_NAME']
aws_region = os.environ['AWS_REGION']


# Fetch RDS Auth Token
def get_auth_token():
    client = boto3.client('rds')
    token = client.generate_db_auth_token(
        DBHostname=proxy_host_name,
        Port=port
        DBUsername=db_user_name
        Region=aws_region
    )
    return token

def lambda_handler(event, context):
    token = get_auth_token()
    try:
        connection = pymysql.connect(
            host=proxy_host_name,
            user=db_user_name,
            password=token,
            db=db_name,
            port=port,
            ssl={'ca': 'Amazon RDS'}  # Ensure you have the CA bundle for SSL connection
        )
        
        with connection.cursor() as cursor:
            cursor.execute('SELECT %s + %s AS sum', (3, 2))
            result = cursor.fetchone()

        return result
        
    except Exception as e:
        return (f"Error: {str(e)}")  # Return an error message if an exception occurs
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
# Ruby code here.

require 'aws-sdk-rds'
require 'json'
require 'mysql2'

def lambda_handler(event:, context:)
  endpoint = ENV['DBEndpoint'] # Add the endpoint without https"
  port = ENV['Port']           # 3306
  user = ENV['DBUser']
  region = ENV['DBRegion']     # 'us-east-1'
  db_name = ENV['DBName']

  credentials = Aws::Credentials.new(
    ENV['AWS_ACCESS_KEY_ID'],
    ENV['AWS_SECRET_ACCESS_KEY'],
    ENV['AWS_SESSION_TOKEN']
  )
  rds_client = Aws::RDS::AuthTokenGenerator.new(
    region: region, 
    credentials: credentials
  )

  token = rds_client.auth_token(
    endpoint: endpoint+ ':' + port,
    user_name: user,
    region: region
  )

  begin
    conn = Mysql2::Client.new(
      host: endpoint,
      username: user,
      password: token,
      port: port,
      database: db_name,
      sslca: '/var/task/global-bundle.pem', 
      sslverify: true,
      enable_cleartext_plugin: true
    )
    a = 3
    b = 2
    result = conn.query("SELECT #{a} + #{b} AS sum").first['sum']
    puts result
    conn.close
    {
      statusCode: 200,
      body: result.to_json
    }
  rescue => e
    puts "Database connection failed due to #{e}"
  end
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-connect-rds-iam)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用した Lambda 関数での Amazon RDS データベースへの接続  

```
use aws_config::BehaviorVersion;
use aws_credential_types::provider::ProvideCredentials;
use aws_sigv4::{
    http_request::{sign, SignableBody, SignableRequest, SigningSettings},
    sign::v4,
};
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde_json::{json, Value};
use sqlx::postgres::PgConnectOptions;
use std::env;
use std::time::{Duration, SystemTime};

const RDS_CERTS: &[u8] = include_bytes!("global-bundle.pem");

async fn generate_rds_iam_token(
    db_hostname: &str,
    port: u16,
    db_username: &str,
) -> Result<String, Error> {
    let config = aws_config::load_defaults(BehaviorVersion::v2024_03_28()).await;

    let credentials = config
        .credentials_provider()
        .expect("no credentials provider found")
        .provide_credentials()
        .await
        .expect("unable to load credentials");
    let identity = credentials.into();
    let region = config.region().unwrap().to_string();

    let mut signing_settings = SigningSettings::default();
    signing_settings.expires_in = Some(Duration::from_secs(900));
    signing_settings.signature_location = aws_sigv4::http_request::SignatureLocation::QueryParams;

    let signing_params = v4::SigningParams::builder()
        .identity(&identity)
        .region(&region)
        .name("rds-db")
        .time(SystemTime::now())
        .settings(signing_settings)
        .build()?;

    let url = format!(
        "https://{db_hostname}:{port}/?Action=connect&DBUser={db_user}",
        db_hostname = db_hostname,
        port = port,
        db_user = db_username
    );

    let signable_request =
        SignableRequest::new("GET", &url, std::iter::empty(), SignableBody::Bytes(&[]))
            .expect("signable request");

    let (signing_instructions, _signature) =
        sign(signable_request, &signing_params.into())?.into_parts();

    let mut url = url::Url::parse(&url).unwrap();
    for (name, value) in signing_instructions.params() {
        url.query_pairs_mut().append_pair(name, &value);
    }

    let response = url.to_string().split_off("https://".len());

    Ok(response)
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    run(service_fn(handler)).await
}

async fn handler(_event: LambdaEvent<Value>) -> Result<Value, Error> {
    let db_host = env::var("DB_HOSTNAME").expect("DB_HOSTNAME must be set");
    let db_port = env::var("DB_PORT")
        .expect("DB_PORT must be set")
        .parse::<u16>()
        .expect("PORT must be a valid number");
    let db_name = env::var("DB_NAME").expect("DB_NAME must be set");
    let db_user_name = env::var("DB_USERNAME").expect("DB_USERNAME must be set");

    let token = generate_rds_iam_token(&db_host, db_port, &db_user_name).await?;

    let opts = PgConnectOptions::new()
        .host(&db_host)
        .port(db_port)
        .username(&db_user_name)
        .password(&token)
        .database(&db_name)
        .ssl_root_cert_from_pem(RDS_CERTS.to_vec())
        .ssl_mode(sqlx::postgres::PgSslMode::Require);

    let pool = sqlx::postgres::PgPoolOptions::new()
        .connect_with(opts)
        .await?;

    let result: i32 = sqlx::query_scalar("SELECT $1 + $2")
        .bind(3)
        .bind(2)
        .fetch_one(&pool)
        .await?;

    println!("Result: {:?}", result);

    Ok(json!({
        "statusCode": 200,
        "content-type": "text/plain",
        "body": format!("The selected sum is: {result}")
    }))
}
```

------

## Amazon RDS からのイベント通知を処理する
<a name="rds-events"></a>

Lambda を使用して、Amazon RDS データベースからのイベント通知を処理できます。Amazon RDS は、Amazon Simple Notification Service (Amazon SNS) トピックに通知を送信します。このトピックは Lambda 関数を呼び出すように設定することができます。Amazon SNS は、Amazon RDS からのメッセージを独自のイベントドキュメントにラップし、これを関数に送信します。

通知を送信するように Amazon RDS データベースを設定する方法の詳細については、「[Using Amazon RDS event notifications](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html)」を参照してください。

**Example Amazon SNS イベントでの Amazon RDS メッセージ**  

```
{
        "Records": [
          {
            "EventVersion": "1.0",
            "EventSubscriptionArn": "arn:aws:sns:us-east-2:123456789012:rds-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
            "EventSource": "aws:sns",
            "Sns": {
              "SignatureVersion": "1",
              "Timestamp": "2023-01-02T12:45:07.000Z",
              "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
              "SigningCertUrl": "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
              "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
              "Message": "{\"Event Source\":\"db-instance\",\"Event Time\":\"2023-01-02 12:45:06.000\",\"Identifier Link\":\"https://console.aws.amazon.com/rds/home?region=eu-west-1#dbinstance:id=dbinstanceid\",\"Source ID\":\"dbinstanceid\",\"Event ID\":\"http://docs.amazonwebservices.com/AmazonRDS/latest/UserGuide/USER_Events.html#RDS-EVENT-0002\",\"Event Message\":\"Finished DB Instance backup\"}",
              "MessageAttributes": {},
              "Type": "Notification",
              "UnsubscribeUrl": "https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
              "TopicArn":"arn:aws:sns:us-east-2:123456789012:sns-lambda",
              "Subject": "RDS Notification Message"
            }
          }
        ]
      }
```

## Lambda と Amazon RDS の完全なチュートリアル
<a name="rds-database-samples"></a>
+ [Lambda 関数を使用して Amazon RDS データベースにアクセスする](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html) – Amazon RDS ユーザーガイドで、Lambda 関数を使用して、Amazon RDS Proxy 経由で Amazon RDS データベースにデータを書き込む方法を学びます。Lambda 関数は、メッセージが追加されるたびに Amazon SQS キューからレコードを読み取り、データベース内のテーブルに新しい項目を書き込みます。

# Lambda ベースのアプリケーションのデータベースサービスを選択する
<a name="ddb-rds-database-decision"></a>

多くのサーバーレスアプリケーションは、データを保存および取得する必要があります。AWS には、Lambda 関数で動作する複数のデータベースオプションが用意されています。最も一般的な選択肢は、NoSQL データベースサービスである Amazon DynamoDB と、従来のリレーショナルデータベースソリューションである Amazon RDS の 2 つです。以下のセクションでは、Lambda で使用する際のこれらのサービスの主な違いについて説明します。これは、サーバーレスアプリケーションに適したデータベースサービスを選択するのに役立ちます。

AWS が提供する他のデータベースサービスの詳細を確認し、そのユースケースとトレードオフをより一般的に理解するには、「[Choosing an AWS database service](https://docs.aws.amazon.com/decision-guides/latest/databases-on-aws-how-to-choose/databases-on-aws-how-to-choose.html)」を参照してください。すべての AWS データベースサービスは Lambda と互換性がありますが、すべてのサービスが特定のユースケースに適しているとは限りません。

## Lambda を使用するデータベースサービスを選択する場合、どのような選択肢がありますか。
<a name="w2aad101d101c19b9"></a>

AWS は、複数のデータベースサービスを提供しています。サーバーレスアプリケーションの場合、最も一般的な選択肢は DynamoDB と Amazon RDS の 2 つです。
+ **DynamoDB** は、サーバーレスアプリケーション用に最適化されたフルマネージド NoSQL データベースサービスです。シームレスなスケーリングと 1 桁ミリ秒の安定したパフォーマンスをあらゆる規模で提供します。
+ **Amazon RDS** は、MySQL や PostgreSQL などの複数のデータベースエンジンをサポートするマネージドリレーショナルデータベースサービスです。マネージドインフラストラクチャで使い慣れた SQL 機能を提供します。

## 要件が既にわかっている場合の推奨事項
<a name="w2aad101d101c19c11"></a>

要件が既に明確な場合は、基本的な推奨事項を以下に示します。

一貫した低レイテンシーのパフォーマンスや自動スケーリングが必要で、複雑な結合やトランザクションが不要なサーバーレスアプリケーションには、[DynamoDB](with-ddb.md) をお勧めします。サーバーレスであるため、特に Lambda ベースのアプリケーションに適しています。

[Amazon RDS](services-rds.md) は、複雑な SQL クエリや結合が必要な場合、またはリレーショナルデータベースを使用する既存のアプリケーションがある場合に適しています。ただし、Lambda 関数を Amazon RDS に接続するには追加の設定が必要であり、コールドスタート時間に影響する可能性があることに注意してください。

## データベースサービスを選択する際の考慮事項
<a name="w2aad101d101c19c13"></a>

Lambda アプリケーション用に DynamoDB または Amazon RDS を選択するときは、次の要素を考慮してください。
+ 接続管理とコールドスタート
+ データアクセスパターン
+ クエリの複雑さ
+ データ整合性の要件
+ スケーリング特性
+ コストモデル

これらの要因を理解することで、特定のユースケースのニーズに最適なオプションを選択できます。

### 接続管理とコールドスタート
<a name="w2aad101d101c19c13b9b1"></a>
+ DynamoDB は、すべてのオペレーションに HTTP API を使用します。Lambda 関数は、接続を維持せずに即時リクエストを行うことができ、コールドスタートのパフォーマンスが向上します。各リクエストは、接続オーバーヘッドなしで AWS 認証情報を使用して認証されます。
+ Amazon RDS では、従来のデータベース接続を使用するため、接続プールの管理が必要です。新しい Lambda インスタンスが接続を確立する必要があるため、コールドスタートに影響する可能性があります。接続プーリング戦略を実装し、場合によっては [Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) を使用して接続を効果的に管理する必要があります。Amazon RDS Proxy を使用すると追加料金が発生することに注意してください。

### データアクセスパターン
<a name="w2aad101d101c19c13b9b3"></a>
+ DynamoDB は、既知のアクセスパターンと単一テーブルの設計に最適です。これは、プライマリキーまたはセカンダリインデックスに基づいたデータへの一貫した低レイテンシーアクセスを必要とする Lambda アプリケーションに最適です。
+ Amazon RDS は、複雑なクエリやアクセスパターンの変更に柔軟に対応します。Lambda 関数が複数のテーブルに対して一意のカスタマイズされたクエリまたは複雑な結合を実行する必要がある場合に適しています。

### クエリの複雑さ
<a name="w2aad101d101c19c13b9b5"></a>
+ DynamoDB は、シンプルなキーベースのオペレーションや事前定義されたアクセスパターンにおいて優れた力を発揮します。複雑なクエリはインデックス構造を中心に設計する必要があり、結合はアプリケーションコードで処理する必要があります。
+ Amazon RDS は、結合、サブクエリ、集計を含む複雑な SQL クエリをサポートします。これにより、複雑なデータオペレーションが必要な場合に Lambda 関数コードを簡素化できます。

### データ整合性の要件
<a name="w2aad101d101c19c13b9b7"></a>
+ DynamoDB は、結果整合性オプションと強力な整合性オプションの両方を提供し、1 つの項目の読み取りで強力な整合性を利用できます。トランザクションはサポートされていますが、いくつかの制限があります。
+ Amazon RDS は、完全なアトミック性、一貫性、分離性、耐久性 (ACID) コンプライアンスと複雑なトランザクションのサポートを提供します。Lambda 関数で複雑なトランザクションが必要な場合や、複数のレコード間で強力な整合性が必要な場合は、Amazon RDS の方が適していることがあります。

### スケーリング特性
<a name="w2aad101d101c19c13b9b9"></a>
+ DynamoDB はワークロードに合わせて自動的にスケーリングされます。事前プロビジョニングなしで Lambda 関数からのトラフィックの急増に対処できます。オンデマンドキャパシティモードを使用すると、Lambda のスケーリングモデルと完全に一致させて、使用した分のみの支払いにできます。
+ Amazon RDS には、選択したインスタンスサイズに基づいた固定容量があります。複数の Lambda 関数が同時に接続しようとすると、接続クォータを超える可能性があります。接続プールを慎重に管理し、場合によっては再試行ロジックを実装する必要があります。

### コストモデル
<a name="w2aad101d101c19c13b9c11"></a>
+ DynamoDB の料金体系は、サーバーレスアプリケーションに適しています。オンデマンド容量では、Lambda 関数によって実行された実際の読み取りと書き込みに対してのみ料金が発生します。アイドル時間には料金はかかりません。
+ Amazon RDS では、使用状況に関係なく、実行中のインスタンスに対して課金されます。これは、サーバーレスアプリケーションで一般的な散発的なワークロードではコスト効率が低下する可能性があります。ただし、使用量が一貫している高スループットのワークロードでは、より経済的になる可能性があります。

## 選択したデータベースサービスの開始方法
<a name="w2aad101d101c19c15"></a>

DynamoDB と Amazon RDS の選択基準とその主な違いについて確認した後は、ニーズに最適なオプションを選択し、以下のリソースを使用して利用を開始できます。

------
#### [ DynamoDB ]

**以下のリソースを使用して DynamoDB の使用を開始する**
+ DynamoDB サービスの概要については、「*Amazon DynamoDB デベロッパーガイド*」の「[DynamoDB とは](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html)」を参照してください。
+ 「[チュートリアル: API Gateway で Lambda を使用する](services-apigateway-tutorial.md)」に従って、Lambda 関数を使用して、API リクエストに応答して DynamoDB テーブルで CRUD オペレーションを実行する例を確認してください。
+ AWS SDK のいずれかを使用して Lambda 関数内から DynamoDB にアクセスする方法の詳細については、「*Amazon DynamoDB デベロッパーガイド*」の「[DynamoDB と AWS SDK を使用したプログラミング](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.html)」を参照してください。

------
#### [ Amazon RDS ]

**以下のリソースを使用して Amazon RDS の使用を開始する**
+ Amazon RDS サービスの概要については、「*Amazon Relational Database Service ユーザーガイド*」の「[Amazon Relational Database Service (Amazon RDS) とは](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html)」を参照してください。
+ 「*Amazon Relational Database Service ユーザーガイド*」の「[チュートリアル: Lambda 関数を使用して Amazon RDS にアクセスする](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-lambda-tutorial.html)」に従ってください。
+ Amazon RDS での Lambda の使用の詳細については、「[Amazon RDS で AWS Lambda 使用する](services-rds.md)」を参照してください。

------

# Lambda を使用した Amazon S3 イベント通知の処理
<a name="with-s3"></a>

Amazon Simple Storage Service からの[イベント通知](https://docs.aws.amazon.com/AmazonS3/latest/userguide/NotificationHowTo.html)は、Lambda を使用して処理することができます。Amazon S3 は、オブジェクトを作成または削除するときに、イベントを Lambda 関数に送信できます。バケットの通知設定を構成し、関数のリソースベースのアクセス許可ポリシーで関数を呼び出すためのアクセス許可を Amazon S3 に付与します。

**警告**  
 Lambda 関数で使用するバケットが、その関数をトリガーするのと同じバケットである場合、関数はループで実行される可能性があります。たとえば、オブジェクトがアップロードされるたびにバケットで関数をトリガーし、その関数によってオブジェクトがバケットにアップロードされると、その関数によって間接的にその関数自体がトリガーされます。これを回避するには、2 つのバケットを使用するか、受信オブジェクトで使用されるプレフィックスにのみ適用されるようにトリガーを設定します。

Amazon S3 は、オブジェクトに関する詳細を含むイベントで[非同期に](invocation-async.md)関数を呼び出します。次の例は、デプロイパッケージが Amazon S3 にアップロードされたときに Amazon S3 から送信されたイベントを示しています。

**Example Amazon S3 の通知イベント**  

```
{
  "Records": [
    {
      "eventVersion": "2.1",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-2",
      "eventTime": "2019-09-03T19:37:27.192Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
      },
      "requestParameters": {
        "sourceIPAddress": "205.255.255.255"
      },
      "responseElements": {
        "x-amz-request-id": "D82B88E5F771F645",
        "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
        "bucket": {
          "name": "amzn-s3-demo-bucket",
          "ownerIdentity": {
            "principalId": "A3I5XTEXAMAI3E"
          },
          "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
        },
        "object": {
          "key": "b21b84d653bb07b05b1e6b33684dc11b",
          "size": 1305107,
          "eTag": "b21b84d653bb07b05b1e6b33684dc11b",
          "sequencer": "0C0F6F405D6ED209E1"
        }
      }
    }
  ]
}
```

関数を呼び出すには、Amazon S3 には、関数の[リソースベースのポリシー](access-control-resource-based.md)によるアクセス許可が必要です。Lambda コンソールで Amazon S3 トリガーを設定すると、バケット名とアカウント ID が一致した場合に Amazon S3 で関数を呼び出せるように、コンソールでリソースベースのポリシーが変更されます。Amazon S3 の通知を設定する場合は、Lambda API を使用してこのポリシーを更新します。また、Lambda API を使用して、別のアカウントにアクセス許可を付与したり、指定されたエイリアスへのアクセス許可を制限したりできます。

関数で AWS SDK を使用して Amazon S3 リソースを管理する場合は、その[実行ロール](lambda-intro-execution-role.md)にも Amazon S3 のアクセス許可が必要です。

**Topics**
+ [チュートリアル: Amazon S3 トリガーを使用して Lambda 関数を呼び出す](with-s3-example.md)
+ [チュートリアル: Amazon S3 トリガーを使用してサムネイル画像を作成する](with-s3-tutorial.md)

# チュートリアル: Amazon S3 トリガーを使用して Lambda 関数を呼び出す
<a name="with-s3-example"></a>

このチュートリアルでは、コンソールを使用して Lambda 関数を作成し、Amazon Simple Storage Service (Amazon S3) バケットのトリガーを設定します。Amazon S3 バケットにオブジェクトを追加するたびに関数を実行し、Amazon CloudWatch Logs にオブジェクトタイプを出力します。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3_tut_config.png)


このチュートリアルでは、次の方法を示します。

1. Amazon S3 バケットを作成する。

1. Amazon S3 バケット内のオブジェクトのオブジェクトタイプを返す Lambda 関数を作成します。

1. オブジェクトがバケットにアップロードされたときに関数を呼び出す Lambda トリガーを設定します。

1. 最初にダミーイベントを使用して関数をテストし、次にトリガーを使用してテストします。

これらのステップを完了することにより、Amazon S3 バケットにオブジェクトが追加されたり、Amazon S3 バケットから削除されたりするたびに実行されるように Lambda 関数を設定する方法を学びます。AWS マネジメントコンソール のみを使って、このチュートリアルを完了できます。

## Amazon S3 バケットを作成する
<a name="with-s3-example-create-bucket"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps1.png)


**Amazon S3 バケットを作成するには**

1. [[Amazon S3 コンソール]](https://console.aws.amazon.com/s3) を開き、**[汎用バケット]** ページを選択します。

1. 住まいの地域に最も近い AWS リージョン を選択してください。画面上部にあるドロップダウンリストを使用して、リージョンを変更できます。チュートリアルの後半では、同じリージョンで Lambda 関数を作成する必要があります。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_region_select.png)

1. **[バケットを作成する]** を選択します。

1. **[全般設定]** で、次の操作を行います。

   1. **[バケットタイプ]** で、**[汎用]** が選択されていることを確認してください。

   1. **[バケット名]** には、Amazon S3 [バケットの命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)を満たすグローバルに一意な名前を入力します。バケット名は、小文字、数字、ドット (.)、およびハイフン (-) のみで構成できます。

1. 他のすべてのオプションはデフォルト設定値のままにしておき、**[バケットの作成]** を選択します。

## テストオブジェクトをバケットにアップロードする
<a name="with-s3-example-upload-test-object"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps2.png)


**テストオブジェクトをアップロードするには**

1. Amazon S3 コンソールの[バケット](https://console.aws.amazon.com/s3/buckets)ページを開き、前のステップで作成したバケットを選択します。

1. **[アップロード]** を選択します。

1. **[ファイルを追加]** を選択し、アップロードするファイルを選択します。任意のファイルを選択できます (例えば、`HappyFace.jpg`)。

1. **[開く]**、**[アップロード]** の順に選択します。

チュートリアルの後半では、このオブジェクトを使用して Lambda 関数をテストします。

## 許可ポリシーを作成する
<a name="with-s3-example-create-policy"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps3.png)


Lambda が Amazon S3 バケットからオブジェクトを取得し、Amazon CloudWatch Logs に書き込めるようにする許可ポリシーを作成します。

**ポリシーを作成するには**

1. IAM コンソールの[ポリシー](https://console.aws.amazon.com/iam/home#/policies)ページを開きます。

1. **[ポリシーの作成]** を選択します。

1. **[JSON]** タブを選択して、次のカスタムポリシーを JSON エディタに貼り付けます。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:PutLogEvents",
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream"
               ],
               "Resource": "arn:aws:logs:*:*:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           }
       ]
   }
   ```

------

1. **[次へ: タグ]** を選択します。

1. **[次へ: レビュー]** を選択します。

1. **[ポリシーの確認]** でポリシーの **[名前]** に「**s3-trigger-tutorial**」と入力します。

1. **[ポリシーの作成]** を選択します。

## 実行ロールを作成する
<a name="with-s3-example-create-role"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps4.png)


[実行ロール](lambda-intro-execution-role.md)とは、AWS のサービス およびリソースに対するアクセス許可を Lambda 関数に付与する AWS Identity and Access Management (IAM) のロールです。この手順では、前のステップで作成したアクセス権限ポリシーを使用して実行ロールを作成します。

**実行ロールを作成して、カスタム許可ポリシーをアタッチするには**

1. IAM コンソールの[ロールページ](https://console.aws.amazon.com/iam/home#/roles)を開きます。

1. **[ロールの作成]** を選択します。

1. 信頼されたエンティティには、**[AWS サービス]** を選択し、ユースケースには **[Lambda]** を選択します。

1. **[次へ]** をクリックします。

1. ポリシー検索ボックスに、「**s3-trigger-tutorial**」と入力します。

1. 検索結果で作成したポリシー (`s3-trigger-tutorial`) を選択し、**[次へ]** を選択します。

1. **[ロールの詳細]** で **[ロール名]** に **lambda-s3-trigger-role** を入力してから、**[ロールの作成]** を選択します。

## Lambda 関数を作成する
<a name="with-s3-example-create-function"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps5.png)


Python 3.14 ランタイムを使用してコンソールで Lambda 関数を作成します。

**Lambda 関数を作成するには**

1. Lambda コンソールの[関数](https://console.aws.amazon.com/lambda/home#/functions)ページを開きます。

1. Amazon S3 バケットを作成したときと同じ AWS リージョン で操作していることを確認してください。画面上部にあるドロップダウンリストを使用して、リージョンを変更できます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_region_select.png)

1. **[関数の作成]** を選択します。

1. **[一から作成]** を選択します。

1. **[基本的な情報]** で、以下を実行します。

   1. **[関数名]** に `s3-trigger-tutorial` と入力します。

   1. **[ランタイム]** には、**[Python 3.14]** を選択します。

   1. **[アーキテクチャ]** で **[x86\$164]** を選択します。

1. **[デフォルトの実行ロールの変更]** タブで、次の操作を行います。

   1. タブを展開し、**[既存のロールを使用する]** を選択します。

   1. 先ほど作成した `lambda-s3-trigger-role` を選択します。

1. [**関数の作成**] を選択してください。

## 関数コードをデプロイする
<a name="with-s3-example-deploy-code"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps6.png)


このチュートリアルは Python 3.14 ランタイムを使用しますが、他のランタイム用のサンプルコードのファイルも用意しています。次のボックスでタブを選択すると、関心のあるランタイムのコードが表示されます。

Lambda 関数は、Amazon S3 から受信する `event` パラメータから、アップロードされたオブジェクトのキー名およびバケットの名前を取得します。次に、関数は AWS SDK for Python (Boto3) から「[get\$1object](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3/client/get_object.html)」メソッドを使用し、アップロードされたオブジェクトのコンテンツタイプ (MIME タイプ) を含むオブジェクトのメタデータを取得します。

**関数コードをデプロイするには**

1. 次のボックスで **[Python]** タブを選択し、コードをコピーします。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
.NET を使用して Lambda で S3 イベントを消費します。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   ﻿using System.Threading.Tasks;
   using Amazon.Lambda.Core;
   using Amazon.S3;
   using System;
   using Amazon.Lambda.S3Events;
   using System.Web;
   
   // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
   [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
   
   namespace S3Integration
   {
       public class Function
       {
           private static AmazonS3Client _s3Client;
           public Function() : this(null)
           {
           }
   
           internal Function(AmazonS3Client s3Client)
           {
               _s3Client = s3Client ?? new AmazonS3Client();
           }
   
           public async Task<string> Handler(S3Event evt, ILambdaContext context)
           {
               try
               {
                   if (evt.Records.Count <= 0)
                   {
                       context.Logger.LogLine("Empty S3 Event received");
                       return string.Empty;
                   }
   
                   var bucket = evt.Records[0].S3.Bucket.Name;
                   var key = HttpUtility.UrlDecode(evt.Records[0].S3.Object.Key);
   
                   context.Logger.LogLine($"Request is for {bucket} and {key}");
   
                   var objectResult = await _s3Client.GetObjectAsync(bucket, key);
   
                   context.Logger.LogLine($"Returning {objectResult.Key}");
   
                   return objectResult.Key;
               }
               catch (Exception e)
               {
                   context.Logger.LogLine($"Error processing request - {e.Message}");
   
                   return string.Empty;
               }
           }
       }
   }
   ```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
Go を使用して Lambda で S3 イベントを消費します。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   package main
   
   import (
   	"context"
   	"log"
   
   	"github.com/aws/aws-lambda-go/events"
   	"github.com/aws/aws-lambda-go/lambda"
   	"github.com/aws/aws-sdk-go-v2/config"
   	"github.com/aws/aws-sdk-go-v2/service/s3"
   )
   
   func handler(ctx context.Context, s3Event events.S3Event) error {
   	sdkConfig, err := config.LoadDefaultConfig(ctx)
   	if err != nil {
   		log.Printf("failed to load default config: %s", err)
   		return err
   	}
   	s3Client := s3.NewFromConfig(sdkConfig)
   
   	for _, record := range s3Event.Records {
   		bucket := record.S3.Bucket.Name
   		key := record.S3.Object.URLDecodedKey
   		headOutput, err := s3Client.HeadObject(ctx, &s3.HeadObjectInput{
   			Bucket: &bucket,
   			Key:    &key,
   		})
   		if err != nil {
   			log.Printf("error getting head of object %s/%s: %s", bucket, key, err)
   			return err
   		}
   		log.Printf("successfully retrieved %s/%s of type %s", bucket, key, *headOutput.ContentType)
   	}
   
   	return nil
   }
   
   func main() {
   	lambda.Start(handler)
   }
   ```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
Java を使用した Lambda での S3 イベントの消費。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   package example;
   
   import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
   import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
   import software.amazon.awssdk.services.s3.S3Client;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import com.amazonaws.services.lambda.runtime.events.S3Event;
   import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification.S3EventNotificationRecord;
   
   import org.slf4j.Logger;
   import org.slf4j.LoggerFactory;
   
   public class Handler implements RequestHandler<S3Event, String> {
       private static final Logger logger = LoggerFactory.getLogger(Handler.class);
       @Override
       public String handleRequest(S3Event s3event, Context context) {
           try {
             S3EventNotificationRecord record = s3event.getRecords().get(0);
             String srcBucket = record.getS3().getBucket().getName();
             String srcKey = record.getS3().getObject().getUrlDecodedKey();
   
             S3Client s3Client = S3Client.builder().build();
             HeadObjectResponse headObject = getHeadObject(s3Client, srcBucket, srcKey);
   
             logger.info("Successfully retrieved " + srcBucket + "/" + srcKey + " of type " + headObject.contentType());
   
             return "Ok";
           } catch (Exception e) {
             throw new RuntimeException(e);
           }
       }
   
       private HeadObjectResponse getHeadObject(S3Client s3Client, String bucket, String key) {
           HeadObjectRequest headObjectRequest = HeadObjectRequest.builder()
                   .bucket(bucket)
                   .key(key)
                   .build();
           return s3Client.headObject(headObjectRequest);
       }
   }
   ```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
JavaScript を使用した Lambda での S3 イベントの消費。  

   ```
   import { S3Client, HeadObjectCommand } from "@aws-sdk/client-s3";
   
   const client = new S3Client();
   
   export const handler = async (event, context) => {
   
       // Get the object from the event and show its content type
       const bucket = event.Records[0].s3.bucket.name;
       const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
   
       try {
           const { ContentType } = await client.send(new HeadObjectCommand({
               Bucket: bucket,
               Key: key,
           }));
   
           console.log('CONTENT TYPE:', ContentType);
           return ContentType;
   
       } catch (err) {
           console.log(err);
           const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
           console.log(message);
           throw new Error(message);
       }
   };
   ```
TypeScript を使用した Lambda での S3 イベントの消費。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   import { S3Event } from 'aws-lambda';
   import { S3Client, HeadObjectCommand } from '@aws-sdk/client-s3';
   
   const s3 = new S3Client({ region: process.env.AWS_REGION });
   
   export const handler = async (event: S3Event): Promise<string | undefined> => {
     // Get the object from the event and show its content type
     const bucket = event.Records[0].s3.bucket.name;
     const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
     const params = {
       Bucket: bucket,
       Key: key,
     };
     try {
       const { ContentType } = await s3.send(new HeadObjectCommand(params));
       console.log('CONTENT TYPE:', ContentType);
       return ContentType;
     } catch (err) {
       console.log(err);
       const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
       console.log(message);
       throw new Error(message);
     }
   };
   ```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用して Lambda で S3 イベントの消費。  

   ```
   <?php
   
   use Bref\Context\Context;
   use Bref\Event\S3\S3Event;
   use Bref\Event\S3\S3Handler;
   use Bref\Logger\StderrLogger;
   
   require __DIR__ . '/vendor/autoload.php';
   
   
   class Handler extends S3Handler 
   {
       private StderrLogger $logger;
       public function __construct(StderrLogger $logger)
       {
           $this->logger = $logger;
       }
       
       public function handleS3(S3Event $event, Context $context) : void
       {
           $this->logger->info("Processing S3 records");
   
           // Get the object from the event and show its content type
           $records = $event->getRecords();
           
           foreach ($records as $record) 
           {
               $bucket = $record->getBucket()->getName();
               $key = urldecode($record->getObject()->getKey());
   
               try {
                   $fileSize = urldecode($record->getObject()->getSize());
                   echo "File Size: " . $fileSize . "\n";
                   // TODO: Implement your custom processing logic here
               } catch (Exception $e) {
                   echo $e->getMessage() . "\n";
                   echo 'Error getting object ' . $key . ' from bucket ' . $bucket . '. Make sure they exist and your bucket is in the same region as this function.' . "\n";
                   throw $e;
               }
           }
       }
   }
   
   $logger = new StderrLogger();
   return new Handler($logger);
   ```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
Python を使用して Lambda で S3 イベントを消費します。  

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier: Apache-2.0
   import json
   import urllib.parse
   import boto3
   
   print('Loading function')
   
   s3 = boto3.client('s3')
   
   
   def lambda_handler(event, context):
       #print("Received event: " + json.dumps(event, indent=2))
   
       # Get the object from the event and show its content type
       bucket = event['Records'][0]['s3']['bucket']['name']
       key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
       try:
           response = s3.get_object(Bucket=bucket, Key=key)
           print("CONTENT TYPE: " + response['ContentType'])
           return response['ContentType']
       except Exception as e:
           print(e)
           print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
           raise e
   ```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用して Lambda での S3 イベントの消費。  

   ```
   require 'json'
   require 'uri'
   require 'aws-sdk'
   
   puts 'Loading function'
   
   def lambda_handler(event:, context:)
     s3 = Aws::S3::Client.new(region: 'region') # Your AWS region
     # puts "Received event: #{JSON.dump(event)}"
   
     # Get the object from the event and show its content type
     bucket = event['Records'][0]['s3']['bucket']['name']
     key = URI.decode_www_form_component(event['Records'][0]['s3']['object']['key'], Encoding::UTF_8)
     begin
       response = s3.get_object(bucket: bucket, key: key)
       puts "CONTENT TYPE: #{response.content_type}"
       return response.content_type
     rescue StandardError => e
       puts e.message
       puts "Error getting object #{key} from bucket #{bucket}. Make sure they exist and your bucket is in the same region as this function."
       raise e
     end
   end
   ```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-s3-to-lambda)リポジトリで完全な例を検索し、設定および実行の方法を確認してください。
Rust を使用して Lambda で S3 イベントを消費します。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   use aws_lambda_events::event::s3::S3Event;
   use aws_sdk_s3::{Client};
   use lambda_runtime::{run, service_fn, Error, LambdaEvent};
   
   
   /// Main function
   #[tokio::main]
   async fn main() -> Result<(), Error> {
       tracing_subscriber::fmt()
           .with_max_level(tracing::Level::INFO)
           .with_target(false)
           .without_time()
           .init();
   
       // Initialize the AWS SDK for Rust
       let config = aws_config::load_from_env().await;
       let s3_client = Client::new(&config);
   
       let res = run(service_fn(|request: LambdaEvent<S3Event>| {
           function_handler(&s3_client, request)
       })).await;
   
       res
   }
   
   async fn function_handler(
       s3_client: &Client,
       evt: LambdaEvent<S3Event>
   ) -> Result<(), Error> {
       tracing::info!(records = ?evt.payload.records.len(), "Received request from SQS");
   
       if evt.payload.records.len() == 0 {
           tracing::info!("Empty S3 event received");
       }
   
       let bucket = evt.payload.records[0].s3.bucket.name.as_ref().expect("Bucket name to exist");
       let key = evt.payload.records[0].s3.object.key.as_ref().expect("Object key to exist");
   
       tracing::info!("Request is for {} and object {}", bucket, key);
   
       let s3_get_object_result = s3_client
           .get_object()
           .bucket(bucket)
           .key(key)
           .send()
           .await;
   
       match s3_get_object_result {
           Ok(_) => tracing::info!("S3 Get Object success, the s3GetObjectResult contains a 'body' property of type ByteStream"),
           Err(_) => tracing::info!("Failure with S3 Get Object request")
       }
   
       Ok(())
   }
   ```

------

1. Lambda コンソールの **[コードソース]** ペインで、コードをコードエディタに貼り付け、Lambda が作成したコードを置き換えます。

1. **[DEPLOY]** セクションで、**[デプロイ]** を選択して関数のコードを更新します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

## Amazon S3 トリガーを作成する
<a name="with-s3-example-create-trigger"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps7.png)


**Amazon S3 トリガーを作成するには**

1. **[関数の概要]** ペインで、**[トリガーを追加]** を選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/overview-trigger.png)

1. **[S3]** を選択します。

1. **[バケット]**で、前のチュートリアルで作成したバケットを選択します。

1. **[イベントタイプ]** で、**[すべてのオブジェクトの作成イベント]** を選択します。

1. **[再帰呼び出し]** でチェックボックスを選択して、入力と出力に同じ Amazon S3 バケットを使用することは推奨されないことを確認します。

1. **[Add]** (追加) を選択します。

**注記**  
Lambda コンソールを使用して Lambda 関数の Amazon S3 トリガーを作成すると、Amazon S3 は指定したバケットに対して[イベント通知](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html)を設定します。このイベント通知を設定する前に、Amazon S3 は一連のチェックを実行して、イベントの送信先が存在し、必要な IAM ポリシーがあることを確認します。また、Amazon S3 は、そのバケットに設定されている他のイベント通知に対してもこれらのテストを実行します。  
このチェックが行われるために、既に存在しないリソースや必要なアクセス許可ポリシーを持たないリソースのイベントの送信先がバケットで既に設定されている場合、Amazon S3 は新しいイベント通知を作成できません。トリガーを作成できなかったことを示す次のエラーメッセージが表示されます。  

```
An error occurred when creating the trigger: Unable to validate the following destination configurations.
```
このエラーは、以前に同じバケットを使用して別の Lambda 関数のトリガーを設定しており、その後に関数を削除したり、そのアクセス許可ポリシーを変更したりした場合に表示されます。

## Lambda 関数をダミーイベントでテストする
<a name="with-s3-example-test-dummy-event"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps8.png)


**Lambda 関数をダミーイベントでテストするには**

1. 関数の Lambda コンソールページで、**[テスト]** タブを選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/test-tab.png)

1. **イベント名**()で、`MyTestEvent` と入力します。

1. **[イベント JSON]** で、次のテストイベントを貼り付けます。次の値を必ず置き換えてください。
   + `us-east-1` を Amazon S3 バケットを作成したリージョンに置き換えます。
   + `amzn-s3-demo-bucket` の両方のインスタンスをお使いの Amazon S3 バケットの名前に置き換えます。
   + `test%2FKey` を前にバケットにアップロードしたテストオブジェクトの名前 (例えば、`HappyFace.jpg`) に置き換えます。

   ```
   {
     "Records": [
       {
         "eventVersion": "2.0",
         "eventSource": "aws:s3",
         "awsRegion": "us-east-1",
         "eventTime": "1970-01-01T00:00:00.000Z",
         "eventName": "ObjectCreated:Put",
         "userIdentity": {
           "principalId": "EXAMPLE"
         },
         "requestParameters": {
           "sourceIPAddress": "127.0.0.1"
         },
         "responseElements": {
           "x-amz-request-id": "EXAMPLE123456789",
           "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
         },
         "s3": {
           "s3SchemaVersion": "1.0",
           "configurationId": "testConfigRule",
           "bucket": {
             "name": "amzn-s3-demo-bucket",
             "ownerIdentity": {
               "principalId": "EXAMPLE"
             },
             "arn": "arn:aws:s3:::amzn-s3-demo-bucket"
           },
           "object": {
             "key": "test%2Fkey",
             "size": 1024,
             "eTag": "0123456789abcdef0123456789abcdef",
             "sequencer": "0A1B2C3D4E5F678901"
           }
         }
       }
     ]
   }
   ```

1. **[保存]** を選択します。

1. [**Test**] を選択します。

1. 関数が正常に実行されると、**[実行結果]** タブに次のような出力が表示されます。

   ```
   Response
   "image/jpeg"
   
   Function Logs
   START RequestId: 12b3cae7-5f4e-415e-93e6-416b8f8b66e6 Version: $LATEST
   2021-02-18T21:40:59.280Z    12b3cae7-5f4e-415e-93e6-416b8f8b66e6    INFO    INPUT BUCKET AND KEY:  { Bucket: 'amzn-s3-demo-bucket', Key: 'HappyFace.jpg' }
   2021-02-18T21:41:00.215Z    12b3cae7-5f4e-415e-93e6-416b8f8b66e6    INFO    CONTENT TYPE: image/jpeg
   END RequestId: 12b3cae7-5f4e-415e-93e6-416b8f8b66e6
   REPORT RequestId: 12b3cae7-5f4e-415e-93e6-416b8f8b66e6    Duration: 976.25 ms    Billed Duration: 977 ms    Memory Size: 128 MB    Max Memory Used: 90 MB    Init Duration: 430.47 ms        
   
   Request ID
   12b3cae7-5f4e-415e-93e6-416b8f8b66e6
   ```

### Amazon S3 トリガーを使用して Lambda 関数をテストする
<a name="with-s3-example-test-s3-trigger"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-example/s3trigger_tut_steps9.png)


設定したトリガーで関数をテストするには、コンソールを使用して Amazon S3 バケットにオブジェクトをアップロードします。Lambda 関数が予想通りに実行されたことを確認するには、CloudWatch Logs を使用して関数の出力を確認します。

**オブジェクトを Amazon S3 バケットにアップロードするには**

1. Amazon S3 コンソールの「[バケット](https://console.aws.amazon.com/s3/buckets)」ページを開き、先ほど作成したバケットを選択します。

1. **アップロード** を選択します。

1. **[ファイルを追加]** を選択し、ファイルセレクターを使用してアップロードするオブジェクトを選択します。このオブジェクトには任意のファイルを選択できます。

1. **[開く]**、**[アップロード]** の順に選択します。

**CloudWatch Logs を使用して関数の呼び出しを確認する方法**

1. [CloudWatch](https://console.aws.amazon.com/cloudwatch/home) コンソールを開きます。

1. Lambda 関数を作成したところと同じ AWS リージョン で操作していることを確認してください。画面上部にあるドロップダウンリストを使用して、リージョンを変更できます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_region_select.png)

1. **[ログ]**、**[ロググループ]** の順に選択します。

1. 関数のロググループの名前を選択します (`/aws/lambda/s3-trigger-tutorial`) 。

1. **[ログストリーム]** から、最新のログストリームを選択します。

1. Amazon S3 トリガーに応答して関数が正しく呼び出される場合、次のような内容と同じような出力が表示されます。表示される `CONTENT TYPE` は、バケットにアップロードしたファイルのタイプによって異なります。

   ```
   2022-05-09T23:17:28.702Z	0cae7f5a-b0af-4c73-8563-a3430333cc10	INFO	CONTENT TYPE: image/jpeg
   ```

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**S3 バケットを削除するには**

1. [Amazon S3 コンソール](https://console.aws.amazon.com//s3/home#)を開きます。

1. 作成したバケットを選択します。

1. [**削除**] を選択します。

1. テキスト入力フィールドにバケットの名前を入力します。

1. **[バケットを削除]** を選択します。

## 次のステップ
<a name="next-steps"></a>

[チュートリアル: Amazon S3 トリガーを使用してサムネイル画像を作成する](with-s3-tutorial.md) では、Amazon S3 トリガーが関数を呼び出します。この感想は、バケットにアップロードされる各イメージファイルにサムネイルイメージを作成します。このチュートリアルでは、AWS と Lambda ドメインに関する中級レベルの知識が必要です。AWS Command Line Interface (AWS CLI) を使用してリソースを作成し、関数およびその依存関係に .zip ファイルアーカイブのデプロイパッケージを作成する方法を示します。

# チュートリアル: Amazon S3 トリガーを使用してサムネイル画像を作成する
<a name="with-s3-tutorial"></a>

このチュートリアルでは、Amazon Simple Storage Service (Amazon S3) バケットに追加された画像のサイズを変更する Lambda 関数を作成および構成します。バケットに画像ファイルを追加すると、Amazon S3 は Lambda 関数を呼び出します。その後、この関数が画像のサムネイルバージョンを作成し、別の Amazon S3 バケットに出力します。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_resources.png)


このチュートリアルを完了するには、次のステップを実行します。

1. ソース元と保存先の Amazon S3 バケットを作成し、サンプル画像をアップロードします。

1. 画像のサイズを変更し、Amazon S3 バケットにサムネイルを出力する Lambda 関数 を作成します。

1. オブジェクトがソースバケットにアップロードされたときに、関数を呼び出す Lambda トリガーを設定します。

1. 最初にダミーイベントを使用して関数をテストし、その後画像をソースバケットにアップロードしてテストします。

これらのステップを完了することで、Lambda を使用して Amazon S3 バケットに追加されたオブジェクトに対してファイル処理タスクを実行する方法が分かるようになります。AWS Command Line Interface または AWS CLI(AWS マネジメントコンソール) を使って、このチュートリアルを完了できます。

Lambda 用に Amazon S3 トリガーを設定する方法を知るための、より簡単な例が必要であれば、「[チュートリアル: Amazon S3 トリガーを使用して Lambda 関数を呼び出す](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html)」をお試しください。

**Topics**
+ [前提条件](#with-s3-example-prereqs)
+ [2 つの Amazon S3 バケットを作成する](#with-s3-tutorial-prepare-create-buckets)
+ [テスト画像をソース元バケットにアップロードする](#with-s3-tutorial-test-image)
+ [許可ポリシーを作成する](#with-s3-tutorial-create-policy)
+ [実行ロールを作成する](#with-s3-tutorial-create-execution-role)
+ [関数デプロイパッケージを作成する](#with-s3-tutorial-create-function-package)
+ [Lambda 関数を作成する](#with-s3-tutorial-create-function-createfunction)
+ [関数を呼び出すように Amazon S3 を設定する](#with-s3-tutorial-configure-s3-trigger)
+ [Lambda 関数をダミーイベントでテストする](#with-s3-tutorial-dummy-test)
+ [Amazon S3 トリガーを使用して関数をテストする](#with-s3-tutorial-test-s3)
+ [リソースのクリーンアップ](#s3-tutorial-cleanup)

## 前提条件
<a name="with-s3-example-prereqs"></a>

AWS CLI を使用してチュートリアルを完了する場合は、[AWS Command Line Interface の最新バージョン]()をインストールしてください。

Lambda 関数コードには、Python または Node.js を使用できます。使用する言語の言語サポートツールとパッケージマネージャーをインストールします。

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## 2 つの Amazon S3 バケットを作成する
<a name="with-s3-tutorial-prepare-create-buckets"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps1.png)


まず、2 つの Amazon S3 バケットを作成します。1 つ目のバケットは、画像をアップロードするソースバケットです。2 つ目のバケットは、関数を呼び出したときにサイズ変更されたサムネイルを保存するために Lambda が使用するバケットです。

------
#### [ AWS マネジメントコンソール ]

**Amazon S3 バケットを作成する方法 (コンソール)**

1. [[Amazon S3 コンソール]](https://console.aws.amazon.com/s3) を開き、**[汎用バケット]** ページを選択します。

1. 住まいの地域に最も近い AWS リージョン を選択してください。画面上部にあるドロップダウンリストを使用して、リージョンを変更できます。チュートリアルの後半では、同じリージョンで Lambda 関数を作成する必要があります。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_region_select.png)

1. **[バケットを作成する]** を選択します。

1. **[全般設定]** で、次の操作を行います。

   1. **[バケットタイプ]** で、**[汎用]** が選択されていることを確認してください。

   1. **[バケット名]** には、Amazon S3 [バケットの命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)を満たすグローバルに一意な名前を入力します。バケット名は、小文字、数字、ドット (.)、およびハイフン (-) のみで構成できます。

1. 他のすべてのオプションはデフォルト設定値のままにしておき、**[バケットの作成]** を選択します。

1. ステップ 1 ～ 5 を繰り返して、送信先のバケットを作成します。**[バケット名]** には `amzn-s3-demo-source-bucket-resized` と入力します。`amzn-s3-demo-source-bucket` は先ほど作成したソース元バケットの名前です。

------
#### [ AWS CLI ]

**Amazon S3 バケットを作成する方法 (AWS CLI)**

1. 次の CLI コマンドを実行して、ソース元のバケットを作成します。バケットに付ける名前は、グローバルに一意で、Amazon S3 [バケットの命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)に従ったものである必要があります。名前には、小文字、数字、ドット (.)、およびハイフン (-) のみを使用できます。`region` および `LocationConstraint` については、お住まいの地域に最も近い [AWS リージョン](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) を選択してください。

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-source-bucket --region us-east-1 \
   --create-bucket-configuration LocationConstraint=us-east-1
   ```

   チュートリアルの後半では、ソース元バケットと同じ AWS リージョン で Lambda 関数を作成する必要があるため、選択したリージョンを書き留めておいてください。

1. 次のコマンドを実行して、送信先のバケットを作成します。バケット名には `amzn-s3-demo-source-bucket-resized` を使用する必要があります。`amzn-s3-demo-source-bucket` はステップ 1 で作成したソース元バケットの名前です。`region` および `LocationConstraint` については、ソース元バケットを作成するときに使用したものと同じ AWS リージョン を選択してください。

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-source-bucket-resized --region us-east-1 \
   --create-bucket-configuration LocationConstraint=us-east-1
   ```

------

## テスト画像をソース元バケットにアップロードする
<a name="with-s3-tutorial-test-image"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps2.png)


チュートリアルの後半では、AWS CLI または Lambda コンソールを使用して、Lambda 関数を呼び出してテストします。関数が正しく動作していることを確認するために、ソース元バケットにはテスト画像が含まれている必要があります。この画像には、任意の JPG または PNG ファイルを使用できます。

------
#### [ AWS マネジメントコンソール ]

**テスト画像をソース元バケットにアップロードする方法 (コンソール)**

1. Amazon S3 コンソールの[バケット](https://console.aws.amazon.com/s3/buckets)ページを開きます。

1. 前のステップで作成したソースバケットを選択します。

1. **[アップロード]** を選択します。

1. **[ファイルを追加]** を選択し、ファイルセレクターを使用してアップロードするオブジェクトを選択します。

1. **[開く]**、**[アップロード]** の順に選択します。

------
#### [ AWS CLI ]

**テスト画像をソース元バケットにアップロードする方法 (AWS CLI)**
+ アップロードする画像が含まれるディレクトリから、次の CLI コマンドを実行します。`--bucket` パラメータをソース元バケットの名前に置き換えます。`--key` および `--body` パラメータには、テスト画像のファイル名を使用します。

  ```
  aws s3api put-object --bucket amzn-s3-demo-source-bucket --key HappyFace.jpg --body ./HappyFace.jpg
  ```

------

## 許可ポリシーを作成する
<a name="with-s3-tutorial-create-policy"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps3.png)


Lambda 関数を作成するための最初のステップは、許可ポリシーを作成することです。このポリシーは、他の AWS リソースにアクセスするために必要となるアクセス許可を関数に付与します。このチュートリアルでは、ポリシーにより Lambda に Amazon S3 バケットの読み取り権限と書き込み権限が付与され、Amazon CloudWatch Logs に書き込めるようになります。

------
#### [ AWS マネジメントコンソール ]

**ポリシーを作成する方法 (コンソール)**

1. AWS Identity and Access Management (IAM) コンソールの [[Policies (ポリシー)] ページ](https://console.aws.amazon.com/iamv2/home#policies)を開きます。

1. [**Create policy**] (ポリシーの作成) を選択します。

1. **[JSON]** タブを選択して、次のカスタムポリシーを JSON エディタに貼り付けます。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:PutLogEvents",
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream"
               ],
               "Resource": "arn:aws:logs:*:*:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:PutObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           }
       ]
   }
   ```

1. [**次へ**] を選択します。

1. **[ポリシーの詳細]** で **[ポリシー名]** に「`LambdaS3Policy`」と入力します。

1. [**Create policy**] (ポリシーの作成) を選択します。

------
#### [ AWS CLI ]

**ポリシーを作成する方法 (AWS CLI)**

1. 次の JSON を `policy.json` という名のファイルに保存します。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:PutLogEvents",
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream"
               ],
               "Resource": "arn:aws:logs:*:*:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:PutObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           }
       ]
   }
   ```

1. JSON ポリシードキュメントを保存したディレクトリから、次の CLI コマンドを実行します。

   ```
   aws iam create-policy --policy-name LambdaS3Policy --policy-document file://policy.json
   ```

------

## 実行ロールを作成する
<a name="with-s3-tutorial-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps4.png)


実行ロールとは、AWS のサービス とリソースにアクセスする許可を Lambda 関数に付与する IAM ロールです。関数に Amazon S3 バケットへの読み取りおよび書き込みアクセス許可を付与するには、前のステップで作成した許可ポリシーをアタッチします。

------
#### [ AWS マネジメントコンソール ]

**実行ロールを作成して、許可ポリシーをアタッチする方法 (コンソール)**

1. (IAM) コンソールの [[ロール]](https://console.aws.amazon.com/iamv2/home#roles) ページを開きます。

1. [**ロールの作成**] を選択してください。

1. **[信頼できるエンティティタイプ]** で **AWS のサービス** を選択し、**[ユースケース]** では **[Lambda]** を選択します。

1. [**次へ**] を選択します。

1. 次の手順を実行して、前のステップで作成した許可ポリシーを追加します。

   1. ポリシー検索ボックスに、「`LambdaS3Policy`」と入力します。

   1. 検索結果内にある `LambdaS3Policy` のチェックボックスを選択します。

   1. [**次へ**] を選択します。

1. **[ロールの詳細]** にある **[ロール名]** には `LambdaS3Role` を入力します。

1. [**ロールの作成**] を選択してください。

------
#### [ AWS CLI ]

**実行ロールを作成して、許可ポリシーをアタッチする方法 (AWS CLI)**

1. 次の JSON を `trust-policy.json` という名のファイルに保存します。この信頼ポリシーは、AWS Security Token Service (AWS STS) `AssumeRole` アクションを呼び出すサービスプリンシパルの `lambda.amazonaws.com` アクセス許可を付与することで、Lambda がロールのアクセス許可を使用できるようにします。  
****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

1. JSON 信頼ポリシードキュメントを保存したディレクトリから、次の CLI コマンドを実行して実行ロールを作成します。

   ```
   aws iam create-role --role-name LambdaS3Role --assume-role-policy-document file://trust-policy.json
   ```

1. 次の CLI コマンドを実行して、前のステップで作成した許可ポリシーをアタッチします。ポリシーの ARN にある AWS アカウント 番号を、自分のアカウント番号へと置き換えます。

   ```
   aws iam attach-role-policy --role-name LambdaS3Role --policy-arn arn:aws:iam::123456789012:policy/LambdaS3Policy
   ```

------

## 関数デプロイパッケージを作成する
<a name="with-s3-tutorial-create-function-package"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps5.png)


関数を作成するには、関数コードとその依存関係を含むデプロイパッケージを作成します。この `CreateThumbnail` 関数では、関数コードで画像のサイズ変更に別のライブラリを使用します。選択した言語の指示に従って、必要なライブラリを含むデプロイパッケージを作成します。

------
#### [ Node.js ]

**デプロイパッケージを作成する方法 (Node.js)**

1. 関数コードと依存関係用に `lambda-s3` という名前のディレクトリを作成し、そこに移動します。

   ```
   mkdir lambda-s3
   cd lambda-s3
   ```

1. `npm` で新しい Node.js プロジェクトを作成します。インタラクティブな形式で提供されるデフォルトオプションを受け入れるには、`Enter` を押します。

   ```
   npm init
   ```

1. 以下の関数コードを `index.mjs` という名のファイルに保存します。必ず `us-east-1` を AWS リージョン (独自のソースバケットおよび宛先バケットを作成したもの) に置き換えてください。

   ```
   // dependencies
   import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
   
   import { Readable } from 'stream';
   
   import sharp from 'sharp';
   import util from 'util';
   
   
   // create S3 client
   const s3 = new S3Client({region: 'us-east-1'});
   
   // define the handler function
   export const handler = async (event, context) => {
   
   // Read options from the event parameter and get the source bucket
   console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
     const srcBucket = event.Records[0].s3.bucket.name;
     
   // Object key may have spaces or unicode non-ASCII characters
   const srcKey    = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
   const dstBucket = srcBucket + "-resized";
   const dstKey    = "resized-" + srcKey;
   
   // Infer the image type from the file suffix
   const typeMatch = srcKey.match(/\.([^.]*)$/);
   if (!typeMatch) {
     console.log("Could not determine the image type.");
     return;
   }
   
   // Check that the image type is supported
   const imageType = typeMatch[1].toLowerCase();
   if (imageType != "jpg" && imageType != "png") {
     console.log(`Unsupported image type: ${imageType}`);
     return;
   }
   
   // Get the image from the source bucket. GetObjectCommand returns a stream.
   try {
     const params = {
       Bucket: srcBucket,
       Key: srcKey
     };
     var response = await s3.send(new GetObjectCommand(params));
     var stream = response.Body;
     
   // Convert stream to buffer to pass to sharp resize function.
     if (stream instanceof Readable) {
       var content_buffer = Buffer.concat(await stream.toArray());
       
     } else {
       throw new Error('Unknown object stream type');
     }
   
   
   } catch (error) {
     console.log(error);
     return;
   }
   
     
   // set thumbnail width. Resize will set the height automatically to maintain aspect ratio.
   const width  = 200;
   
   // Use the sharp module to resize the image and save in a buffer.
   try {    
     var output_buffer = await sharp(content_buffer).resize(width).toBuffer();
   
   } catch (error) {
     console.log(error);
     return;
   }
   
   // Upload the thumbnail image to the destination bucket
   try {
     const destparams = {
       Bucket: dstBucket,
       Key: dstKey,
       Body: output_buffer,
       ContentType: "image"
     };
   
     const putResult = await s3.send(new PutObjectCommand(destparams));
   
     } catch (error) {
       console.log(error);
       return;
     }
   
     console.log('Successfully resized ' + srcBucket + '/' + srcKey +
       ' and uploaded to ' + dstBucket + '/' + dstKey);
     };
   ```

1. npm を使用して、`lambda-s3` ディレクトリに sharp ライブラリをインストールします。sharp の最新バージョン (0.33) は Lambda と互換性がないことに注意してください。このチュートリアルを完了するには、バージョン 0.32.6 をインストールしてください。

   ```
   npm install sharp@0.32.6
   ```

   npm `install` コマンドによって、モジュール用の `node_modules` ディレクトリが作成されます。このステップ完了後のディレクトリ構造は、次のようになります。

   ```
   lambda-s3
   |- index.mjs
   |- node_modules
   |  |- base64js
   |  |- bl
   |  |- buffer
   ...
   |- package-lock.json
   |- package.json
   ```

1. 関数コードと依存関係が含まれる.zip ファイル形式のデプロイパッケージを作成します。MacOS および Linux では、次のコマンドを実行します。

   ```
   zip -r function.zip .
   ```

   Windows では、任意の zip ツールを使用して .zip ファイルを作成します。`index.mjs`、`package.json`、`package-lock.json` ファイルと `node_modules` ディレクトリがすべて、.zip ファイルのルートにあることを確認します。

------
#### [ Python ]

**デプロイパッケージを作成する方法 (Python)**

1. サンプルコードをファイル名 `lambda_function.py` で保存します。

   ```
   import boto3
   import os
   import sys
   import uuid
   from urllib.parse import unquote_plus
   from PIL import Image
   import PIL.Image
               
   s3_client = boto3.client('s3')
               
   def resize_image(image_path, resized_path):
     with Image.open(image_path) as image:
       image.thumbnail(tuple(x / 2 for x in image.size))
       image.save(resized_path)
               
   def lambda_handler(event, context):
     for record in event['Records']:
       bucket = record['s3']['bucket']['name']
       key = unquote_plus(record['s3']['object']['key'])
       tmpkey = key.replace('/', '')
       download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
       upload_path = '/tmp/resized-{}'.format(tmpkey)
       s3_client.download_file(bucket, key, download_path)
       resize_image(download_path, upload_path)
       s3_client.upload_file(upload_path, '{}-resized'.format(bucket), 'resized-{}'.format(key))
   ```

1. `lambda_function.py` ファイルを作成したのと同じディレクトリに、`package` という名前の新しいディレクトリを作成し、[Pillow (PIL)](https://pypi.org/project/Pillow/) ライブラリと AWS SDK for Python (Boto3) をインストールします。Lambda Python ランタイムには Boto3 SDK のあるバージョンが含まれていますが、ランタイムに含まれている場合でも、関数の依存関係はすべてデプロイパッケージに追加することをお勧めします。詳細については、「[Python のランタイム依存関係](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-dependencies)」を参照してください。

   ```
   mkdir package
   pip install \
   --platform manylinux2014_x86_64 \
   --target=package \
   --implementation cp \
   --python-version 3.12 \
   --only-binary=:all: --upgrade \
   pillow boto3
   ```

   Pillow ライブラリには C/C\$1\$1 コードが含まれています。`--platform manylinux_2014_x86_64` および `--only-binary=:all:` のオプションを使用すると、pip は Amazon Linux 2 オペレーティングシステムと互換性のあるプリコンパイル済みバイナリを含むバージョンの Pillow をダウンロードしてインストールします。これにより、ローカルビルドマシンのオペレーティングシステムやアーキテクチャに関係なく、デプロイパッケージが Lambda 実行環境で動作することが保証されます。

1. アプリケーションコードと Pillow および Boto3 ライブラリを含む .zip ファイルを作成します。Linux または MacOS では、コマンドラインインターフェイスから次のコマンドを実行します。

   ```
   cd package
   zip -r ../lambda_function.zip .
   cd ..
   zip lambda_function.zip lambda_function.py
   ```

    Windows では、任意の zip ツールを使用して、`lambda_function.zip` ファイルを作成します。`lambda_function.py` ファイルと依存関係が含まれるフォルダは、.zip ファイルのルートにインストールする必要があります。

また、Python 仮想環境を使用してデプロイパッケージを作成することもできます。「[Python Lambda 関数で .zip ファイルアーカイブを使用する](python-package.md)」を参照してください。

------

## Lambda 関数を作成する
<a name="with-s3-tutorial-create-function-createfunction"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps6.png)


AWS CLI または Lambda コンソールを使用して、Lambda 関数を作成することができます。選択した言語の指示に従って関数を作成します。

------
#### [ AWS マネジメントコンソール ]

**関数を作成するには (コンソール)**

コンソールを使用して Lambda 関数を作成するには、まず「Hello world」コードが含まれるベーシックな関数を作成します。次に、前のステップで作成した .zip または JAR ファイルをアップロードして、このコードを自身で作成した関数コードへと置き換えます。

1. Lambda コンソールの[関数](https://console.aws.amazon.com/lambda/home#/functions)ページを開きます。

1. Amazon S3 バケットを作成したときと同じ AWS リージョン で操作していることを確認してください。画面上部にあるドロップダウンリストを使用して、リージョンを変更できます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/console_region_select.png)

1. **関数の作成** を選択します。

1. **Author from scratch** を選択します。

1. **基本的な情報** で、以下の作業を行います。

   1. **[関数名]** に「`CreateThumbnail`」と入力します。

   1. **[ランタイム]** には、関数に選択した言語に応じて **[Node.js 22.x]** または **[Python 3.12]** を選択します。

   1. **[アーキテクチャ]** で **[x86\$164]** を選択します。

1. **[デフォルトの実行ロールの変更]** タブで、次の操作を行います。

   1. タブを展開し、**[既存のロールを使用する]** を選択します。

   1. 先ほど作成した `LambdaS3Role` を選択します。

1. [**関数の作成**] を選択してください。

**関数コードをアップロードする方法 (コンソール)**

1. **[コードソース]** ペインで、**[アップロード元]** をクリックします。

1. **[.zip ファイル]** をクリックします。

1. **アップロード** を選択します。

1. ファイルセレクターで .zip ファイルを選択し、**[開く]** を選択します。

1. **[保存]** を選択します。

------
#### [ AWS CLI ]

**関数を作成する方法 (AWS CLI)**
+ 選択した言語の CLI コマンドを実行します。`role` パラメータでは、`123456789012` を自分自身の AWS アカウント ID へと置き換えます。`region` パラメータでは、`us-east-1` を Amazon S3 バケットを作成したリージョンへと置き換えます。
  + **Node.js** の場合は、`function.zip` ファイルが含まれるディレクトリから次のコマンドを実行します。

    ```
    aws lambda create-function --function-name CreateThumbnail \
    --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
    --timeout 10 --memory-size 1024 \
    --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-1
    ```
  + **Python** の場合は、`lambda_function.zip` ファイルが含まれるディレクトリから次のコマンドを実行します。

    ```
    aws lambda create-function --function-name CreateThumbnail \
    --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler \
    --runtime python3.14 --timeout 10 --memory-size 1024 \
    --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-1
    ```

------

## 関数を呼び出すように Amazon S3 を設定する
<a name="with-s3-tutorial-configure-s3-trigger"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps7.png)


ソース元のバケットに画像をアップロードしたときに Lambda 関数を実行するには、関数のトリガーを設定する必要があります。Amazon S3 トリガーは、コンソールまたは AWS CLI を使用して設定できます。

**重要**  
この手順では、オブジェクトがバケット内に作成されるたびに関数を呼び出すように、Amazon S3 バケットを設定します。この設定は、ソース元バケットのみで行うようにしてください。Lambda 関数が自身を呼び出した同じバケットにオブジェクトを作成する場合、関数が[連続的にループして呼び出される](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)可能性があります。その結果、予期しない請求がお客様の AWS アカウント に請求される可能性があります。

------
#### [ AWS マネジメントコンソール ]

**Amazon S3 トリガーを設定する方法 (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、関数を選択します (`CreateThumbnail`)。

1. **[トリガーを追加]** を選択します。

1. **[S3]** を選択します。

1. **[バケット]** で、ソース元のバケットを選択します。

1. **[イベントタイプ]** で、**[すべてのオブジェクト作成イベント]** を選択します。

1. **[再帰呼び出し]** でチェックボックスを選択して、入力と出力に同じ Amazon S3 バケットを使用することは推奨されないことを確認します。Lambda の再帰呼び出しパターンについて詳しくは、Serverless Land の「[Lambda 関数が暴走する原因となる再帰パターン](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)」を参照してください。

1. **[Add]** (追加) を選択します。

   Lambda コンソールを使用してトリガーを作成すると、Lambda は[リソースベースのポリシー](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)を自動的に作成し、選択したサービスに関数を呼び出すアクセス許可を付与します。

------
#### [ AWS CLI ]

**Amazon S3 トリガーを設定する方法 (AWS CLI)**

1. 画像ファイルを追加したときに Amazon S3 ソース元バケットが関数を呼び出すようにするには、まずは[リソースベースのポリシー](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)を使用して関数への権限を設定する必要があります。リソースベースのポリシーステートメントが、他の AWS のサービス に関数を呼び出す権限を付与します。Amazon S3 に関数を呼び出す権限を付与するには、次の CLI コマンドを実行します。`source-account` パラメータは必ず自分自身の AWS アカウント ID に置き換えて、自分自身のソース元バケット名を使用するようにしてください。

   ```
   aws lambda add-permission --function-name CreateThumbnail \
   --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" \
   --source-arn arn:aws:s3:::amzn-s3-demo-source-bucket \
   --source-account 123456789012
   ```

   このコマンドで定義するポリシーにより、Amazon S3 はソース元バケットでアクションが発生した場合にのみ、関数を呼び出すことができるようになります。
**注記**  
Amazon S3 のバケット名は世界的に一意ですが、リソースベースのポリシーを使用する場合には、バケットがアカウントに属していなければならないことを指定するのがベストプラクティスです。これは、バケットを削除したときに、別の AWS アカウント が同じ Amazon リソースネーム (ARN) でバケットを作成する可能性があるからです。

1. 次の JSON を `notification.json` という名のファイルに保存します。この JSON をソースバケットに適用すると、新しいオブジェクトが追加されるたびに Lambda 関数に通知を送信するようにバケットが設定されます。Lambda 関数 ARN の AWS アカウント 番号と AWS リージョン を、自分自身のアカウント番号とリージョンへと置き換えます。

   ```
   {
   "LambdaFunctionConfigurations": [
       {
         "Id": "CreateThumbnailEventConfiguration",
         "LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:CreateThumbnail",
         "Events": [ "s3:ObjectCreated:Put" ]
       }
     ]
   }
   ```

1. 次の CLI コマンドを実行して、JSON ファイル内に作成した通知設定をソース元のバケットに適用します。`amzn-s3-demo-source-bucket` を自分自身のソース元バケットの名前へと置き換えます。

   ```
   aws s3api put-bucket-notification-configuration --bucket amzn-s3-demo-source-bucket \
   --notification-configuration file://notification.json
   ```

   `put-bucket-notification-configuration` コマンドと `notification-configuration` オプションの詳細については、「AWS CLI コマンドリファレンス」の「[put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html)」を参照してください。

------

## Lambda 関数をダミーイベントでテストする
<a name="with-s3-tutorial-dummy-test"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps8.png)


Amazon S3 ソース元バケットに画像ファイルを追加してセットアップ全体をテストする前に、ダミーイベントで Lambda 関数を呼び出して正しく動作するかどうかをテストします。Lambda 内のイベントは、関数が処理するデータが含まれる JSON 形式のドキュメントです。Amazon S3 によって関数が呼び出されたとき、関数に送信されるイベントには、バケット名、バケット ARN、オブジェクトキーなどの情報が含まれます。

------
#### [ AWS マネジメントコンソール ]

**Lambda 関数をダミーイベントでテストする方法 (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開き、関数を選択します (`CreateThumbnail`)。

1. **[テスト]** タブを選択します。

1. テストイベントを作成するには、**[テストイベント]** ペインで次の操作を行います。

   1. **[テストイベントアクション]** で、**[新しいイベントを作成]** を選択します。

   1. **イベント名**()で、**myTestEvent** と入力します。

   1. **[テンプレート]** で **[S3 Put]** を選択します。

   1. 次のパラメータの値を自分自身の値へと置き換えます。
      + `awsRegion` では、`us-east-1` を Amazon S3 バケットを作成した AWS リージョン へと置き換えます。
      + `name` では、`amzn-s3-demo-bucket` を自分自身の Amazon S3 ソース元バケットの名前へと置き換えます。
      + `key` では、`test%2Fkey` を [テスト画像をソース元バケットにアップロードする](#with-s3-tutorial-test-image) ステップでソース元バケットにアップロードしたテストオブジェクトのファイル名へと置き換えます。

      ```
      {
        "Records": [
          {
            "eventVersion": "2.0",
            "eventSource": "aws:s3",
            "awsRegion": "us-east-1",
            "eventTime": "1970-01-01T00:00:00.000Z",
            "eventName": "ObjectCreated:Put",
            "userIdentity": {
              "principalId": "EXAMPLE"
            },
            "requestParameters": {
              "sourceIPAddress": "127.0.0.1"
            },
            "responseElements": {
              "x-amz-request-id": "EXAMPLE123456789",
              "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
            },
            "s3": {
              "s3SchemaVersion": "1.0",
              "configurationId": "testConfigRule",
              "bucket": {
                "name": "amzn-s3-demo-bucket",
                "ownerIdentity": {
                  "principalId": "EXAMPLE"
                },
                "arn": "arn:aws:s3:::amzn-s3-demo-bucket"
              },
              "object": {
                "key": "test%2Fkey",
                "size": 1024,
                "eTag": "0123456789abcdef0123456789abcdef",
                "sequencer": "0A1B2C3D4E5F678901"
              }
            }
          }
        ]
      }
      ```

   1. **[保存]** を選択します。

1. **[テストイベント]** ペインで **[テスト]** を選択します。

1. 関数によってサイズ変更した画像が作成され、送信先の Amazon S3 バケットに保存されたかどうかを確認するには、以下を実行してください。

   1. Amazon S3 コンソールの [[バケットページ]](https://console.aws.amazon.com/s3/buckets) を開きます。

   1. 送信先のバケットを選択し、サイズ変更したファイルが **[オブジェクト]** ペインに表示されていることを確認します。

------
#### [ AWS CLI ]

**Lambda 関数をダミーイベントでテストする方法 (AWS CLI)**

1. 次の JSON を `dummyS3Event.json` という名のファイルに保存します。次のパラメータの値を自分自身の値へと置き換えます。
   + `awsRegion` では、`us-east-1` を Amazon S3 バケットを作成した AWS リージョン へと置き換えます。
   + `name` では、`amzn-s3-demo-bucket` を自分自身の Amazon S3 ソース元バケットの名前へと置き換えます。
   + `key` では、`test%2Fkey` を [テスト画像をソース元バケットにアップロードする](#with-s3-tutorial-test-image) ステップでソース元バケットにアップロードしたテストオブジェクトのファイル名へと置き換えます。

   ```
   {
     "Records": [
       {
         "eventVersion": "2.0",
         "eventSource": "aws:s3",
         "awsRegion": "us-east-1",
         "eventTime": "1970-01-01T00:00:00.000Z",
         "eventName": "ObjectCreated:Put",
         "userIdentity": {
           "principalId": "EXAMPLE"
         },
         "requestParameters": {
           "sourceIPAddress": "127.0.0.1"
         },
         "responseElements": {
           "x-amz-request-id": "EXAMPLE123456789",
           "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
         },
         "s3": {
           "s3SchemaVersion": "1.0",
           "configurationId": "testConfigRule",
           "bucket": {
             "name": "amzn-s3-demo-bucket",
             "ownerIdentity": {
               "principalId": "EXAMPLE"
             },
             "arn": "arn:aws:s3:::amzn-s3-demo-bucket"
           },
           "object": {
             "key": "test%2Fkey",
             "size": 1024,
             "eTag": "0123456789abcdef0123456789abcdef",
             "sequencer": "0A1B2C3D4E5F678901"
           }
         }
       }
     ]
   }
   ```

1. `dummyS3Event.json` ファイルを保存したディレクトリから、次の CLI コマンドを実行して関数を呼び出します。このコマンドは、`RequestResponse` を呼び出しタイプパラメータの値として指定することにより、Lambda 関数を同期的に呼び出します。同期呼び出しと非同期呼び出しの詳細については、[「Lambda 関数の呼び出し」](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)を参照してください。

   ```
   aws lambda invoke --function-name CreateThumbnail \
   --invocation-type RequestResponse --cli-binary-format raw-in-base64-out \
   --payload file://dummyS3Event.json outputfile.txt
   ```

   AWS CLI のバージョン 2 を使用している場合は、cli-binary-format オプションが必要です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)を参照してください。

1. 関数が画像のサムネイルバージョンを作成し、それを送信先の Amazon S3 バケットに保存していることを確認します。`amzn-s3-demo-source-bucket-resized` を自分自身の送信先のバケットの名前へと置き換えて、次の CLI コマンドを実行します。

   ```
   aws s3api list-objects-v2 --bucket amzn-s3-demo-source-bucket-resized
   ```

   次のような出力が表示されます。`Key` パラメータには、サイズ変更された画像ファイルのファイル名が表示されます。

   ```
   {
       "Contents": [
           {
               "Key": "resized-HappyFace.jpg",
               "LastModified": "2023-06-06T21:40:07+00:00",
               "ETag": "\"d8ca652ffe83ba6b721ffc20d9d7174a\"",
               "Size": 2633,
               "StorageClass": "STANDARD"
           }
       ]
   }
   ```

------

## Amazon S3 トリガーを使用して関数をテストする
<a name="with-s3-tutorial-test-s3"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps9.png)


Lambda 関数が正しく動作していることを確認した後は、Amazon S3 ソース元バケットに画像ファイルを追加して、セットアップ全体をテストします。ソース元バケットに画像を追加すると、Lambda 関数が自動的に呼び出されるはずです。関数がファイルのサイズを変更したバージョンを作成し、送信先のバケットに保存します。

------
#### [ AWS マネジメントコンソール ]

**Amazon S3 トリガーを使用して Lambda 関数をテストする方法 (コンソール)**

1. 画像を Amazon S3 バケットにアップロードするには、以下を実行します。

   1. Amazon S3 コンソールの[[バケット]](https://console.aws.amazon.com/s3/buckets) ページを開き、ソース元のバケットを選択します。

   1. **アップロード** を選択します。

   1. **[ファイルを追加]** を選択し、ファイルセレクターを使用してアップロードする画像ファイルを選択します。画像オブジェクトには、任意の .jpg ファイルまたは.png ファイルを使用できます。

   1. **[開く]**、**[アップロード]** の順に選択します。

1. 以下を実行して、Lambda が画像ファイルのサイズを変更したバージョンを送信先のバケットに保存したことを確認します。

   1. Amazon S3 コンソールの [[バケット]](https://console.aws.amazon.com/s3/buckets) ページに戻り、送信先バケットを選択します。

   1. **[オブジェクト]** ペインに、Lambda 関数に対する各テストで 1 つずつ作成された、合計 2 つのサイズ変更された画像ファイルが表示されるはずです。サイズを変更した画像をダウンロードするには、ファイルを選択してから **[Download]** を選択します。

------
#### [ AWS CLI ]

**Amazon S3 トリガーを使用して Lambda 関数をテストする方法 (AWS CLI)**

1. アップロードする画像が含まれるディレクトリから、次の CLI コマンドを実行します。`--bucket` パラメータをソース元バケットの名前に置き換えます。`--key` および `--body` パラメータには、テスト画像のファイル名を使用します。テスト画像には、任意の .jpg ファイルまたは .png ファイルを使用できます。

   ```
   aws s3api put-object --bucket amzn-s3-demo-source-bucket --key SmileyFace.jpg --body ./SmileyFace.jpg
   ```

1. 関数が画像のサムネイルバージョンを作成し、それを送信先の Amazon S3 バケットに保存していることを確認します。`amzn-s3-demo-source-bucket-resized` を自分自身の送信先のバケットの名前へと置き換えて、次の CLI コマンドを実行します。

   ```
   aws s3api list-objects-v2 --bucket amzn-s3-demo-source-bucket-resized
   ```

   関数が正常に実行されると、以下に類似した出力が表示されます。これで、送信先のバケットに、サイズ変更されたファイルが 2 つ含まれるはずです。

   ```
   {
       "Contents": [
           {
               "Key": "resized-HappyFace.jpg",
               "LastModified": "2023-06-07T00:15:50+00:00",
               "ETag": "\"7781a43e765a8301713f533d70968a1e\"",
               "Size": 2763,
               "StorageClass": "STANDARD"
           },
           {
               "Key": "resized-SmileyFace.jpg",
               "LastModified": "2023-06-07T00:13:18+00:00",
               "ETag": "\"ca536e5a1b9e32b22cd549e18792cdbc\"",
               "Size": 1245,
               "StorageClass": "STANDARD"
           }
       ]
   }
   ```

------

## リソースのクリーンアップ
<a name="s3-tutorial-cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**作成したポリシーを削除する**

1. IAM コンソールの [[Policies (ポリシー)]](https://console.aws.amazon.com/iam/home#/policies) ページを開きます。

1. 作成したポリシー (**AWSLambdaS3Policy**) を選択します。

1. [**ポリシーアクション**]、[**削除**] の順に選択します。

1. [**削除**] を選択します。

**実行ロールを削除するには**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**S3 バケットを削除するには**

1. [Amazon S3 コンソール](https://console.aws.amazon.com//s3/home#)を開きます。

1. 作成したバケットを選択します。

1. [**削除**] を選択します。

1. テキスト入力フィールドにバケットの名前を入力します。

1. **[バケットの削除]** を選択します。

# Lambda 関数で Secrets Manager シークレットを使用する
<a name="with-secrets-manager"></a>

AWS Secrets Manager は、Lambda 関数に必要な認証情報、API キー、およびその他のシークレットを管理するのに役立ちます。Lambda 関数でシークレットを取得するには、次に示すとおり、主に 2 つのアプローチがあり、AWS SDK を使用してシークレットを直接取得するよりもパフォーマンスが向上し、コストを削減できます。
+ **AWS Parameters and Secrets Lambda Extension** - シークレットを取得するためのシンプルな HTTP インターフェイスを提供するランタイムに依存しないソリューション
+ **Powertools for AWS Lambda パラメータユーティリティ** - 組み込み変換で複数のプロバイダー (Secrets Manager、Parameter Store、AppConfig) をサポートするコード統合ソリューション

いずれのアプローチもシークレットのローカルキャッシュを保持します。このため、呼び出しのたびに関数が Secrets Manager を呼び出す必要がなくなります。関数でシークレットをリクエストすると、最初にそのキャッシュがチェックされます。シークレットが利用可能で、有効期限が切れていない場合は、すぐに返されます。それ以外の場合は、Secrets Manager から取得、キャッシュしたのちに、返されます。このキャッシュメカニズムにより、API コールが最小限に抑えられます。その結果、応答時間が短縮し、コストが減少します。

## アプローチの選択
<a name="lambda-secrets-manager-choosing-approach"></a>

拡張機能と PowerTools のいずれかを選択するときは、次の要素を考慮してください。

以下の場合、AWS Parameters and Secrets Lambda Extension を使用する:  
+ 任意の Lambda ランタイムで動作するランタイムに依存しないソリューションが必要な場合
+ 関数にコードの依存関係を追加したくない場合
+ Secrets Manager または Parameter Store からシークレットを取得するだけで済む場合

以下の場合、Powertools for AWS Lambda Parameters を使用する:  
+ アプリケーションコードと統合された開発エクスペリエンスが必要な場合
+ 複数のプロバイダー (Secrets Manager、Parameter Store、AppConfig) のサポートが必要な場合
+ 組み込みのデータ変換 (JSON 解析、base64 デコード) が必要な場合
+ Python、TypeScript、Java、または .NET ランタイムを使用している場合

## Lambda で Secrets Manager を使用する状況
<a name="lambda-secrets-manager-when-to-use"></a>

Lambda で Secrets Manager を使用する一般的なシナリオは次のとおりです。
+ 関数が Amazon RDS または他のデータベースに接続するために使用するデータベース認証情報を保存する
+ 関数が呼び出す外部サービスの API キーを管理する
+ 暗号化キーやその他の機密設定データを保存する
+ 関数コードの更新を必要とせずに認証情報を自動的にローテーションする

## AWS Parameters and Secrets Lambda Extension の使用
<a name="lambda-secrets-manager-extension-approach"></a>

AWS Parameters and Secrets Lambda Extension は、すべての Lambda ランタイムと互換性のあるシンプルな HTTP インターフェイスを使用します。デフォルトでは、シークレットを 300 秒 (5 分) キャッシュし、最大 1,000 個のシークレットを保持できます。[これらの設定は環境変数でカスタマイズ](#lambda-secrets-manager-env-vars)できます。

### Lambda 関数で Secrets Manager を使用する
<a name="lambda-secrets-manager-setup"></a>

このセクションでは、Secrets Manager シークレットが既に存在していることを前提としています。シークレットを作成するには、「[AWS Secrets Manager シークレットの作成](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)」を参照してください。

#### デプロイパッケージの作成
<a name="lambda-secrets-manager-function-code"></a>

好みのランタイムを選択し、Secrets Manager からシークレットを取得する関数の作成手順に従います。サンプル関数は、Secrets Manager からシークレットを取得するもので、アプリケーション内のデータベース認証情報、API キー、またはその他の機密設定データにアクセスするために使用できます。

------
#### [ Python ]

**Python 関数を作成するには**

1. 新しいプロジェクトディレクトリを作成し、そこに移動します。例:

   ```
   mkdir my_function
   cd my_function
   ```

1. `lambda_function.py` という名前のファイルを作成し、次のコードを記述します。`secret_name` には、シークレットの名前または Amazon リソースネーム (ARN) を使用します。

   ```
   import json
   import os
   import requests
   
   def lambda_handler(event, context):
       try:
           # Replace with the name or ARN of your secret
           secret_name = "arn:aws:secretsmanager:us-east-1:111122223333:secret:SECRET_NAME"
           
           secrets_extension_endpoint = f"http://localhost:2773/secretsmanager/get?secretId={secret_name}"
           headers = {"X-Aws-Parameters-Secrets-Token": os.environ.get('AWS_SESSION_TOKEN')}
           
           response = requests.get(secrets_extension_endpoint, headers=headers)
           print(f"Response status code: {response.status_code}")
           
           secret = json.loads(response.text)["SecretString"]
           print(f"Retrieved secret: {secret}")
           
           return {
               'statusCode': response.status_code,
               'body': json.dumps({
                   'message': 'Successfully retrieved secret',
                   'secretRetrieved': True
               })
           }
       
       except Exception as e:
           print(f"Error: {str(e)}")
           return {
               'statusCode': 500,
               'body': json.dumps({
                   'message': 'Error retrieving secret',
                   'error': str(e)
               })
           }
   ```

1. `requirements.txt` という名前のファイルを作成し、次の内容を記述します。

   ```
   requests
   ```

1. 依存関係をインストールします。

   ```
   pip install -r requirements.txt -t .
   ```

1. すべてのファイルを含む .zip ファイルを作成します。

   ```
   zip -r function.zip .
   ```

------
#### [ Node.js ]

**Node.js 関数を作成するには**

1. 新しいプロジェクトディレクトリを作成し、そこに移動します。例:

   ```
   mkdir my_function
   cd my_function
   ```

1. `index.mjs` という名前のファイルを作成し、次のコードを記述します。`secret_name` には、シークレットの名前または Amazon リソースネーム (ARN) を使用します。

   ```
   import http from 'http';
   
   export const handler = async (event) => {
       try {
           // Replace with the name or ARN of your secret
           const secretName = "arn:aws:secretsmanager:us-east-1:111122223333:secret:SECRET_NAME";
           const options = {
               hostname: 'localhost',
               port: 2773,
               path: `/secretsmanager/get?secretId=${secretName}`,
               headers: {
                   'X-Aws-Parameters-Secrets-Token': process.env.AWS_SESSION_TOKEN
               }
           };
   
           const response = await new Promise((resolve, reject) => {
               http.get(options, (res) => {
                   let data = '';
                   res.on('data', (chunk) => { data += chunk; });
                   res.on('end', () => {
                       resolve({ 
                           statusCode: res.statusCode, 
                           body: data 
                       });
                   });
               }).on('error', reject);
           });
   
           const secret = JSON.parse(response.body).SecretString;
           console.log('Retrieved secret:', secret);
   
           return {
               statusCode: response.statusCode,
               body: JSON.stringify({
                   message: 'Successfully retrieved secret',
                   secretRetrieved: true
               })
           };
       } catch (error) {
           console.error('Error:', error);
           return {
               statusCode: 500,
               body: JSON.stringify({
                   message: 'Error retrieving secret',
                   error: error.message
               })
           };
       }
   };
   ```

1. `index.mjs` ファイルを含む .zip ファイルを作成します。

   ```
   zip -r function.zip index.mjs
   ```

------
#### [ Java ]

**Java 関数を作成するには**

1. Maven プロジェクトを作成します。

   ```
   mvn archetype:generate \
       -DgroupId=example \
       -DartifactId=lambda-secrets-demo \
       -DarchetypeArtifactId=maven-archetype-quickstart \
       -DarchetypeVersion=1.4 \
       -DinteractiveMode=false
   ```

1. プロジェクトディレクトリに移動します。

   ```
   cd lambda-secrets-demo
   ```

1. `pom.xml` を開き、内容を次に置き換えます。

   ```
   <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
   
       <groupId>example</groupId>
       <artifactId>lambda-secrets-demo</artifactId>
       <version>1.0-SNAPSHOT</version>
   
       <properties>
           <maven.compiler.source>11</maven.compiler.source>
           <maven.compiler.target>11</maven.compiler.target>
       </properties>
   
       <dependencies>
           <dependency>
               <groupId>com.amazonaws</groupId>
               <artifactId>aws-lambda-java-core</artifactId>
               <version>1.2.1</version>
           </dependency>
       </dependencies>
   
       <build>
           <plugins>
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-shade-plugin</artifactId>
                   <version>3.2.4</version>
                   <executions>
                       <execution>
                           <phase>package</phase>
                           <goals>
                               <goal>shade</goal>
                           </goals>
                           <configuration>
                               <createDependencyReducedPom>false</createDependencyReducedPom>
                               <finalName>function</finalName>
                           </configuration>
                       </execution>
                   </executions>
               </plugin>
           </plugins>
       </build>
   </project>
   ```

1. `/lambda-secrets-demo/src/main/java/example/App.java` の名前を、Lambda のデフォルトの Java ハンドラ名 (`example.Hello::handleRequest`) と一致するように `Hello.java` に変更します。

   ```
   mv src/main/java/example/App.java src/main/java/example/Hello.java
   ```

1. `Hello.java` ファイルを開き、内容を次に置き換えます。`secretName` には、シークレットの名前または Amazon リソースネーム (ARN) を使用します。

   ```
   package example;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import java.net.URI;
   import java.net.http.HttpClient;
   import java.net.http.HttpRequest;
   import java.net.http.HttpResponse;
   
   public class Hello implements RequestHandler<Object, String> {
       private final HttpClient client = HttpClient.newHttpClient();
   
       @Override
       public String handleRequest(Object input, Context context) {
           try {
               // Replace with the name or ARN of your secret
               String secretName = "arn:aws:secretsmanager:us-east-1:111122223333:secret:SECRET_NAME";
               String endpoint = "http://localhost:2773/secretsmanager/get?secretId=" + secretName;
   
               HttpRequest request = HttpRequest.newBuilder()
                   .uri(URI.create(endpoint))
                   .header("X-Aws-Parameters-Secrets-Token", System.getenv("AWS_SESSION_TOKEN"))
                   .GET()
                   .build();
   
               HttpResponse<String> response = client.send(request, 
                   HttpResponse.BodyHandlers.ofString());
   
               String secret = response.body();
               secret = secret.substring(secret.indexOf("SecretString") + 15);
               secret = secret.substring(0, secret.indexOf("\""));
   
               System.out.println("Retrieved secret: " + secret);
               return String.format(
                   "{\"statusCode\": %d, \"body\": \"%s\"}",
                   response.statusCode(), "Successfully retrieved secret"
               );
   
           } catch (Exception e) {
               e.printStackTrace();
               return String.format(
                   "{\"body\": \"Error retrieving secret: %s\"}", 
                   e.getMessage()
               );
           }
       }
   }
   ```

1. テストディレクトリを削除します。Maven はこれをデフォルトで作成しますが、この例では必要ありません。

   ```
   rm -rf src/test
   ```

1. プロジェクトをビルドします。

   ```
   mvn package
   ```

1. JAR ファイル (`target/function.jar`) を後で使用するためにダウンロードします。

------

#### 関数を作成する
<a name="lambda-secrets-manager-create"></a>

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. [**関数の作成**] を選択してください。

1. **[一から作成]** を選択します。

1. **[関数名]** に「**secret-retrieval-demo**」と入力します。

1. 好みの **[ランタイム]** を選択します。

1. [**関数の作成**] を選択してください。

**デプロイパッケージをアップロードするには**

1. 関数の **[コード]** タブで、**[アップロード元]** を選択して **[.zip ファイル]** (Python および Node.js の場合) または **[.jar ファイル]** (Java の場合) を選択します。

1. 前に作成したデプロイパッケージをアップロードします。

1. **[保存]** を選択します。

#### 拡張機能を追加する
<a name="lambda-secrets-manager-extension"></a>

**AWS パラメータとシークレット Lambda 拡張機能をレイヤーとして追加するには**

1. 関数の **[コード]** タブで、**[レイヤー]** まで下にスクロールします。

1. **[レイヤーを追加]** を選択します。

1. **[AWS レイヤー]** を選択します。

1. **[AWS-Parameters-and-Secrets-Lambda-Extension]** を選択します。

1. 最新バージョンを選択します。

1. **[Add]** (追加) を選択します。

#### アクセス許可を追加する
<a name="lambda-secrets-manager-permissions"></a>

**実行ロールに Secrets Manager アクセス許可を追加するには**

1. **[設定]** タブを開き、次に **[アクセス権限]** をクリックします。

1. **[実行ロール]** で、実行ロールのリンクを選択します。このリンクを選択すると、IAM コンソールでロールが開きます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/execution-role-console.png)

1. **[アクセス権限を追加]**、**[インラインポリシーを作成]** の順に選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/create-inline-policy.png)

1. **[JSON]** タブを選択して次のポリシーを追加します。`Resource` には、シークレットの ARN を入力します。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "secretsmanager:GetSecretValue",
               "Resource": "arn:aws:secretsmanager:us-east-1:111122223333:secret:SECRET_NAME"
           }
       ]
   }
   ```

------

1. [**次へ**] を選択します。

1. ポリシーの名前を入力します。

1. [**Create policy**] (ポリシーの作成) を選択します。

#### 関数をテストする
<a name="lambda-secrets-manager-test"></a>

**関数をテストするには**

1. Lambda コンソールに戻ります。

1. **[テスト]** タブを選択します。

1. **[テスト]** を選択します。以下のようなレスポンスが表示されます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/execution-results-secret.png)

### 環境変数
<a name="lambda-secrets-manager-env-vars"></a>

AWS パラメータとシークレット Lambda 拡張機能では、次のデフォルト設定が使用されます。これらの設定は、対応する[環境変数](configuration-envvars.md#create-environment-variables)を作成して上書きできます。関数の現在の設定を表示するには、`PARAMETERS_SECRETS_EXTENSION_LOG_LEVEL` を `DEBUG` に設定します。この拡張機能によって、各関数の呼び出し開始時にその設定情報が CloudWatch Logs に記録されます。


| 設定 | デフォルト値 | 有効値 | 環境変数 | 詳細 | 
| --- | --- | --- | --- | --- | 
| HTTP ポート | 2773 | 1 - 65535 | PARAMETERS\$1SECRETS\$1EXTENSION\$1HTTP\$1PORT | ローカル HTTP サーバーのポート。 | 
| キャッシュ有効 | TRUE | TRUE、FALSE | PARAMETERS\$1SECRETS\$1EXTENSION\$1CACHE\$1ENABLED | キャッシュを有効または無効にします。 | 
| キャッシュサイズ | 1,000 | 0 ～ 1000 | PARAMETERS\$1SECRETS\$1EXTENSION\$1CACHE\$1SIZE | キャッシュを無効にするには 0 に設定します。 | 
| Secrets Manager の TTL | 300 秒 | 0 ～ 300 秒 | SECRETS\$1MANAGER\$1TTL | キャッシュされたシークレットの有効期限。キャッシュを無効にするには 0 に設定します。PARAMETERS\$1SECRETS\$1EXTENSION\$1CACHE\$1SIZE の値が 0 の場合、この変数は無視されます。 | 
| Parameter Store の TTL | 300 秒 | 0 ～ 300 秒 | SSM\$1PARAMETER\$1STORE\$1TTL | キャッシュされたパラメータの有効期限。キャッシュを無効にするには 0 に設定します。PARAMETERS\$1SECRETS\$1EXTENSION\$1CACHE\$1SIZE の値が 0 の場合、この変数は無視されます。 | 
| ログレベル | 情報 | デバッグ \$1 情報 \$1 警告 \$1 エラー \$1 なし | PARAMETERS\$1SECRETS\$1EXTENSION\$1LOG\$1LEVEL | 拡張機能のログに報告された詳細レベル | 
| 最大接続数 | 3 | 1 以上 | PARAMETERS\$1SECRETS\$1EXTENSION\$1MAX\$1CONNECTIONS | Parameter Store または Secrets Manager へのリクエストに使用される HTTP クライアントの最大接続数 | 
| Secrets Manager のタイムアウト | 0 (タイムアウトなし） | すべての整数 | SECRETS\$1MANAGER\$1TIMEOUT\$1MILLIS | Secrets Manager へのリクエストのタイムアウト (ミリ秒単位) | 
| Parameter Store のタイムアウト | 0 (タイムアウトなし） | すべての整数 | SSM\$1PARAMETER\$1STORE\$1TIMEOUT\$1MILLIS | Parameter Store へのリクエストのタイムアウト (ミリ秒単位) | 

### シークレットローテーションの使用
<a name="lambda-secrets-manager-rotation"></a>

シークレットを頻繁にローテーションする場合、デフォルトの 300 秒のキャッシュ期間が原因で関数が古いシークレットを使用する可能性があります。関数が最新のシークレット値を使用するようにするには、次の 2 つのオプションを使用できます。
+ `SECRETS_MANAGER_TTL` 環境変数をより低い値 (秒単位) に設定してキャッシュの TTL を短縮する。例えば、`60` に設定すると、関数は 1 分以上経過したシークレットを使用しなくなります。
+ シークレットリクエストで `AWSCURRENT` または `AWSPREVIOUS` ステージングラベルを使用して、必要な特定のバージョンを確実に取得できるようにする。

  ```
  secretsmanager/get?secretId=YOUR_SECRET_NAME&versionStage=AWSCURRENT
  ```

パフォーマンスと鮮度のニーズのバランスを維持するのに最適なアプローチを選択してください。TTL を短くすると、Secrets Manager の呼び出し頻度が高くなりますが、最新のシークレット値が使用されるようになります。

## Powertools for AWS Lambda のパラメータユーティリティの使用
<a name="lambda-secrets-manager-powertools-approach"></a>

Powertools for AWS Lambda のパラメータユーティリティは、Secrets Manager、パラメータストア、AppConfig などの複数のプロバイダーからシークレットを取得するための統合インターフェイスを提供します。キャッシュ、変換を処理し、拡張アプローチに比べ、より統合された開発エクスペリエンスを提供します。

### パラメータユーティリティの利点
<a name="lambda-secrets-manager-powertools-benefits"></a>
+ **複数のプロバイダー** - 同じインターフェイスを使用して Secrets Manager、Parameter Store、AppConfig からパラメータを取得する
+ **組み込み変換** - 自動 JSON 解析、base64 デコード、およびその他のデータ変換
+ **統合キャッシュ** - API コールを減らすための TTL サポートによる設定可能なキャッシュ
+ **型の安全性** - TypeScript およびその他のサポートされているランタイムで型付けを強力にサポート
+ **エラー処理** - 組み込みの再試行ロジックとエラー処理

### コードの例
<a name="lambda-secrets-manager-powertools-examples"></a>

次の例は、さまざまなランタイムで Parameters ユーティリティを使用してシークレットを取得する方法を示しています。

**Python**  
詳細な例とセットアップ手順については、「[Parameters ユーティリティのドキュメント](https://docs.powertools.aws.dev/lambda/python/latest/utilities/parameters/)」を参照してください。
Powertools for AWS Lambda Parameters ユーティリティを使用して Secrets Manager からシークレットを取得します。  

```
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities import parameters

logger = Logger()

def lambda_handler(event, context):
    try:
        # Get secret with caching (default TTL: 5 seconds)
        secret_value = parameters.get_secret("my-secret-name")
        
        # Get secret with custom TTL
        secret_with_ttl = parameters.get_secret("my-secret-name", max_age=300)
        
        # Get secret and transform JSON
        secret_json = parameters.get_secret("my-json-secret", transform="json")
        
        logger.info("Successfully retrieved secrets")
        
        return {
            'statusCode': 200,
            'body': 'Successfully retrieved secrets'
        }
        
    except Exception as e:
        logger.error(f"Error retrieving secret: {str(e)}")
        return {
            'statusCode': 500,
            'body': f'Error: {str(e)}'
        }
```

**TypeScript**  
詳細な例とセットアップ手順については、「[Parameters ユーティリティのドキュメント](https://docs.aws.amazon.com/powertools/typescript/2.1.1/utilities/parameters/)」を参照してください。
Powertools for AWS Lambda Parameters ユーティリティを使用して Secrets Manager からシークレットを取得します。  

```
import { Logger } from '@aws-lambda-powertools/logger';
import { getSecret } from '@aws-lambda-powertools/parameters/secrets';
import type { Context } from 'aws-lambda';

const logger = new Logger();

export const handler = async (event: any, context: Context) => {
    try {
        // Get secret with caching (default TTL: 5 seconds)
        const secretValue = await getSecret('my-secret-name');
        
        // Get secret with custom TTL
        const secretWithTtl = await getSecret('my-secret-name', { maxAge: 300 });
        
        // Get secret and transform JSON
        const secretJson = await getSecret('my-json-secret', { transform: 'json' });
        
        logger.info('Successfully retrieved secrets');
        
        return {
            statusCode: 200,
            body: 'Successfully retrieved secrets'
        };
        
    } catch (error) {
        logger.error('Error retrieving secret', { error });
        return {
            statusCode: 500,
            body: `Error: ${error}`
        };
    }
};
```

**Java**  
詳細な例とセットアップ手順については、「[Parameters ユーティリティのドキュメント](https://docs.powertools.aws.dev/lambda/java/latest/utilities/parameters/)」を参照してください。
Powertools for AWS Lambda Parameters ユーティリティを使用して Secrets Manager からシークレットを取得します。  

```
import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.parameters.SecretsProvider;
import software.amazon.lambda.powertools.parameters.ParamManager;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class SecretHandler implements RequestHandler<Object, String> {
    
    private final SecretsProvider secretsProvider = ParamManager.getSecretsProvider();
    
    @Logging
    @Override
    public String handleRequest(Object input, Context context) {
        try {
            // Get secret with caching (default TTL: 5 seconds)
            String secretValue = secretsProvider.get("my-secret-name");
            
            // Get secret with custom TTL (300 seconds)
            String secretWithTtl = secretsProvider.withMaxAge(300).get("my-secret-name");
            
            // Get secret and transform JSON
            MySecret secretJson = secretsProvider.get("my-json-secret", MySecret.class);
            
            return "Successfully retrieved secrets";
            
        } catch (Exception e) {
            return "Error retrieving secret: " + e.getMessage();
        }
    }
    
    public static class MySecret {
        // Define your secret structure here
    }
}
```

**.NET**  
詳細な例とセットアップ手順については、「[Parameters ユーティリティのドキュメント](https://docs.aws.amazon.com/powertools/typescript/latest/features/parameters/)」を参照してください。
Powertools for AWS Lambda Parameters ユーティリティを使用して Secrets Manager からシークレットを取得します。  

```
using AWS.Lambda.Powertools.Logging;
using AWS.Lambda.Powertools.Parameters;
using Amazon.Lambda.Core;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

public class Function
{
    private readonly ISecretsProvider _secretsProvider;
    
    public Function()
    {
        _secretsProvider = ParametersManager.SecretsProvider;
    }
    
    [Logging]
    public async Task<string> FunctionHandler(object input, ILambdaContext context)
    {
        try
        {
            // Get secret with caching (default TTL: 5 seconds)
            var secretValue = await _secretsProvider.GetAsync("my-secret-name");
            
            // Get secret with custom TTL
            var secretWithTtl = await _secretsProvider.WithMaxAge(TimeSpan.FromMinutes(5))
                .GetAsync("my-secret-name");
            
            // Get secret and transform JSON
            var secretJson = await _secretsProvider.GetAsync<MySecret>("my-json-secret");
            
            return "Successfully retrieved secrets";
        }
        catch (Exception e)
        {
            return $"Error retrieving secret: {e.Message}";
        }
    }
    
    public class MySecret
    {
        // Define your secret structure here
    }
}
```

### セットアップとアクセス許可
<a name="lambda-secrets-manager-powertools-setup"></a>

Parameters ユーティリティを使用するには、以下を行う必要があります。

1. ランタイム用の Powertools for AWS Lambda をインストールする。詳細については、「[Powertools for AWS Lambda](powertools-for-lambda.md)」を参照してください。

1. 関数の実行ロールに必要な IAM アクセス許可を追加する。詳細については、[AWS Lambda アクセス許可の管理](lambda-permissions.md) を参照してください。

1. [環境変数](configuration-envvars.md)を使用してオプションの設定を構成する。

必要な IAM アクセス許可は、拡張アプローチの場合と同じです。このユーティリティは、設定に基づいて Secrets Manager へのキャッシュと API コールを自動的に処理します。

# Amazon SQS での Lambda の使用
<a name="with-sqs"></a>

**注記**  
Lambda 関数以外のターゲットにデータを送信したい、または送信する前にデータをエンリッチしたいという場合は、「[Amazon EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html)」を参照してください。

Amazon Simple Queue Service (Amazon SQS) キュー内のメッセージを処理するには、Lambda 関数を使用することができます。Lambda は、[イベントソースマッピング](invocation-eventsourcemapping.md)で、[標準キュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html)と[ファーストイン、ファーストアウト (FIFO) キュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html)の両方をサポートしています。プロビジョンドモードを使用して、Amazon SQS イベントソースマッピング専用のポーリングリソースを割り当てることもできます。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要がありますが、[異なる AWS アカウント](with-sqs-cross-account-example.md)にすることができます。

Amazon SQS メッセージを処理するときは、部分的なバッチレスポンスロジックを実装して、バッチ内の一部のメッセージが失敗した場合に正常に処理されたメッセージが再試行されないようにする必要があります。Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)は、部分的なバッチレスポンスロジックを自動的に処理して開発時間を短縮し、信頼性を向上させることで、この実装を簡素化します。

**Topics**
+ [Amazon SQS イベントソースマッピングのポーリングとバッチ処理の動作を理解する](#sqs-polling-behavior)
+ [Amazon SQS イベントソースマッピングでのプロビジョンドモードの使用](#sqs-provisioned-mode)
+ [Amazon SQS イベントソースマッピングのプロビジョンドモードを設定する](#sqs-configuring-provisioned-mode)
+ [標準キューメッセージイベントの例](#example-standard-queue-message-event)
+ [FIFO キューメッセージイベントの例](#sample-fifo-queues-message-event)
+ [Amazon SQS イベントソースマッピングの作成と管理](services-sqs-configure.md)
+ [SQS イベントソースマッピングのスケーリング動作の設定](services-sqs-scaling.md)
+ [Lambda での SQS イベントソースのエラーの処理](services-sqs-errorhandling.md)
+ [Amazon SQS イベントソースマッピング用の Lambda パラメータ](services-sqs-parameters.md)
+ [Amazon SQS イベントソースでのイベントフィルタリングの使用](with-sqs-filtering.md)
+ [チュートリアル: Amazon SQS での Lambda の使用](with-sqs-example.md)
+ [チュートリアル: クロスアカウント Amazon SQS キューをイベントソースとして使用する](with-sqs-cross-account-example.md)

## Amazon SQS イベントソースマッピングのポーリングとバッチ処理の動作を理解する
<a name="sqs-polling-behavior"></a>

Amazon SQS イベントソースマッピングでは、Lambda はキューをポーリングし、イベントと共に関数を[同期的に](invocation-sync.md)呼び出します。各イベントには、キューからの複数のメッセージのバッチを含めることができます。Lambda は、これらのイベントをバッチとして (一度に 1 バッチずつ) 受け取り、バッチごとに関数を 1 回呼び出します。関数が正常にバッチを処理すると、Lambda はキューからそのメッセージを削除します。

Lambda がバッチを受け取ると、メッセージはキューに留まりますが、キューの[可視性タイムアウト](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)の期間中は非表示になります。関数がバッチ内のすべてのメッセージを正常に処理すると、Lambda はそのメッセージをキューから削除します。デフォルトでは、バッチの処理中に関数でエラーが発生すると、可視性タイムアウトの期限が切れた後に、そのバッチ内のすべてのメッセージが再びキューに表示されます。このため、関数コードは、意図しない副次的影響を及ぼすことなく同じメッセージを複数回処理できるようにする必要があります。

**警告**  
Lambda イベントソースマッピングは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

Lambda がメッセージを複数回処理しないようにするには、関数レスポンスに[バッチアイテムの失敗](services-sqs-errorhandling.md#services-sqs-batchfailurereporting)を含めるようにイベントソースマッピングを設定するか、[DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html) API を使用して、Lambda 関数がメッセージを正常に処理した場合にそれらをキューから削除することができます。

Lambda が SQS イベントソースマッピングでサポートする設定パラメータの詳細については、「[SQS イベントソースマッピングの作成](services-sqs-configure.md#events-sqs-eventsource)」を参照してください。

## Amazon SQS イベントソースマッピングでのプロビジョンドモードの使用
<a name="sqs-provisioned-mode"></a>

イベントソースマッピングのスループットを微調整する必要があるワークロードでは、プロビジョンドモードを使用できます。プロビジョンドモードでは、プロビジョニングされたイベントポーラーの最小数と最大数を定義します。これらのプロビジョニングされたイベントポーラーは、イベントソースマッピング専用であり、応答性の高い自動スケーリングによって予期しないメッセージスパイクを処理できます。プロビジョンドモードで設定された Amazon SQS イベントソースマッピングは、デフォルトの Amazon SQS イベントソースマッピング機能よりも 3 倍高速 (1 分あたり最大 1,000 回の同時呼び出し) に動作し、16 倍高い同時実行 (最大 20,000 回の同時呼び出し) をサポートします。マーケットデータフィードを処理する金融サービス会社、リアルタイムのパーソナライズされたレコメンデーションを提供する e コマースプラットフォーム、ライブプレイヤーインタラクションを管理するゲーム会社など、高精度なパフォーマンス要件を持つ Amazon SQS イベント駆動型ワークロードには、プロビジョンドモードを使用することをお勧めします。プロビジョニングモードを使用すると、追加コストが発生します。料金の詳細については、「[AWS Lambda の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。

プロビジョンドモードの各イベントポーラーは、最大 1 MB/秒のスループット、最大 10 回の同時呼び出し、または 1 秒あたり最大 10 回の Amazon SQS ポーリング API コールを処理できます。イベントポーラーの最小数 (MinimumPollers) の許容値の範囲は 2～200 で、デフォルトは 2 です。イベントポーラーの最大数 (MaximumPollers) の許容値の範囲は 2～2,000 で、デフォルトは 200 です。MaximumPollers は MinimumPollers より大きな数でなければなりません。

### 必要なイベントポーラーの決定
<a name="sqs-determining-event-pollers"></a>

SQS ESM にプロビジョンドモードを使用するときに最適なメッセージ処理パフォーマンスを確保するために必要なイベントポーラーの数を推定するには、アプリケーションの次のメトリクスを収集します。低レイテンシー処理を必要とする 1 秒あたりのピーク SQS イベント、平均 SQS イベントペイロードサイズ、平均 Lambda 関数期間、および設定されたバッチサイズ。

まず、次の式を使用して、ワークロードのイベントポーラーでサポートされている SQS イベント/秒 (EPS) の数を見積もることができます。

```
EPS per event poller = 
        minimum(
            ceiling(1024 / average event size in KB),
            ceiling(10 / average function duration in seconds) * batch size, 
            min(100, 10 * batch size)
                )
```

次に、以下の式を使用して、必要な最小ポーラーの数を計算できます。この計算により、ピークトラフィック要件を処理するのに十分な容量をプロビジョニングできます。

```
Required event pollers = (Peak number of events per second in Queue) / EPS per event poller
```

デフォルトのバッチサイズが 10、平均イベントサイズが 3 KB、平均関数期間が 100 ミリ秒、1 秒あたり 1,000 イベントを処理する必要があるワークロードを考えてみましょう。このシナリオでは、各イベントポーラーは 1 秒あたり約 100 イベント (EPS) をサポートします。したがって、ピークトラフィック要件を適切に処理するには、最小ポーラーを 10 に設定する必要があります。ワークロードの特性は同じですが、平均関数時間が 1 秒の場合、各ポーラーは 10 回の EPS のみをサポートするため、低レイテンシーで 1 秒あたり 1,000 イベントをサポートするように 100 回の最小ポーラーを設定する必要があります。

プロビジョンドモードイベントポーラーの効率を最大化するには、デフォルトのバッチサイズ 10 かそれ以上を使用することをお勧めします。バッチサイズを大きくすると、各ポーラーは呼び出しごとにより多くのイベントを処理することができ、スループットとコスト効率が向上します。イベントポーラー容量を計画するときは、トラフィックの急増の可能性を考慮し、バッファを持たせるために minimumPollers 値を計算された最小値よりわずかに高く設定することを検討してください。さらに、最適なパフォーマンスとコスト効率を維持するために、メッセージサイズ、関数の期間、またはトラフィックパターンの変更によりイベントポーラー設定の調整が必要になる場合があるため、ワークロードの特性を経時的にモニタリングします。正確なキャパシティプランニングを行うには、特定のワークロードをテストして、各イベントポーラーが駆動できる実際の EPS を決定することをお勧めします。

## Amazon SQS イベントソースマッピングのプロビジョンドモードを設定する
<a name="sqs-configuring-provisioned-mode"></a>

Amazon SQS イベントソースマッピングのプロビジョンドモードを設定するには、コンソールまたは Lambda API を使用できます。

**既存の Amazon SQS イベントソースマッピングに対してプロビジョンドモードを設定する手順 (コンソール)**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. プロビジョンドモードを設定する Amazon SQS イベントソースマッピングを持つ関数を選択します。

1. **[設定]** タブを選択し、**[トリガー]** を選択します。

1. プロビジョンドモードを設定する Amazon SQS イベントソースマッピングを選択し、**[編集]** をクリックします。

1. **[イベントソースマッピング設定]** で、**[プロビジョンドモードの設定]** を選択します。
   + **[最小イベントポーラー数]** に、2～200 の値を入力します。値を指定しない場合、Lambda はデフォルト値 2 を選択します。
   + **[最大イベントポーラー数]** に、2～2,000 の値を入力します。この値は、**[最小イベントポーラー数]** の値以上である必要があります。値を指定しない場合、Lambda はデフォルト値 200 を選択します。

1. **[保存]** を選択します。

プロビジョンドモードは、`EventSourceMappingConfiguration` の `ProvisionedPollerConfig` オブジェクトを使用してプログラムで設定できます。例えば、次の `UpdateEventSourceMapping` CLI コマンドは、`MinimumPollers` 値を 5、`MaximumPollers` 値を 100 に設定します。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{"MinimumPollers": 5, "MaximumPollers": 100}'
```

プロビジョニングモードを設定すると、`ProvisionedPollers` メトリクスをモニタリングすることで、ワークロードのイベントポーラーの使用状況を確認できます。詳細については、「イベントソースマッピングメトリクス」を参照してください。

プロビジョンドモードを無効にしてデフォルト (オンデマンド) モードに戻すには、次の `UpdateEventSourceMapping` CLI コマンドを使用できます。

```
aws lambda update-event-source-mapping \
    --uuid a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
    --provisioned-poller-config '{}'
```

**注記**  
プロビジョンドモードは、最大同時実行数設定と組み合わせて使用することはできません。プロビジョンドモードを使用する場合、イベントポーラーの最大数を通じて最大同時実行数を制御します。

プロビジョンドモードの設定の詳細については、「[Amazon SQS イベントソースマッピングの作成と管理](services-sqs-configure.md)」を参照してください。

## 標準キューメッセージイベントの例
<a name="example-standard-queue-message-event"></a>

**Example Amazon SQS メッセージイベント (標準キュー)**  

```
{
    "Records": [
        {
            "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
            "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1545082649183",
                "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                "ApproximateFirstReceiveTimestamp": "1545082649185"
            },
            "messageAttributes": {
                "myAttribute": {
                    "stringValue": "myValue", 
                    "stringListValues": [], 
                    "binaryListValues": [], 
                    "dataType": "String"
                }
            },
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
            "awsRegion": "us-east-2"
        },
        {
            "messageId": "2e1424d4-f796-459a-8184-9c92662be6da",
            "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1545082650636",
                "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                "ApproximateFirstReceiveTimestamp": "1545082650649"
            },
            "messageAttributes": {},
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue",
            "awsRegion": "us-east-2"
        }
    ]
}
```

デフォルトでは、Lambda はキュー内の最大 10 個のメッセージを一度にポーリングし、そのバッチを関数に送信します。少数のレコードで関数が呼び出されることを回避するには、バッチウィンドウを設定することで、最大 5 分間レコードをバッファリングするようにイベントソースに指示できます。関数を呼び出す前に、Lambda は、バッチ処理ウィンドウの期限が切れる、[呼び出しペイロードサイズのクォータ](gettingstarted-limits.md)に到達する、または設定された最大バッチサイズに到達するまで、標準キューからのメッセージのポーリングを継続します。

バッチウィンドウを使用していて、SQS キューのトラフィックがきわめて少ない場合、Lambda は関数を呼び出す前に最大 20 秒間待機することがあります。これは、バッチウィンドウを 20 秒未満に設定した場合であっても同様です。

**注記**  
Java では、JSON を逆シリアル化するときに null ポインタエラーが発生することがあります。これは、「Records」と「eventSourceARN」のケースが JSON オブジェクトマッパーによってどのように変換されるかに起因している可能性があります。

## FIFO キューメッセージイベントの例
<a name="sample-fifo-queues-message-event"></a>

FIFO キューの場合、レコードには、重複除外と順序付けに関連する追加属性が含まれます。

**Example Amazon SQS メッセージイベント (FIFO キュー)**  

```
{
    "Records": [
        {
            "messageId": "11d6ee51-4cc7-4302-9e22-7cd8afdaadf5",
            "receiptHandle": "AQEBBX8nesZEXmkhsmZeyIE8iQAMig7qw...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1573251510774",
                "SequenceNumber": "18849496460467696128",
                "MessageGroupId": "1",
                "SenderId": "AIDAIO23YVJENQZJOL4VO",
                "MessageDeduplicationId": "1",
                "ApproximateFirstReceiveTimestamp": "1573251510774"
            },
            "messageAttributes": {},
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:fifo.fifo",
            "awsRegion": "us-east-2"
        }
    ]
}
```

# Amazon SQS イベントソースマッピングの作成と管理
<a name="services-sqs-configure"></a>

Lambda で Amazon SQS メッセージを処理するには、キューを適切に設定し、Lambda イベントソースマッピングを作成します。

**Topics**
+ [Lambda で使用するキューの設定](#events-sqs-queueconfig)
+ [Lambda 実行ロールのアクセス許可の設定](#events-sqs-permissions)
+ [SQS イベントソースマッピングの作成](#events-sqs-eventsource)

## Lambda で使用するキューの設定
<a name="events-sqs-queueconfig"></a>

既存の Amazon SQS キューがない場合は、Lambda 関数のイベントソースとして機能する[キューを作成します](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-create-queue.html)。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要がありますが、[異なる AWS アカウント](with-sqs-cross-account-example.md)にすることができます。

関数がレコードの各バッチを処理する時間を確保するには、ソースキューの[可視性タイムアウト](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)を、関数の[設定タイムアウト](configuration-timeout.md)の少なくとも 6 倍に設定します。追加の時間は、関数が前のバッチの処理中にスロットリングされた場合に、Lambda が再試行することを可能にします。

**注記**  
関数のタイムアウトは、キューの可視性タイムアウト以下である必要があります。Lambda は、イベントソースマッピングを作成または更新するときにこの要件を検証し、関数のタイムアウトがキューの可視性タイムアウトを超えた場合にエラーを返します。

デフォルトでは、Lambda がバッチを処理しているときにエラーが発生すると、そのバッチ内のすべてのメッセージがキューに戻ります。[可視性タイムアウト](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)の後、メッセージは再び Lambda に表示されるようになります。[部分的なバッチレスポンス](services-sqs-errorhandling.md#services-sqs-batchfailurereporting)を使用するようにイベントソースマッピングを設定することで、失敗したメッセージのみがキューに戻るようにすることができます。さらに、関数が 1 つのメッセージの処理に複数回失敗する場合、Amazon SQS はそのメッセージを[デッドレターキュー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)に送信できます。ソースキューの[再処理ポリシー](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html#policies-for-dead-letter-queues)で、`maxReceiveCount` を少なくとも 5 に設定することをお勧めします。これにより、Lambda は、失敗したメッセージをデッドレターキューに直接送信する前に再試行を数回行う機会を確保できます。

## Lambda 実行ロールのアクセス許可の設定
<a name="events-sqs-permissions"></a>

[AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html) AWS マネージドポリシーには、Lambda が Amazon SQS キューから読み取るために必要なアクセス許可が含まれています。関数の実行ロールに[このマネージドポリシーを追加](lambda-intro-execution-role.md)できます。

オプションで、暗号化されたキューを使用している場合は、実行ロールに次の権限を追加する必要もあります。
+ [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)

## SQS イベントソースマッピングの作成
<a name="events-sqs-eventsource"></a>

イベントソースマッピングを作成し、キューから Lambda 関数に項目を送信するように Lambda に通知します。1 つの関数で複数のキューの項目を処理するには、複数のイベントソースマッピングを作成します。Lambda がターゲットの関数を呼び出すと、このイベントには設定可能な*バッチサイズ*までの複数の項目が含まれている可能性があります。

Amazon SQS から読み取るように関数を設定するには、[AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html) AWS マネージドポリシーを実行ロールにアタッチします。次に、以下の手順を使用して、コンソールから **SQS** イベントソースマッピングを作成します。

**アクセス許可を追加してトリガーを作成するには**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 関数の名前を選択します。

1. **[設定]** タブを開き、次に **[アクセス権限]** をクリックします。

1. **[実行ロール]** で、実行ロールのリンクを選択します。このリンクを選択すると、IAM コンソールでロールが開きます。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/execution-role.png)

1. **[アクセス許可を追加]**、**[ポリシーをアタッチ]** の順に選択します。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/attach-policies.png)

1. [検索] フィールドに `AWSLambdaSQSQueueExecutionRole` を入力します。実行ロールにポリシーを追加 これは、関数が Amazon SQS キューから読み取るために必要なアクセス許可を含む AWS 管理ポリシーです。このポリシーの詳細については、「*AWS マネージドポリシーリファレンス*」の「[AWSLambdaSQSQueueExecutionRole](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaSQSQueueExecutionRole.html)」を参照してください。

1. Lambda コンソールの関数に戻ります。**[関数の概要]** で **[トリガーを追加]** をクリックします。  
![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/add-trigger.png)

1. トリガーのタイプを選択します。

1. 必須のオプションを設定し、[**Add**] (追加) を選択します。

Lambda は、Amazon SQS イベントソースに対して以下の設定オプションをサポートしています。

**SQS キュー**  
レコードの読み取り元である Amazon SQS キュー。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要がありますが、[異なる AWS アカウント](with-sqs-cross-account-example.md)にすることができます。

**トリガーの有効化**  
イベントソースマッピングのステータス。**[Enable trigger]** (トリガーの有効化) はデフォルトで選択されています。

**バッチサイズ**  
各バッチで関数に送信されるレコードの最大数。標準キューの場合、最大 10,000 レコードまで可能です。FIFO キューの場合、最大値は 10 です。バッチサイズが 10 を超える場合は、バッチウィンドウ (`MaximumBatchingWindowInSeconds`) も 1 秒以上に設定する必要があります。  
[関数のタイムアウト](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/configurations#timeouts)は、バッチの項目すべてを処理するために十分な時間を確保できるように設定します。項目の処理に長時間かかる場合には、より少ないバッチサイズを選択します。バッチサイズを大きくするとワークロードの効率を向上させることができ、非常に高速になるか、多くのコストがかかります。関数で[予約された同時実行数](configuration-concurrency.md)を設定すると、同時実行数を 5 以上に設定した場合に、Lambda が関数を呼び出したときにスロットリングエラーが発生する可能性が少なくなります。  
Lambda は、イベントの合計サイズが同期呼び出しの[呼び出しペイロードサイズのクォータ](gettingstarted-limits.md) (6 MB) を超えない限り、バッチ内のすべてのレコードを単一の呼び出しで関数に渡します。Lambda と Amazon SQS の両方が、レコードごとにメタデータを生成します。この追加のメタデータは合計ペイロードサイズに計上され、1 つのバッチで送信されるレコードの総数が設定されたバッチサイズよりも少なくなる可能性があります。Amazon SQS が送信するメタデータフィールドは可変長にすることができます。Amazon SQS メタデータフィールドの詳細については、「*Amazon Simple Queue Service API リファレンス*」の「[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)」API 操作のドキュメントを参照してください。

**バッチウィンドウ**  
関数を呼び出すまでのレコード収集の最大時間 (秒) です。これが適用されるのは標準キューのみです。  
0 秒を超えるバッチウィンドウを使用している場合は、キューの[可視性タイムアウト](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)に処理時間の増加を考慮する必要があります。キューの可視性タイムアウトは、[関数のタイムアウト](configuration-timeout.md)の 6 倍に `MaximumBatchingWindowInSeconds` の値を加えた時間に設定することをお勧めします。これによりスロットリングエラーが発生した場合に Lambda 関数がイベントの各バッチを処理し、再試行する時間が許容されます。  
メッセージが使用可能になると、Lambda はメッセージのバッチ処理を開始します。Lambda は、関数を 5 回同時に呼び出すことで、一度に 5 つのバッチの処理を開始します。メッセージがまだ利用可能な場合、Lambda は関数の同時呼び出しを 1 分あたり最大 300 回まで追加し、最大 1,250 回の同時呼び出しまで増やします。プロビジョンドモードを使用する場合、各イベントポーラーは最大 1 MB/秒のスループット、最大 10 回の同時呼び出し、または 1 秒あたり最大 10 の Amazon SQS ポーリング API コールを処理できます。Lambda は、設定された最小値と最大値の間でイベントポーラーの数をスケールし、1 分あたり最大 1,000 回の同時呼び出しをすばやく追加することで、Amazon SQS イベントの低レイテンシー処理を実現します。これらの最小および最大イベントポーラー設定を使用して、スケーリングと同時実行を制御します。関数のスケーリングと同時実行の詳細については、「[Lambda 関数のスケーリングについて](lambda-concurrency.md)」を参照してください。  
より多くのメッセージを処理するには、Lambda 関数を最適化してスループットを向上させることができます。詳細については、「[AWS Lambda が Amazon SQS 標準キューでどのようにスケールするかを理解する](https://aws.amazon.com/blogs/compute/understanding-how-aws-lambda-scales-when-subscribed-to-amazon-sqs-queues/#:~:text=If there are more messages,messages from the SQS queue.)」を参照してください。

**フィルター条件**  
フィルター条件を追加して、Lambda が処理のために関数に送信するイベントを制御します。詳細については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

**最大同時実行数**  
イベントソースが呼び出せる同時関数の最大数。プロビジョンドモードを有効にして使用することはできません。詳細については、「[Amazon SQS イベントソースの最大同時実行数の設定](services-sqs-scaling.md#events-sqs-max-concurrency)」を参照してください。

**プロビジョンドモード**  
有効にすると、イベントソースマッピング専用のポーリングリソースを割り当てます。イベントポーラーの最小数 (2～200) と最大数 (2～2,000) を設定できます。各イベントポーラーは、最大 1 MB/秒のスループット、最大 10 回の同時呼び出し、または 1 秒あたり最大 10 の Amazon SQS ポーリング API コールを処理できます。  
注: プロビジョンドモードと最大同時実行数を一緒に使用することはできません。プロビジョンドモードが有効になっている場合は、最大ポーラー設定を使用して同時実行数を制御します。

# SQS イベントソースマッピングのスケーリング動作の設定
<a name="services-sqs-scaling"></a>

Amazon SQS イベントソースマッピングのスケーリング動作は、最大同時実行数の設定またはプロビジョンドモードを有効にすることで制御できます。これらは相互に排他的なオプションです。

デフォルトでは、Lambda はメッセージ量に基づいてイベントポーラーを自動的にスケーリングします。プロビジョンドモードを有効にすると、予想されるトラフィックパターンを処理する準備ができている専用ポーリングリソースの最小数と最大数を割り当てます。これにより、イベントソースマッピングのパフォーマンスを 2 つの方法で最適化できます。
+ 標準モード (デフォルト): Lambda は、少数のポーラーから始めてスケーリングを自動的に管理し、ワークロードに基づいてスケールアップまたはスケールダウンします。
+ プロビジョンドモード: 最小制限と最大制限で専用ポーリングリソースを設定し、スケーリングを 3 倍高速化、処理容量を最大 16 倍拡張できます。

標準キューの場合、Lambda は[ロングポーリング](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html#sqs-long-polling)を使用して、キューがアクティブになるまでキューをポーリングします。メッセージが利用可能な場合、Lambda は、関数を 5 回同時に呼び出すことで、一度に 5 つのバッチの処理を開始します。メッセージがまだ利用可能な場合、Lambda はバッチを読み込むプロセスの数を 1 分あたり最大 300 インスタンスまで増やします。イベントソースマッピングによって同時に処理できるバッチの最大数は 1,250 です。トラフィックが少ない場合、Lambda は処理を 5 つの同時実行呼び出しにスケールバックして、わずか 2 つの同時実行呼び出しに最適化できるため、Amazon SQS 呼び出しとそれに対応するコストを削減することができます。ただし、この最適化は、最大同時実行数設定を有効にしている場合には使用できません。

FIFO キューの場合、Lambda は、受信した順序でメッセージを関数に送信します。FIFO キューにメッセージを送信する場合、[メッセージグループ ID](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagegroupid-property.html) を指定します。Amazon SQS は、同じグループ内のメッセージが Lambda に順番に配信されるようにします。Lambda がメッセージをバッチに読み込むとき、各バッチには複数のメッセージグループからのメッセージが含まれることがありますが、メッセージの順序は維持されます。関数がエラーを返す場合、その関数は、Lambda が同じグループから追加のメッセージを受信する前に、対象メッセージですべての再試行を試みます。

プロビジョンドモードを使用する場合、各イベントポーラーは最大 1 MB/秒のスループット、最大 10 回の同時呼び出し、または最大 10 の Amazon SQS ポーリング API コールを処理できます。Lambda は、設定された最小値と最大値の間でイベントポーラーの数をスケーリングし、1 分あたり最大 1,000 個の同時実行数をすばやく追加して、Amazon SQS イベントの一貫した低レイテンシー処理を提供します。プロビジョニングモードを使用すると、追加コストが発生します。料金の詳細については、「[AWS Lambda の料金](https://aws.amazon.com/lambda/pricing/)」を参照してください。各イベントポーラーは、1 秒あたり最大 10 [のポーリングで SQS キューへのロング](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html)ポーリングを使用します。これにより、SQS API リクエストのコストが発生します。詳細については、「[Amazon SQS の料金](https://aws.amazon.com/sqs/pricing/ )」を参照してください。これらのオプションは一緒に使用できないため、最大同時実行設定を使用するのではなく、これらの最小および最大イベントポーラー設定を使用してスケーリングと同時実行を制御します。

**注記**  
最大同時実行数設定とプロビジョンドモードを同時に使用することはできません。プロビジョンドモードを有効にすると、イベントポーラーの最小数と最大数を通じて Amazon SQS イベントソースマッピングのスケーリングと同時実行を制御します。

## Amazon SQS イベントソースの最大同時実行数の設定
<a name="events-sqs-max-concurrency"></a>

最大同時実行数の設定を使用して、SQS イベントソースのスケーリング動作を制御できます。最大同時実行数は、プロビジョンドモードを有効にして使用することはできません。最大同時実行数設定は、Amazon SQS イベントソースが呼び出せる関数の同時インスタンス数を制限します。最大同時実行数は、イベントソースレベルの設定です。1 つの関数に複数の Amazon SQS イベントソースをマップしている場合は、各イベントソースに個別の最大同時実行数を設定できます。最大同時実行数は、1 つのキューが関数の[予約された同時実行](configuration-concurrency.md)のすべてを使用したり、[アカウントの同時実行クォータ](gettingstarted-limits.md)の残りのすべてを使用したりしないようにするために使用できます。Amazon SQS イベントソースでの最大同時実行数の設定に料金はかかりません。

重要なのは、最大同時実行数と予約された同時実行は、2 つの独立した設定であるということです。最大同時実行数を、関数の予約された同時実行よりも多い数に設定しないでください。最大同時実行数を設定する場合は、関数の予約された同時実行数が、関数にマップされたすべての Amazon SQS イベントソースの合計最大同時実行数以上になるようにしてください。合計数未満になった場合は、Lambda がメッセージをスロットルする可能性があります。

ご使用のアカウントの同時実行クォータがデフォルト値の 1,000 に設定されている場合、最大同時実行数を指定しない限り、Amazon SQS イベントソースマッピングは、関数インスタンスの呼び出し数がこの値に達するまでスケールできます。

アカウントのデフォルトの同時実行クォータを引き上げると、Lambda が同時実行の関数インスタンスを新しいクォータまで呼び出せない場合があります。Lambda はデフォルトで、Amazon SQS イベントソースマッピングに対する同時実行の関数インスタンスの呼び出し数が最大の 1,250 に達するまでスケールできます。デフォルト値がユースケースに不十分な場合は、AWS サポートへ連絡し、ご使用のアカウントにおける Amazon SQS イベントソースマッピングの同時実行数の増加についてご相談ください。

**注記**  
FIFO キューの場合、同時呼び出しの上限は、[メッセージグループ ID](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagegroupid-property.html) の数 (`messageGroupId`) または最大同時実行数の設定 (どちらか小さい方) です。例えば、メッセージグループ ID が 6 つあり、最大同時実行数が 10 に設定されている場合、関数は最大 6 回の同時呼び出しを行うことができます。

新規および既存の Amazon SQS イベントソースマッピングに最大同時実行数を設定できます。

**Lambda コンソールを使用して最大同時実行数を設定する**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. 関数の名前を選択します。

1. **[Function overview]** (関数の概要) で **[SQS]** を選択します。選択すると、**[Configuration]** (設定) タブが開きます。

1. Amazon SQS トリガーを選択し、**[Edit]** (編集) を選択します。

1. **[Maximum concurrency]** (最大同時実行数) には、2 から 1,000 までの数値を入力します。最大同時実行数をオフにするには、ボックスを空のままにします。

1. **[保存]** を選択します。

**AWS Command Line Interface(AWS CLI) を使用して最大同時実行数を設定する**  
`--scaling-config` オプション付きの [update-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) コマンドを使用します。例:

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --scaling-config '{"MaximumConcurrency":5}'
```

最大同時実行数をオフにするには、`--scaling-config` に空の値を入力します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --scaling-config "{}"
```

**Lambda API を使用して最大同時実行数を設定する**  
[ScalingConfig](https://docs.aws.amazon.com/lambda/latest/api/API_ScalingConfig.html) オブジェクトを指定した [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) アクションまたは [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) アクションを使用します。

# Lambda での SQS イベントソースのエラーの処理
<a name="services-sqs-errorhandling"></a>

SQS イベントソースに関連するエラーを処理する際に、Lambda はバックオフ戦略を備えた再試行戦略を自動的に使用します。また、[部分的なバッチレスポンス](#services-sqs-batchfailurereporting)を返すように SQS イベントソースマッピングを設定することで、エラー処理の動作をカスタマイズすることもできます。

## 失敗した呼び出しに対するバックオフ戦略
<a name="services-sqs-backoff-strategy"></a>

呼び出しが失敗すると、Lambda はバックオフ戦略の実装中に呼び出しの再試行を試みます。バックオフ戦略は、Lambda で発生した障害が関数コード内のエラーによるものか、スロットリングによるものかに応じて若干異なります。
+  **関数コード**が原因でエラーが発生した場合、Lambda は呼び出しの処理と再試行を停止します。その間、Lambda は Amazon SQS イベントソースマッピングに割り当てられた同時実行数を減らすことで、再試行を徐々にバックオフします。キューの可視性タイムアウトがタイムアウトすると、メッセージが再びキューに表示されます。
+ **スロットリング**が原因で呼び出しが失敗する場合、Lambda は Amazon SQS イベントソースマッピングに割り当てられた同時実行数を減らすことで、再試行を徐々にバックオフします。Lambda は、メッセージのタイムスタンプがキューの可視性タイムアウトを超過するまでメッセージを再試行し続けますが、タイムアウトした時点でメッセージをドロップします。

## 部分的なバッチレスポンスの実装
<a name="services-sqs-batchfailurereporting"></a>

Lambda 関数がバッチを処理しているときにエラーが発生すると、デフォルトでそのバッチ内のすべてのメッセージが再度キューに表示され、これには Lambda が正常に処理したメッセージも含まれます。その結果、関数が同じメッセージを複数回処理することになる場合があります。

失敗したバッチ内の正常に処理されたメッセージを再処理しないようにするために、失敗したメッセージのみを再び表示するようにイベントソースマッピングを設定できます。これを部分的なバッチレスポンスと呼びます。部分的なバッチレスポンスをオンにするには、イベントソースマッピングを設定するときに [FunctionResponseTypes](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html#lambda-UpdateEventSourceMapping-request-FunctionResponseTypes) アクション用に `ReportBatchItemFailures` を指定します。そうすると、関数が部分的な成功を返すようになるため、レコードでの不必要な再試行回数を減らすことができます。

**注記**  
Powertools for AWS Lambda の[バッチプロセッサユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)は、すべての部分的なバッチレスポンスロジックを自動的に処理します。このユーティリティは、バッチ処理パターンの実装を簡素化し、バッチ項目の障害を正しく処理するために必要なカスタムコードを削減します。Python、Java、Typescript、および .NET で使用できます。

`ReportBatchItemFailures` がアクティブ化されている場合、Lambda は、関数の呼び出しが失敗したときに[メッセージポーリングをスケールダウン](#services-sqs-backoff-strategy)しません。一部のメッセージが失敗することが想定され、それらの失敗によってメッセージの処理レートに影響が及ばないようにする場合は、`ReportBatchItemFailures` を使用します。

**注記**  
部分的なバッチレスポンスを使用する場合は、次の点に注意してください。  
関数が例外をスローする場合、バッチ全体が完全な失敗とみなされます。
この機能を FIFO キューで使用している場合、関数は最初の失敗後にメッセージの処理を停止し、`batchItemFailures` で失敗したメッセージと未処理のメッセージのすべてを返します。これは、キュー内のメッセージの順序を維持するのに役立ちます。

**部分的なバッチレポートをアクティブ化するには**

1. [部分的なバッチレスポンスを実装するためのベストプラクティス](https://docs.aws.amazon.com/prescriptive-guidance/latest/lambda-event-filtering-partial-batch-responses-for-sqs/best-practices-partial-batch-responses.html)を確認します。

1. 次のコマンドを実行して、関数用に `ReportBatchItemFailures` をアクティブ化します。イベントソースマッピングの UUID を取得するには、[list-event-source-mappings](https://docs.aws.amazon.com/cli/latest/reference/lambda/list-event-source-mappings.html) AWS CLI コマンドを実行します。

   ```
   aws lambda update-event-source-mapping \
   --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
   --function-response-types "ReportBatchItemFailures"
   ```

1. 関数コードを更新して、すべての例外をキャッチし、失敗したメッセージを `batchItemFailures` JSON レスポンスで返します。`batchItemFailures` レスポンスには、メッセージ ID のリストが `itemIdentifier` JSON 値として含まれている必要があります。

   例えば、メッセージ ID が `id1`、`id2`、`id3`、`id4`、および `id5` である 5 つのメッセージのバッチがあるとします。関数は、`id1`、`id3`、`id5` を正常に処理します。メッセージ `id2` および `id4` がキューで再び表示されるようにするには、関数が次のレスポンスを返す必要があります。

   ```
   { 
     "batchItemFailures": [ 
           {
               "itemIdentifier": "id2"
           },
           {
               "itemIdentifier": "id4"
           }
       ]
   }
   ```

   バッチで失敗したメッセージ ID のリストを返す関数コードの例を次に示します。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   using Amazon.Lambda.Core;
   using Amazon.Lambda.SQSEvents;
   
   // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
   [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
   namespace sqsSample;
   
   public class Function
   {
       public async Task<SQSBatchResponse> FunctionHandler(SQSEvent evnt, ILambdaContext context)
       {
           List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new List<SQSBatchResponse.BatchItemFailure>();
           foreach(var message in evnt.Records)
           {
               try
               {
                   //process your message
                   await ProcessMessageAsync(message, context);
               }
               catch (System.Exception)
               {
                   //Add failed message identifier to the batchItemFailures list
                   batchItemFailures.Add(new SQSBatchResponse.BatchItemFailure{ItemIdentifier=message.MessageId}); 
               }
           }
           return new SQSBatchResponse(batchItemFailures);
       }
   
       private async Task ProcessMessageAsync(SQSEvent.SQSMessage message, ILambdaContext context)
       {
           if (String.IsNullOrEmpty(message.Body))
           {
               throw new Exception("No Body in SQS Message.");
           }
           context.Logger.LogInformation($"Processed message {message.Body}");
           // TODO: Do interesting work based on the new message
           await Task.CompletedTask;
       }
   }
   ```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   package main
   
   import (
   	"context"
   	"fmt"
   	"github.com/aws/aws-lambda-go/events"
   	"github.com/aws/aws-lambda-go/lambda"
   )
   
   func handler(ctx context.Context, sqsEvent events.SQSEvent) (map[string]interface{}, error) {
   	batchItemFailures := []map[string]interface{}{}
   
   	for _, message := range sqsEvent.Records {
   		if len(message.Body) > 0 {
   			// Your message processing condition here
   			fmt.Printf("Successfully processed message: %s\n", message.Body)
   		} else {
   			// Message processing failed
   			fmt.Printf("Failed to process message %s\n", message.MessageId)
   			batchItemFailures = append(batchItemFailures, map[string]interface{}{"itemIdentifier": message.MessageId})
   		}
   	}
   
   	sqsBatchResponse := map[string]interface{}{
   		"batchItemFailures": batchItemFailures,
   	}
   	return sqsBatchResponse, nil
   }
   
   func main() {
   	lambda.Start(handler)
   }
   ```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   import com.amazonaws.services.lambda.runtime.events.SQSEvent;
   import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse;
    
   import java.util.ArrayList;
   import java.util.List;
    
   public class ProcessSQSMessageBatch implements RequestHandler<SQSEvent, SQSBatchResponse> {
       @Override
       public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) {
            List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new ArrayList<SQSBatchResponse.BatchItemFailure>();
   
            for (SQSEvent.SQSMessage message : sqsEvent.getRecords()) {
                try {
                    //process your message
                } catch (Exception e) {
                    //Add failed message identifier to the batchItemFailures list
                    batchItemFailures.add(new SQSBatchResponse.BatchItemFailure(message.getMessageId()));
                }
            }
            return new SQSBatchResponse(batchItemFailures);
        }
   }
   ```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Node.js 20.x Lambda runtime, AWS SDK for Javascript V3
   export const handler = async (event, context) => {
       const batchItemFailures = [];
       for (const record of event.Records) {
           try {
               await processMessageAsync(record, context);
           } catch (error) {
               batchItemFailures.push({ itemIdentifier: record.messageId });
           }
       }
       return { batchItemFailures };
   };
   
   async function processMessageAsync(record, context) {
       if (record.body && record.body.includes("error")) {
           throw new Error("There is an error in the SQS Message.");
       }
       console.log(`Processed message: ${record.body}`);
   }
   ```
TypeScript を使用して Lambda で SQS バッチ項目の失敗を報告します。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   import { SQSEvent, SQSBatchResponse, Context, SQSBatchItemFailure, SQSRecord } from 'aws-lambda';
   
   export const handler = async (event: SQSEvent, context: Context): Promise<SQSBatchResponse> => {
       const batchItemFailures: SQSBatchItemFailure[] = [];
   
       for (const record of event.Records) {
           try {
               await processMessageAsync(record);
           } catch (error) {
               batchItemFailures.push({ itemIdentifier: record.messageId });
           }
       }
   
       return {batchItemFailures: batchItemFailures};
   };
   
   async function processMessageAsync(record: SQSRecord): Promise<void> {
       if (record.body && record.body.includes("error")) {
           throw new Error('There is an error in the SQS Message.');
       }
       console.log(`Processed message ${record.body}`);
   }
   ```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   <?php
   
   use Bref\Context\Context;
   use Bref\Event\Sqs\SqsEvent;
   use Bref\Event\Sqs\SqsHandler;
   use Bref\Logger\StderrLogger;
   
   require __DIR__ . '/vendor/autoload.php';
   
   class Handler extends SqsHandler
   {
       private StderrLogger $logger;
       public function __construct(StderrLogger $logger)
       {
           $this->logger = $logger;
       }
   
       /**
        * @throws JsonException
        * @throws \Bref\Event\InvalidLambdaEvent
        */
       public function handleSqs(SqsEvent $event, Context $context): void
       {
           $this->logger->info("Processing SQS records");
           $records = $event->getRecords();
   
           foreach ($records as $record) {
               try {
                   // Assuming the SQS message is in JSON format
                   $message = json_decode($record->getBody(), true);
                   $this->logger->info(json_encode($message));
                   // TODO: Implement your custom processing logic here
               } catch (Exception $e) {
                   $this->logger->error($e->getMessage());
                   // failed processing the record
                   $this->markAsFailed($record);
               }
           }
           $totalRecords = count($records);
           $this->logger->info("Successfully processed $totalRecords SQS records");
       }
   }
   
   $logger = new StderrLogger();
   return new Handler($logger);
   ```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier: Apache-2.0
   
   def lambda_handler(event, context):
       if event:
           batch_item_failures = []
           sqs_batch_response = {}
        
           for record in event["Records"]:
               try:
                   print(f"Processed message: {record['body']}")
               except Exception as e:
                   batch_item_failures.append({"itemIdentifier": record['messageId']})
           
           sqs_batch_response["batchItemFailures"] = batch_item_failures
           return sqs_batch_response
   ```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda-with-batch-item-handling)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   # SPDX-License-Identifier: Apache-2.0
   require 'json'
   
   def lambda_handler(event:, context:)
     if event
       batch_item_failures = []
       sqs_batch_response = {}
   
       event["Records"].each do |record|
         begin
           # process message
         rescue StandardError => e
           batch_item_failures << {"itemIdentifier" => record['messageId']}
         end
       end
   
       sqs_batch_response["batchItemFailures"] = batch_item_failures
       return sqs_batch_response
     end
   end
   ```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/lambda-function-sqs-report-batch-item-failures)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用した Lambda での SQS バッチアイテム失敗のレポート。  

   ```
   // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   // SPDX-License-Identifier: Apache-2.0
   use aws_lambda_events::{
       event::sqs::{SqsBatchResponse, SqsEvent},
       sqs::{BatchItemFailure, SqsMessage},
   };
   use lambda_runtime::{run, service_fn, Error, LambdaEvent};
   
   async fn process_record(_: &SqsMessage) -> Result<(), Error> {
       Err(Error::from("Error processing message"))
   }
   
   async fn function_handler(event: LambdaEvent<SqsEvent>) -> Result<SqsBatchResponse, Error> {
       let mut batch_item_failures = Vec::new();
       for record in event.payload.records {
           match process_record(&record).await {
               Ok(_) => (),
               Err(_) => batch_item_failures.push(BatchItemFailure {
                   item_identifier: record.message_id.unwrap(),
               }),
           }
       }
   
       Ok(SqsBatchResponse {
           batch_item_failures,
       })
   }
   
   #[tokio::main]
   async fn main() -> Result<(), Error> {
       run(service_fn(function_handler)).await
   }
   ```

------

失敗したイベントがキューに戻らない場合は、AWS ナレッジセンターの「[Lambda 関数 SQS ReportBatchItemFailures をトラブルシューティングするにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-sqs-report-batch-item-failures/)」を参照してください。

### 成功条件と失敗の条件
<a name="sqs-batchfailurereporting-conditions"></a>

関数が以下のいずれかを返す場合、Lambda はバッチを完全な成功として扱います。
+ 空の `batchItemFailures` リスト
+ null の `batchItemFailures` リスト
+ 空の `EventResponse`
+ null の `EventResponse`

関数が以下のいずれかを返す場合、Lambda はバッチを完全な失敗として扱います。
+ 無効な JSON レスポンス
+ 空の文字列 `itemIdentifier`
+ ヌル `itemIdentifier`
+ 不正なキー名を持つ `itemIdentifier`
+ 存在しないメッセージ ID を持つ `itemIdentifier` 値

### CloudWatch メトリクス
<a name="sqs-batchfailurereporting-metrics"></a>

関数がバッチ項目の失敗を正しく報告しているかどうかを判断するために、Amazon SQS メトリクスの `NumberOfMessagesDeleted` および `ApproximateAgeOfOldestMessage` を Amazon CloudWatch でモニタリングできます。
+ `NumberOfMessagesDeleted` は、キューから削除されたメッセージの数を追跡します。これが 0 になるということは、関数レスポンスが失敗したメッセージを正しく返していないことを示唆しています。
+ `ApproximateAgeOfOldestMessage` は、最も古いメッセージがキューに残っている期間を追跡します。このメトリクスの急激な増加は、関数が失敗したメッセージを正しく返していないことを示唆している可能性があります。

### Powertools for AWS Lambda バッチプロセッサを使用する
<a name="services-sqs-batchfailurereporting-powertools"></a>

Powertools for AWS Lambda のバッチプロセッサユーティリティは、部分的なバッチレスポンスロジックを自動的に処理するため、バッチ障害レポートの実装の複雑さが軽減されます。バッチプロセッサを使用した例を次に示します。

**Python**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.powertools.aws.dev/lambda/python/latest/utilities/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した Amazon SQS メッセージの処理。  

```
import json
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.batch import BatchProcessor, EventType, process_partial_response
from aws_lambda_powertools.utilities.data_classes import SQSEvent
from aws_lambda_powertools.utilities.typing import LambdaContext

processor = BatchProcessor(event_type=EventType.SQS)
logger = Logger()

def record_handler(record):
    logger.info(record)
    # Your business logic here
    # Raise an exception to mark this record as failed
    
def lambda_handler(event, context: LambdaContext):
    return process_partial_response(
        event=event, 
        record_handler=record_handler, 
        processor=processor,
        context=context
    )
```

**TypeScript**  
詳細な例とセットアップ手順については、[バッチプロセッサのドキュメント](https://docs.aws.amazon.com/powertools/typescript/latest/features/batch/)を参照してください。
AWS Lambda バッチプロセッサを使用した Amazon SQS メッセージの処理。  

```
import { BatchProcessor, EventType, processPartialResponse } from '@aws-lambda-powertools/batch';
import { Logger } from '@aws-lambda-powertools/logger';
import type { SQSEvent, Context } from 'aws-lambda';

const processor = new BatchProcessor(EventType.SQS);
const logger = new Logger();

const recordHandler = async (record: any): Promise<void> => {
    logger.info('Processing record', { record });
    // Your business logic here
    // Throw an error to mark this record as failed
};

export const handler = async (event: SQSEvent, context: Context) => {
    return processPartialResponse(event, recordHandler, processor, {
        context,
    });
};
```

# Amazon SQS イベントソースマッピング用の Lambda パラメータ
<a name="services-sqs-parameters"></a>

すべての Lambda イベントソースタイプは、同じ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html) および [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html) API オペレーションを共有しています。ただし、Amazon SQS に適用されるのは一部のパラメータのみです。


| [Parameter] (パラメータ) | 必須 | デフォルト | メモ | 
| --- | --- | --- | --- | 
|  BatchSize  |  N  |  10  |  標準キューの場合、最大値は 10,000 です。FIFO キューの場合、最大値は 10 です。  | 
|  有効  |  N  |  true  | なし  | 
|  EventSourceArn  |  Y  | 該当なし |  データストリームまたはストリーミングコンシューマーの ARN。  | 
|  FunctionName  |  Y  | 該当なし  | なし  | 
|  FilterCriteria  |  N  |  該当なし   |  [Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)  | 
|  FunctionResponseTypes  |  N  | 該当なし  |  関数がバッチ内の特定の失敗を報告できるようにするには、`FunctionResponseTypes` に値 `ReportBatchItemFailures` を含めます。詳細については、[部分的なバッチレスポンスの実装](services-sqs-errorhandling.md#services-sqs-batchfailurereporting) を参照してください。  | 
|  MaximumBatchingWindowInSeconds  |  N  |  0  | バッチ処理ウィンドウは FIFO キューではサポートされていません | 
|  ProvisionedPollerConfig  |  N  |  該当なし  |  SQS イベントソースマッピングの専用イベントポーラーの最小数 (2～200) と最大数 (2～2,000) を設定します。各ポーラーは、最大 1 MB/秒のスループットと 10 回の同時呼び出しを処理できます。  | 
|  ScalingConfig  |  N  |  該当なし   |  [Amazon SQS イベントソースの最大同時実行数の設定](services-sqs-scaling.md#events-sqs-max-concurrency)  | 

# Amazon SQS イベントソースでのイベントフィルタリングの使用
<a name="with-sqs-filtering"></a>

イベントフィルタリングを使用して、Lambda が関数に送信するストリームまたはキューからのレコードを制御することができます。イベントフィルタリングの仕組みに関する一般情報については、「[Lambda が関数に送信するイベントを制御する](invocation-eventfiltering.md)」を参照してください。

このセクションでは、Amazon SQS イベントソースのイベントフィルタリングに焦点を当てます。

**注記**  
Amazon SQS イベントソースマッピングは、 `body` キーでのフィルタリングのみをサポートします。

**Topics**
+ [Amazon SQS イベントフィルタリングの基本](#filtering-SQS)

## Amazon SQS イベントフィルタリングの基本
<a name="filtering-SQS"></a>

Amazon SQS キューに次の JSON 形式のメッセージが含まれているとします。

```
{
    "RecordNumber": 1234,
    "TimeStamp": "yyyy-mm-ddThh:mm:ss",
    "RequestCode": "AAAA"
}
```

このキューのレコード例は次のようになります。

```
{
    "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
    "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
    "body": "{\n "RecordNumber": 1234,\n "TimeStamp": "yyyy-mm-ddThh:mm:ss",\n "RequestCode": "AAAA"\n}",
    "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1545082649183",
        "SenderId": "AIDAIENQZJOLO23YVJ4VO",
        "ApproximateFirstReceiveTimestamp": "1545082649185"
        },
    "messageAttributes": {},
    "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
    "eventSource": "aws:sqs",
    "eventSourceARN": "arn:aws:sqs:us-west-2:123456789012:my-queue",
    "awsRegion": "us-west-2"
}
```

Amazon SQS メッセージの内容に基づいてフィルタリングするには、Amazon SQS メッセージレコードの `body` キーを使用します。Amazon SQS メッセージの `RequestCode` が「BBBB」のレコードのみを処理するとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "body": {
        "RequestCode": [ "BBBB" ]
        }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "body" : { "RequestCode" : [ "BBBB" ] } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RequestCode\" : [ \"BBBB\" ] } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "body" : { "RequestCode" : [ "BBBB" ] } }'
```

------

関数が、`RecordNumber` が 9999 を超えるレコードのみを処理するとします。`FilterCriteria` オブジェクトは次のようになります。

```
{
    "Filters": [
        {
            "Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"
        }
    ]
}
```

以下は、わかりやすくするためにプレーン JSON で展開したフィルターの `Pattern` の値を記載しています。

```
{
    "body": {
        "RecordNumber": [
            {
                "numeric": [ ">", 9999 ]
            }
        ]
    }
}
```

コンソール、AWS CLI、または AWS SAM テンプレートを使用してフィルターを追加できます。

------
#### [ Console ]

コンソールを使用してこのフィルターを追加するには、[イベントソースマッピングへのフィルター条件のアタッチ (コンソール)](invocation-eventfiltering.md#filtering-console) の指示に従って **[フィルター条件]** に次の文字列を入力します。

```
{ "body" : { "RecordNumber" : [ { "numeric": [ ">", 9999 ] } ] } }
```

------
#### [ AWS CLI ]

AWS Command Line Interface (AWS CLI) を使用してこれらのフィルター条件を持つ新しいイベントソースマッピングを作成するには、以下のコマンドを実行します。

```
aws lambda create-event-source-mapping \
    --function-name my-function \
    --event-source-arn arn:aws:sqs:us-east-2:123456789012:my-queue \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"}]}'
```

これらのフィルター条件を既存のイベントソースマッピングに追加するには、次のコマンドを実行します。

```
aws lambda update-event-source-mapping \
    --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
    --filter-criteria '{"Filters": [{"Pattern": "{ \"body\" : { \"RecordNumber\" : [ { \"numeric\": [ \">\", 9999 ] } ] } }"}]}'
```

------
#### [ AWS SAM ]

AWS SAM を使用してこのフィルターを追加するには、イベントソースの YAML テンプレートに次のスニペットを追加します。

```
FilterCriteria:
  Filters:
    - Pattern: '{ "body" : { "RecordNumber" : [ { "numeric": [ ">", 9999 ] } ] } }'
```

------

Amazon SQS では、メッセージ本文は任意の文字列にすることができます。`body` が有効な JSON フォーマットであることが `FilterCriteria` で想定されている場合は、これが問題になる可能性があります。逆の場合も同様です。着信メッセージの本文が JSON 形式であっても、フィルター条件が `body` をプレーン文字列であると想定する場合、意図しない動作が発生する可能性があります。

この問題を回避するには、`FilterCriteria` の本文の形式がキューで受信するメッセージで想定する `body` の形式と一致することを確認してください。メッセージをフィルタリングする前に、Lambda は着信メッセージの本文の形式および `body` のフィルターパターンの形式を自動的に評価します。一致しない場合、Lambda はメッセージを除外します。この評価のまとめは、以下の表のとおりです。


| 着信メッセージの `body` の形式 | フィルターパターンの `body` の形式 | 結果として生じるアクション | 
| --- | --- | --- | 
|  プレーン文字列  |  プレーン文字列  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 
|  プレーン文字列  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  プレーン文字列  |  有効な JSON  |  Lambda はメッセージを除外します。  | 
|  有効な JSON  |  プレーン文字列  |  Lambda はメッセージを除外します。  | 
|  有効な JSON  |  データプロパティのフィルターパターンがない  |  Lambda がフィルター条件に基づいて (他のメタデータプロパティのみを) フィルタリングします。  | 
|  有効な JSON  |  有効な JSON  |  Lambda がフィルター条件に基づいてフィルタリングを実行します。  | 

# チュートリアル: Amazon SQS での Lambda の使用
<a name="with-sqs-example"></a>

このチュートリアルでは、[Amazon Simple Queue Service (Amazon SQS)](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html) キューからのメッセージを消費する Lambda 関数を作成します。Lambda 関数は、新しいメッセージがキューに追加されるたびに実行されます。この関数は、メッセージを Amazon CloudWatch Logs ストリームに書き込みます。次の図は、チュートリアルを完了するために使用する AWS リソースを示しています。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_resources.png)


このチュートリアルを完了するには、次のステップを実行します。

1. CloudWatch Logs にメッセージを書き込む Lambda 関数を作成します。

1. Amazon SQS キューを作成します。

1. Lambda イベントソースマッピングを作成します。イベントソースマッピングは Amazon SQS キューを読み取り、新しいメッセージが追加されたときに Lambda 関数を呼び出します。

1. キューにメッセージを追加して設定をテストし、CloudWatch Logs で結果をモニタリングします。

## 前提条件
<a name="with-sqs-prepare"></a>

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## 実行ロールを作成する
<a name="with-sqs-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps1.png)


[実行ロール](lambda-intro-execution-role.md)とは、AWS のサービス およびリソースに対するアクセス許可を Lambda 関数に付与する AWS Identity and Access Management (IAM) のロールです。関数が Amazon SQS から項目を読み取れるようにするには、**AWSLambdaSQSQueueExecutionRole** 許可ポリシーをアタッチします。

**実行ロールを作成して Amazon SQS 許可ポリシーをアタッチする方法**

1. IAM コンソールの[ロールページ](https://console.aws.amazon.com/iam/home#/roles)を開きます。

1. [**ロールの作成**] を選択してください。

1. **[信頼できるエンティティタイプ]** で、**[AWS サービス]** を選択します。

1. **[ユースケース]** で、**[Lambda]** を選択します。

1. [**次へ**] を選択します。

1. **[許可ポリシー]** 検索ボックスに **AWSLambdaSQSQueueExecutionRole** と入力します。

1. **AWSLambdaSQSQueueExecutionRole** ポリシーを選択し、**[Next]** を選択します。

1. **[Role details]** で **[Role name]** に **lambda-sqs-role** を入力してから、**[Create role]** を選択します。

ロールを作成したら、実行ロールの Amazon リソースネーム (ARN) を書き留めてください。これは、後のステップで必要になります。

## 関数を作成する
<a name="with-sqs-create-function"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps2.png)


Amazon SQS メッセージを処理する Lambda 関数を作成します。この関数コードは、Amazon SQS メッセージの本文を CloudWatch Logs に記録します。

このチュートリアルでは Node.js 24 ランタイムを使用しますが、他のランタイム言語のサンプルコードも提供しています。次のボックスでタブを選択すると、関心のあるランタイムのコードが表示されます。このステップで使用する JavaScript コードは、**[JavaScript]** タブに表示されている最初のサンプルにあります。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
.NET を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
﻿using Amazon.Lambda.Core;
using Amazon.Lambda.SQSEvents;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace SqsIntegrationSampleCode
{
    public async Task FunctionHandler(SQSEvent evnt, ILambdaContext context)
    {
        foreach (var message in evnt.Records)
        {
            await ProcessMessageAsync(message, context);
        }

        context.Logger.LogInformation("done");
    }

    private async Task ProcessMessageAsync(SQSEvent.SQSMessage message, ILambdaContext context)
    {
        try
        {
            context.Logger.LogInformation($"Processed message {message.Body}");

            // TODO: Do interesting work based on the new message
            await Task.CompletedTask;
        }
        catch (Exception e)
        {
            //You can use Dead Letter Queue to handle failures. By configuring a Lambda DLQ.
            context.Logger.LogError($"An error occurred");
            throw;
        }

    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package integration_sqs_to_lambda

import (
	"fmt"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(event events.SQSEvent) error {
	for _, record := range event.Records {
		err := processMessage(record)
		if err != nil {
			return err
		}
	}
	fmt.Println("done")
	return nil
}

func processMessage(record events.SQSMessage) error {
	fmt.Printf("Processed message %s\n", record.Body)
	// TODO: Do interesting work based on the new message
	return nil
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;

public class Function implements RequestHandler<SQSEvent, Void> {
    @Override
    public Void handleRequest(SQSEvent sqsEvent, Context context) {
        for (SQSMessage msg : sqsEvent.getRecords()) {
            processMessage(msg, context);
        }
        context.getLogger().log("done");
        return null;
    }

    private void processMessage(SQSMessage msg, Context context) {
        try {
            context.getLogger().log("Processed message " + msg.getBody());

            // TODO: Do interesting work based on the new message

        } catch (Exception e) {
            context.getLogger().log("An error occurred");
            throw e;
        }

    }
}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/blob/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
JavaScript を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message) {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```
TypeScript を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SQSEvent, Context, SQSHandler, SQSRecord } from "aws-lambda";

export const functionHandler: SQSHandler = async (
  event: SQSEvent,
  context: Context
): Promise<void> => {
  for (const message of event.Records) {
    await processMessageAsync(message);
  }
  console.info("done");
};

async function processMessageAsync(message: SQSRecord): Promise<any> {
  try {
    console.log(`Processed message ${message.body}`);
    // TODO: Do interesting work based on the new message
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用した Lambda での SQS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

# using bref/bref and bref/logger for simplicity

use Bref\Context\Context;
use Bref\Event\InvalidLambdaEvent;
use Bref\Event\Sqs\SqsEvent;
use Bref\Event\Sqs\SqsHandler;
use Bref\Logger\StderrLogger;

require __DIR__ . '/vendor/autoload.php';

class Handler extends SqsHandler
{
    private StderrLogger $logger;
    public function __construct(StderrLogger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * @throws InvalidLambdaEvent
     */
    public function handleSqs(SqsEvent $event, Context $context): void
    {
        foreach ($event->getRecords() as $record) {
            $body = $record->getBody();
            // TODO: Do interesting work based on the new message
        }
    }
}

$logger = new StderrLogger();
return new Handler($logger);
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用した Lambda での SQS イベントの消費。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event, context):
    for message in event['Records']:
        process_message(message)
    print("done")

def process_message(message):
    try:
        print(f"Processed message {message['body']}")
        # TODO: Do interesting work based on the new message
    except Exception as err:
        print("An error occurred")
        raise err
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda での SQS イベントの消費。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event:, context:)
  event['Records'].each do |message|
    process_message(message)
  end
  puts "done"
end

def process_message(message)
  begin
    puts "Processed message #{message['body']}"
    # TODO: Do interesting work based on the new message
  rescue StandardError => err
    puts "An error occurred"
    raise err
  end
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sqs-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用して Lambda で SQS イベントを消費します。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::event::sqs::SqsEvent;
use lambda_runtime::{run, service_fn, Error, LambdaEvent};

async fn function_handler(event: LambdaEvent<SqsEvent>) -> Result<(), Error> {
    event.payload.records.iter().for_each(|record| {
        // process the record
        tracing::info!("Message body: {}", record.body.as_deref().unwrap_or_default())
    });

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        // disable printing the name of the module in every log line.
        .with_target(false)
        // disabling time is handy because CloudWatch will add the ingestion time.
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

**Node.js Lambda 関数を作成する方法**

1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

   ```
   mkdir sqs-tutorial
   cd sqs-tutorial
   ```

1. サンプル JavaScript コードを `index.js` という名前の新しいファイルにコピーします。

1. 以下の `zip` コマンドを使用して、デプロイパッケージを作成します。

   ```
   zip function.zip index.js
   ```

1. [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) AWS CLI コマンドを使用して、Lambda 関数を作成します。`role`パラメータには、前に作成した実行ロールの ARN を入力します。
**注記**  
Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要があります。

   ```
   aws lambda create-function --function-name ProcessSQSRecord \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/lambda-sqs-role
   ```

## 関数をテストする
<a name="with-sqs-create-test-function"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps3.png)


`invoke` AWS CLI コマンドおよびサンプルの Amazon SQS イベントを使用して、手動で Lambda 関数を呼び出します。

**サンプルイベントで Lambda 関数を呼び出す方法**

1. 次の JSON をファイル名 `input.json` で保存します。この JSON は、Amazon SQS が Lambda 関数に送信する可能性のあるイベントをシミュレートするもので、`"body"` にはキューからの実際のメッセージが含まれます。この例では、メッセージは `"test"` です。  
**Example Amazon SQS イベント**  

   これはテストイベントです。メッセージやアカウント番号を変更する必要はありません。

   ```
   {
       "Records": [
           {
               "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
               "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
               "body": "test",
               "attributes": {
                   "ApproximateReceiveCount": "1",
                   "SentTimestamp": "1545082649183",
                   "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                   "ApproximateFirstReceiveTimestamp": "1545082649185"
               },
               "messageAttributes": {},
               "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
               "eventSource": "aws:sqs",
               "eventSourceARN": "arn:aws:sqs:us-east-1:111122223333:my-queue",
               "awsRegion": "us-east-1"
           }
       ]
   }
   ```

1. 次の [invoke](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) AWS CLI コマンドを実行します。このコマンドは、レスポンスで CloudWatch ログを返します。ログの取得の詳細については、「[AWS CLI を使用したログへのアクセス](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-cli)」を参照してください。

   ```
   aws lambda invoke --function-name ProcessSQSRecord --payload file://input.json out --log-type Tail \
   --query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
   ```

   AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、バージョン 2 の AWS Command Line Interface ユーザーガイドの「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。

1. レスポンス内にある `INFO` ログを探します。このログは Lambda 関数がメッセージ本文を記録する場所です。次のようなログが表示されます。

   ```
   2023-09-11T22:45:04.271Z	348529ce-2211-4222-9099-59d07d837b60	INFO	Processed message test
   2023-09-11T22:45:04.288Z	348529ce-2211-4222-9099-59d07d837b60	INFO	done
   ```

## Amazon SQS キュー を作成する
<a name="with-sqs-configure-sqs"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps4.png)


Lambda 関数がイベントソースとして使用できる Amazon SQS キューを作成します。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要があります。

**キューを作成するには**

1. [Amazon SQS コンソール](https://console.aws.amazon.com/sqs) を開きます。

1. **[キューの作成]** を選択します。

1. キューの名前を入力します。その他のオプションはすべて、デフォルト設定のままにしておきます。

1. [**キューの作成**] を選択します。

キューを作成したら、その ARN を書き留めます。こちらは、次のセクションでキューを Lambda 関数と関連付ける際に必要になります。

## イベントソースを設定する
<a name="with-sqs-attach-notification-configuration"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps5.png)


[イベントソースマッピング](invocation-eventsourcemapping.md)を作成して、Amazon SQS キューを Lambda 関数に接続します。イベントソースマッピングは Amazon SQS キューを読み取り、新しいメッセージが追加されたときに Lambda 関数を呼び出します。

Amazon SQS キューと Lambda 関数の間でマッピングを作成するには、[create-event-source-mapping](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) AWS CLI コマンドを使用します。例:

```
aws lambda create-event-source-mapping --function-name ProcessSQSRecord  --batch-size 10 \
--event-source-arn arn:aws:sqs:us-east-1:111122223333:my-queue
```

イベントソースマッピングのリストを取得するには、[list-event-source-mappings](https://awscli.amazonaws.com/v2/documentation/api/2.1.29/reference/lambda/list-event-source-mappings.html) コマンドを使用します。例:

```
aws lambda list-event-source-mappings --function-name ProcessSQSRecord
```

## テストメッセージを送信する
<a name="with-sqs-test-message"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps6.png)


**Amazon SQS メッセージを Lambda 関数に送信する方法**

1. [Amazon SQS コンソール](https://console.aws.amazon.com/sqs)を開きます。

1. 先ほど作成したキューを選択します。

1. **[メッセージの送信と受信]** を選択します。

1. **メッセージ本文**に、「これはテストメッセージです」などとテストメッセージを入力します。

1. **[メッセージの送信]** を選択します。

Lambdaがキューにアップデートをポーリングします。新しいメッセージがあると、Lambda はキューからのこの新しいイベントデータを使用して関数を呼び出します。　　 関数ハンドラーが例外をスローせずに正常に戻った場合、Lambda はメッセージが正しく処理されたと見なし、キュー内の新しいメッセージの読み取りを開始します。メッセージが正常に処理された後、Lambda はメッセージをキューから自動的に削除します。ハンドラーが例外をスローした場合、Lambda はメッセージの バッチが正常に処理されなかったと見なし、Lambdaは同じメッセージのバッチで関数を呼び出します。

## CloudWatch のログを確認する
<a name="with-sqs-check-logs"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sqs_tut_steps7.png)


**関数がメッセージを処理したことを確認する方法**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. **ProcessSQSRecord** 関数を選択します。

1. [**モニター**] を選択します。

1. **[CloudWatch Logs を表示]** を選択します。

1. CloudWatch コンソールで、関数の**ログストリーム**を選択します。

1. `INFO` ログを探します。このログは Lambda 関数がメッセージ本文を記録する場所です。Amazon SQS キューから送信したメッセージが表示されるはずです。例:

   ```
   2023-09-11T22:49:12.730Z b0c41e9c-0556-5a8b-af83-43e59efeec71 INFO Processed message this is a test message.
   ```

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[Delete]** (削除) を選択します。

**Amazon SQS キューを削除するには**

1. AWS マネジメントコンソール にサインインし、Amazon SQS コンソール ([https://console.aws.amazon.com/sqs/](https://console.aws.amazon.com/sqs/)) を開きます。

1. 作成したキューを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドに **confirm** を入力します。

1. **[Delete]** (削除) をクリックします。

# チュートリアル: クロスアカウント Amazon SQS キューをイベントソースとして使用する
<a name="with-sqs-cross-account-example"></a>

このチュートリアルでは、別のAWSアカウントで、 Amazon Simple Queue Service (Amazon SQS) キューからのメッセージを使用する Lambda 関数を作成します。　 このチュートリアルには 2 つのAWSアカウントが含まれています: **アカウント A** Lambda 関数を含むアカウントを参照します。**アカウント B** Amazon SQS キューを含むアカウントを参照します。

## 前提条件
<a name="with-sqs-cross-account-prepare"></a>

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## 実行ロールを作成する (アカウント A)
<a name="with-sqs-cross-account-create-execution-role"></a>

**アカウント A** で、必要なAWSリソースにアクセスするためのアクセス許可を関数に付与する[実行ロール](lambda-intro-execution-role.md)を作成します。

**実行ロールを作成するには**

1. AWS Identity and Access Management (IAM) コンソールの [[Roles page (ロールページ)](https://console.aws.amazon.com/iam/home#/roles)] を開きます。

1. **[ロールの作成]** を選択します。

1. 次のプロパティでロールを作成します。
   + **信頼されたエンティティ** - **AWS Lambda**
   + **アクセス許可** - **AWSLambdaSQSQueueExecutionRole**
   + **[ロール名]** – **cross-account-lambda-sqs-role**

**AWSLambdaSQSQueueExecutionRole** ポリシーには、Amazon SQS から項目を読み取り、Amazon CloudWatch Logs にログを書き込むために関数が必要とするアクセス許可があります。

## 関数を作成する (アカウント A)
<a name="with-sqs-cross-account-create-function"></a>

**[アカウント A]** で、Amazon SQS メッセージを処理する Lambda 関数を作成します。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要があります。

次の Node.js コード例は、各メッセージを CloudWatch Logs のログに書き込みます。

**Example index.mjs**  

```
export const handler = async function(event, context) {
  event.Records.forEach(record => {
    const { body } = record;
    console.log(body);
  });
  return {};
}
```

**関数を作成するには**
**注記**  
以下の手順を実行すると、Node.js 関数が作成されます。他の言語では、手順は似ていますが、いくつかの詳細が異なります。

1. サンプルコードをファイル名 `index.mjs` で保存します。

1. デプロイパッケージを作成します。

   ```
   zip function.zip index.mjs
   ```

1. `create-function` AWS Command Line Interface (AWS CLI) コマンドを使用して関数を作成します。`arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role` を、先ほど作成した実行ロールの ARN に置き換えます。

   ```
   aws lambda create-function --function-name CrossAccountSQSExample \
   --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
   --role arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role
   ```

## 関数をテストする (アカウント A)
<a name="with-sqs-cross-account-create-test-function"></a>

**アカウント A** で、`invoke` AWS CLIコマンドおよびサンプルの Amazon SQS イベントを使用して、手動で Lambda 関数をテストします。

ハンドラーが例外をスローせずに正常に戻る場合、Lambda はメッセージが正しく処理されたと見なし、キュー内の新しいメッセージの読み取りを開始します。メッセージが正常に処理された後、Lambda はメッセージをキューから自動的に削除します。ハンドラーが例外をスローした場合、Lambda はメッセージの バッチが正常に処理されなかったと見なし、Lambdaは同じメッセージのバッチで関数を呼び出します。

1. 次の JSON をファイル名 `input.txt` で保存します。

   ```
   {
       "Records": [
           {
               "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
               "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...",
               "body": "test",
               "attributes": {
                   "ApproximateReceiveCount": "1",
                   "SentTimestamp": "1545082649183",
                   "SenderId": "AIDAIENQZJOLO23YVJ4VO",
                   "ApproximateFirstReceiveTimestamp": "1545082649185"
               },
               "messageAttributes": {},
               "md5OfBody": "098f6bcd4621d373cade4e832627b4f6",
               "eventSource": "aws:sqs",
               "eventSourceARN": "arn:aws:sqs:us-east-1:111122223333:example-queue",
               "awsRegion": "us-east-1"
           }
       ]
   }
   ```

   `"body"`にキューからの実際のメッセージが含まれている場合、先行する JSON は、Amazon SQS が Lambda 関数に送信する可能性のあるイベントをシミュレートします。

1. 次の `invoke` AWS CLI コマンドを実行します。

   ```
   aws lambda invoke --function-name CrossAccountSQSExample \
   --cli-binary-format raw-in-base64-out \
   --payload file://input.txt outputfile.txt
   ```

   AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。

1. `outputfile.txt` ファイルで出力を確認します。

## Amazon SQS キュー を作成する (アカウント B)
<a name="with-sqs-cross-account-configure-sqs"></a>

**アカウント B** で、**アカウント A** の Lambda 関数がイベントソースとして使用できる Amazon SQS キューを作成します。Lambda 関数と Amazon SQS キューは同じ AWS リージョンに存在する必要があります。

**キューを作成するには**

1. [Amazon SQS コンソール](https://console.aws.amazon.com/sqs) を開きます。

1. **[キューの作成]** を選択します。

1. 次のプロパティでキューを作成します。
   + **タイプ** – **スタンダード**
   + **名前** – **LambdaCrossAccountQueue**
   + **設定** – デフォルト設定のままにします。
   + **アクセスポリシー** – [**Advanced (アドバンスト)**] を選択します。次の JSON ポリシーに貼り付けます。以下の値を置き換えます:
     + `111122223333`: **アカウント A** の AWS アカウント ID
     + `444455556666`: **アカウント B** の AWS アカウント ID

------
#### [ JSON ]

****  

     ```
     {
         "Version":"2012-10-17",		 	 	 
         "Id": "Queue1_Policy_UUID",
         "Statement": [
             {
                 "Sid": "Queue1_AllActions",
                 "Effect": "Allow",
                 "Principal": {
                     "AWS": [
                         "arn:aws:iam::111122223333:role/cross-account-lambda-sqs-role"
                     ]
                 },
                 "Action": "sqs:*",
                 "Resource": "arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue"
             }
         ]
     }
     ```

------

     このポリシーは、**アカウント A** で Lambda 実行ロールに、この Amazon SQS キューからのメッセージを使用するアクセス許可を付与します。

1. キューの作成後、Amazon リソースネーム (ARN)を記録します。こちらは、次のセクションでキューを Lambda 関数と関連付ける際に必要になります。

## イベントソースを設定する (アカウント A)
<a name="with-sqs-cross-account-event-source"></a>

**[アカウント A]** で、**[アカウント B]** の Amazon SQS キューと Lambda 関数の間に、次の `create-event-source-mapping` AWS CLIコマンドを実行してイベントソースマッピングを作成します。`arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue` を、前のステップで作成した Amazon SQS キューの ARN に置き換えます。

```
aws lambda create-event-source-mapping --function-name CrossAccountSQSExample --batch-size 10 \
--event-source-arn arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue
```

次のコマンドを実行して、イベントソースのマッピングのリストを取得できます。

```
aws lambda list-event-source-mappings --function-name CrossAccountSQSExample \
--event-source-arn arn:aws:sqs:us-east-1:444455556666:LambdaCrossAccountQueue
```

## セットアップをテストする
<a name="with-sqs-final-integration-test-no-iam"></a>

これにより、次のようにセットアップをテストできます。

1. **アカウント B** で [Amazon SQS コンソール](https://console.aws.amazon.com/sqs)を開きます。

1. 前に作成した [**LambdaCrossAccountQueue**] を選択します。

1. **[メッセージの送信と受信]** を選択します。

1. **[メッセージ本文]** にテストメッセージを入力します。

1. **[メッセージの送信]** を選択します。

**[アカウント A]** の Lambda 関数がメッセージを受信します。Lambda はキューに更新をポーリングし続けます。新しいメッセージがあると、Lambda はキューからのこの新しいイベントデータを使用して関数を呼び出します。　　 関数が実行され、Amazon CloudWatch にログが作成されます。[CloudWatch コンソール](https://console.aws.amazon.com/cloudwatch)でログを表示できます。

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**[アカウント A]** で、実行ロールと Lambda 関数をクリーンアップします。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[削除]** を選択します。

**[アカウント B]** で、Amazon SQS キューをクリーンアップします。

**Amazon SQS キューを削除するには**

1. AWS マネジメントコンソール にサインインし、Amazon SQS コンソール ([https://console.aws.amazon.com/sqs/](https://console.aws.amazon.com/sqs/)) を開きます。

1. 作成したキューを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドに **confirm** を入力します。

1. **[Delete]** (削除) をクリックします。

# Step Functions を用いた Lambda 関数のオーケストレーション
<a name="with-step-functions"></a>

AWS Step Functions は、Lambda 関数を他の AWS サービスと調整するためのビジュアルワークフローオーケストレーションを提供します。220 以上の AWS サービスとのネイティブ統合とフルマネージド型のゼロメンテナンスインフラストラクチャにより、Step Functions はビジュアルワークフロー設計とフルマネージド型のサービス統合が必要な場合に最適です。

ワークフローロジックがビジネスロジックと並行して存在する Lambda 内で標準プログラミング言語を使用するオーケストレーションについては、[Lambda の耐久性のある関数](durable-functions.md)を検討してください。これらのオプションの選択については、「[耐久性のある関数か Step Functions か](durable-step-functions.md)」を参照してください。

例えば、注文を処理するには、注文の詳細の確認、在庫レベルのチェック、支払の処理、請求書の生成が必要になる場合があります。それらのタスクそれぞれについて個別の Lambda 関数を記述し、Step Functions を使用してワークフローを管理します。Step Functions は各関数間のデータフローを調整し、各手順でエラーを処理します。この分離型アプローチにより、ワークフローが複雑になっても容易にワークフローを視覚化、変更、維持することができます。

## Lambda で Step Functions を使用すべき状況
<a name="when-to-use-step-functions"></a>

以下のシナリオは、Lambda ベースの複数のアプリケーションをオーケストレーションするのに Step Functions が特に適合する場合の例を示します。
+ [シーケンシャル処理](#sequential-processing)
+ [複雑なエラー処理](#complex-error-handling)
+ [条件付きワークフローと人間による承認](#conditional-workflows-human-approvals)
+ [並列処理](#parallel-processing)

### シーケンシャル処理
<a name="sequential-processing"></a>

シーケンシャル処理とは、あるタスクが完了してから、次のタスクを開始するアプローチを指します。例えば、注文処理システムでは、注文の確認が完了するまで支払処理を開始できず、請求書の生成は支払の確認を待つ必要があります。タスクごとに個別の Lambda 関数を記述し、Step Functions を使用してシーケンスを管理し、関数間のデータフローを調整します。

#### アンチパターンの例
<a name="anti-pattern-sequential"></a>

1 つの Lambda 関数で、注文処理ワークフロー全体を以下のように管理しています。
+ 他の Lambda 関数を順番に呼び出す
+ 各関数からのレスポンスを解析および検証する
+ エラー処理および復旧ロジックを実行する
+ 関数間のデータフローの管理

#### (推奨されるアプローチ)
<a name="recommended-sequential"></a>

2 つの Lambda 関数を使用しており、1 つは注文を確認し、もう 1 つは支払を処理するためのものです。Step Functions で、これらの関数を次のように調整します。
+ 各タスクを正しい順序で実行する
+ 関数間でのデータを受け渡しを行う
+ 各手順でエラー処理を実行する
+ [Choice](https://docs.aws.amazon.com/step-functions/latest/dg/state-choice.html) 状態を使用して、有効な注文のみが支払に進むようにする

**Example ワークフローのグラフ**  

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sequential_workflow.png)


**注記**  
**コードファーストの代替:** コードベースのチェックポイント設定と再試行によるシーケンシャル処理については、「[Lambda の耐久性のある関数の手順](durable-basic-concepts.md)」を参照してください。

### 複雑なエラー処理
<a name="complex-error-handling"></a>

Lambda は[非同期呼び出しおよびイベントソースマッピングの再試行機能](invocation-retries.md)を提供しますが、これに対し Step Functions は複雑なワークフローに対してより高度なエラー処理を提供します。エクスポネンシャルバックオフを使用して[自動再試行を設定](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-error-handling.html#error-handling-retrying-after-an-error)し、さまざまなエラータイプに対してそれぞれ個別の再試行ポリシーを設定できます。再試行で解決できなかった場合、`Catch` を使用してエラーを[フォールバック状態](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-error-handling.html#error-handling-fallback-states)にルーティングします。複数の関数およびサービスを調整するワークフローレベルのエラー処理が必要な場合、特に便利です。

ステートマシンでの Lambda 関数エラーの処理に関する詳細については、「*AWS Step Functions ワークショップ*」の「[エラーの処理](https://catalog.workshops.aws/stepfunctions/handling-errors)」を参照してください。

#### アンチパターンの例
<a name="anti-pattern-error-handling"></a>

1 つの Lambda 関数で、次のすべてを処理しています。
+ 支払処理サービスの呼び出しを試行する
+ 支払サービスが利用できない場合、関数は待機して後で再試行する。
+ 待機時間のカスタムエクスポネンシャルバックオフを実装する
+ すべての試行が失敗したら、エラーをキャッチして別のフローを選択する。

#### (推奨されるアプローチ)
<a name="recommended-error-handling"></a>

そこで、支払処理のみを中心に扱う 1 つの Lambda 関数を使用します。Step Functions で次のようにエラー処理を管理します。
+ [設定可能なバックオフ期間により、失敗したタスクを自動的に再試行する](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-error-handling.html#error-handling-retrying-after-an-error)
+ エラータイプに基づいて異なる再試行ポリシーを適用する
+ さまざまなエラーのタイプをそれぞれ適切なフォールバック状態にルーティングする
+ エラー処理の状態および履歴を維持する

**Example ワークフローのグラフ**  

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/error_handling_workflow.png)


**注記**  
**コードファーストの代替:** 耐久性のある関数は、設定可能な再試行戦略で try-catch エラー処理を提供します。[耐久性のある関数でのエラー処理](durable-execution-sdk-retries.md)を参照してください。

### 条件付きワークフローと人間による承認
<a name="conditional-workflows-human-approvals"></a>

Step Functions の [Choice 状態](https://docs.aws.amazon.com/step-functions/latest/dg/state-choice.html)を使用して関数の出力に基づいてワークフローをルーティングするとともに、人間の判断によりワークフローを一時停止できる [waitForTaskToken サフィックス](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token)を使用します。例えば、クレジット上限の引き上げリクエストを処理するには、Lambda 関数を使用してリスク要因を評価します。次に、Step Functions を使用して高リスクのリクエストを手動承認にルーティングし、低リスクのリクエストを自動承認にルーティングします。

コールバックタスクトークンの統合パターンを使用するワークフローの例をデプロイするには、「*AWS Step Functions ワークショップ*」の「[タスクトークンを使用したコールバック](https://catalog.workshops.aws/stepfunctions/integrating-services/3-callback-token)」を参照してください。

#### アンチパターンの例
<a name="anti-pattern-conditional"></a>

1 つの Lambda 関数で、複雑な承認ワークフローを次のように管理しています。
+ ネストされた条件付きロジックを実装してクレジットリクエストを評価する
+ リクエスト金額に基づいて複数の異なる承認関数を呼び出す
+ 複数の承認パスおよび決定ポイントを管理する
+ 承認待ち状態を追跡する
+ 承認用のタイムアウトおよび通知ロジックを実装する

#### (推奨されるアプローチ)
<a name="recommended-conditional"></a>

これに対し、3 つの Lambda 関数を使用します。1 つは各リクエストのリスクを評価し、1 つは低リスクのリクエストを承認し、最後の 1 つは高リスクのリクエストを管理者によるレビューにルーティングします。Step Functions で次のようにこのワークフローを管理します。
+ [Choice](https://docs.aws.amazon.com/step-functions/latest/dg/state-choice.html) 状態を使用して、量およびリスクレベルに基づいてリクエストをルーティングする
+ 人間による承認を待っている間は実行を一時停止する
+ 承認待ちのタイムアウトを管理する
+ 各リクエストの現在の状態を可視化する

**Example ワークフローのグラフ**  

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/conditional_workflow.png)


**注記**  
**コードファーストの代替:** 耐久性のある関数は、human-in-the-loop ワークフローのコールバックをサポートします。[耐久性のある関数の「コールバック」](durable-execution-sdk.md)を参照してください。

### 並列処理
<a name="parallel-processing"></a>

Step Functions には、並列処理を行う 3 つの方法があります。
+ [Parallel 状態](https://docs.aws.amazon.com/step-functions/latest/dg/state-parallel.html)は、ワークフローの複数の分岐を同時に実行します。画像メタデータ抽出中のサムネイル生成など、さまざまな関数を並行して実行する必要があるときに Parallel 状態を使用します。
+ [Inline Map 状態](https://docs.aws.amazon.com/step-functions/latest/dg/state-map-inline.html)は、最大 40 回の反復同時実行でデータ配列を処理します。Inline Map 状態は、各項目に対して同じオペレーションを実行する必要がある、小規模から中規模のデータセットに使用します。
+ [Distributed Map 状態](https://docs.aws.amazon.com/step-functions/latest/dg/state-map-distributed.html)は、最大 10,000 回の同時実行で大規模な並列処理を行うもので、JSON 配列と Amazon Simple Storage Service (Amazon S3) データソースの両方をサポートします。Distributed Map 状態は、大規模なデータセットの処理や、より大量の同時実行に対応する必要がある場合に使用します。

#### アンチパターンの例
<a name="anti-pattern-parallel"></a>

1 つの Lambda 関数で、次のような並列処理の管理を行っています。
+ 複数の画像処理関数を同時に呼び出す
+ カスタム並列実行ロジックを実装する
+ 各並列タスクでタイムアウトおよびエラー処理を管理する
+ すべての関数の結果を収集および集計する

#### (推奨されるアプローチ)
<a name="recommended-parallel"></a>

これに対し、3 つの Lambda 関数を使用します。1 つはサムネイルイメージを作成し、1 つはウォーターマークを付与し、最後の 1 つはメタデータを抽出します。Step Functions でこれらの関数を次のように管理します。
+ [Parallel](https://docs.aws.amazon.com/step-functions/latest/dg/state-parallel.html) 状態を使用してすべての関数を同時に実行する
+ 各関数の結果を収集し、順序付けられた配列にまとめる
+ すべての並列実行のタイムアウトおよびエラー処理を管理する
+ すべての並列分岐が完了した場合にのみ次に進む

**Example ワークフローのグラフ**  

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/parallel_workflow.png)


**注記**  
**コードファーストの代替:** 耐久性のある関数は `parallel()` および `map()` オペレーションを提供します。「[同時実行](durable-execution-sdk.md)」を参照してください。

## Lambda で Step Functions を使用すべきではない状況
<a name="when-not-to-use"></a>

すべての Lambda ベースのアプリケーションに Step Functions を使用するメリットがあるとは限りません。アプリケーションのアーキテクチャを選択する際、次のシナリオを検討してください。
+ [単純なアプリケーション](#simple-applications)
+ [複雑なデータの処理](#complex-data-processing)
+ [CPU 負荷が高いワークロード](#cpu-intensive)

### 単純なアプリケーション
<a name="simple-applications"></a>

**注記**  
視覚的な設計や広範なサービス統合を必要としないワークフローの場合、[Lambda の耐久性のある関数](durable-functions.md)は、ワークフローロジックを Lambda 内のコードに保持するより簡単な代替手段である可能性があります。

複雑なオーケストレーションが不要なアプリケーションの場合、Step Functions を使用すると不要な複雑さにつながることがあります。例えば、Amazon SQS キューからのメッセージの処理や、Amazon EventBridge イベントに応答するのみのサービスであれば、Lambda 関数の直接呼び出しで対応できるでしょう。同様に、エラー処理が簡単な 1 つもしくは 2 つの Lambda 関数 で構成されるアプリケーションであれば、Lambda の直接呼び出し機能もしくはイベント駆動型アーキテクチャの方がデプロイもメンテナンスもしやすいでしょう。

### 複雑なデータの処理
<a name="complex-data-processing"></a>

Step Functions の [Distributed Map](https://docs.aws.amazon.com/step-functions/latest/dg/state-map-distributed.html) 状態を使用することで、Lambda 関数で大規模な Amazon S3 データセットを同時に処理できます。この方法は、JSON ファイルや CSV ファイルなどの半構造化データの処理を含め、多くの大規模な並列ワークロードに効果的です。ただし、さらに複雑なデータ変換や高度な分析を要する場合は、次に説明する代替方法も検討してください。
+ **データ変換パイプライン**: AWS Glueを使用して、複数のソースからの構造化データまたは半構造化データを処理する ETL ジョブを構築します。AWS Glueは、ビルトインデータカタログやスキーマの管理機能が必要な場合に特に便利です。
+ **データ分析:** Amazon EMR を使用してペタバイト規模のデータ分析を行います。この方法は、Apache Hadoop エコシステムツールが必要な場合や、Lambda の[メモリ](configuration-memory.md)制限を超える機械学習ワークロードに特に適しています。

### CPU 負荷が高いワークロード
<a name="cpu-intensive"></a>

Step Functions は CPU 負荷が高いタスクもオーケストレーションすることができますが、Lambda 関数自体の CPU リソースが限られているためにこうしたワークロードには適していない場合があります。ワークフロー内のコンピューティング負荷が高いオペレーションについては、次の代替方法を検討してください。
+ **コンテナオーケストレーション:** Step Functions を使用して Amazon Elastic Container Service (Amazon ECS) タスクを管理し、一貫性がありスケーラブルなコンピューティングリソースを提供します。
+ **バッチ処理:** AWS Batch を Step Functions と統合し、継続的な CPU の使用を必要とするコンピューティング負荷の高いバッチジョブを管理します。

# Amazon S3 バッチイベントで Lambda 関数を呼び出す
<a name="services-s3-batch"></a>

Amazon S3 のバッチ操作を使用することで、大量の Amazon S3 オブジェクトに対して Lambda 関数を呼び出すことができます。Amazon S3 は、バッチオペレーションの進行状況を追跡して、通知を送信し、各アクションのステータスを示す完了レポートを保存します。

バッチ操作を実行するには、Amazon S3 [バッチ操作ジョブ](https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops-operations.html)を作成します。ジョブを作成するときは、マニフェスト (オブジェクトのリスト) を用意し、それらのオブジェクトに対して実行するアクションを設定します。

バッチジョブが開始されると、Amazon S3 はマニフェスト内の各オブジェクトに対して[同期的に](invocation-sync.md) Lambda 関数を呼び出します。イベントパラメータには、バケットとオブジェクトの名前が含まれます。

以下の例では、Amazon S3 が **amzn-s3-demo-bucket** バケット内の **customerImage1.jpg** という名前のオブジェクトの Lambda 関数に送信するイベントを示しています。

**Example Amazon S3 バッチリクエストイベント**  

```
{
"invocationSchemaVersion": "1.0",
    "invocationId": "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo",
    "job": {
        "id": "f3cc4f60-61f6-4a2b-8a21-d07600c373ce"
    },
    "tasks": [
        {
            "taskId": "dGFza2lkZ29lc2hlcmUK",
            "s3Key": "customerImage1.jpg",
            "s3VersionId": "1",
            "s3BucketArn": "arn:aws:s3:::amzn-s3-demo-bucket"
        }
    ]  
}
```

Lambda 関数は、次の例に示すとおり、フィールドを含む JSON オブジェクトを返す必要があります。イベントパラメータから `invocationId` と `taskId` をコピーできます。`resultString` で文字列を返します。Amazon S3 は、`resultString` 値を完了レポートに保存します。

**Example Amazon S3 バッチリクエストのレスポンス**  

```
{
  "invocationSchemaVersion": "1.0",
  "treatMissingKeysAs" : "PermanentFailure",
  "invocationId" : "YXNkbGZqYWRmaiBhc2RmdW9hZHNmZGpmaGFzbGtkaGZza2RmaAo",
  "results": [
    {
      "taskId": "dGFza2lkZ29lc2hlcmUK",
      "resultCode": "Succeeded",
      "resultString": "[\"Alice\", \"Bob\"]"
    }
  ]
}
```

## Amazon S3 バッチ操作からの Lambda 関数の呼び出し
<a name="invoking"></a>

Lambda 関数は、非修飾または修飾関数 ARN を使用して呼び出すことができます。バッチジョブ全体に同じ関数バージョンを使用する場合は、ジョブの作成時に `FunctionARN` パラメータで特定の関数バージョンを構成します。エイリアスまたは \$1LATEST 修飾子を設定した場合、ジョブ実行中にエイリアスまたは \$1LATEST が更新されると、バッチジョブは新しいバージョンの関数の呼び出しをただちに開始します。

既存の Amazon S3 イベントベースの関数をバッチ操作に再利用することはできません。これは、Amazon S3 バッチ操作によって異なるイベントパラメータが Lambda 関数に渡され、特定の JSON 構造を持つリターンメッセージが期待されるためです。

Amazon S3 Batch Job 用に作成する[リソースベースのポリシー](access-control-resource-based.md)で、Lambda 関数を呼び出すためのジョブに、アクセス許可が設定されていることを確認します。

関数の[実行ロール](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-iam-role-policies.html)で、Amazon S3 が関数の実行時にロールを引き受けるための信頼ポリシーを設定します。

関数で AWS SDK を使用して Amazon S3 リソースを管理する場合は、実行ロールに Amazon S3 のアクセス許可を追加する必要があります。

ジョブが実行されると、Amazon S3 は複数の関数インスタンスを起動して、関数の[同時実行数の上限](lambda-concurrency.md)に達するまで Amazon S3 オブジェクトを並列処理します。Amazon S3 は、小規模なジョブでコストが高騰することを避けるため、インスタンスの初期ランプアップを制限します。

Lambda 関数が `TemporaryFailure` レスポンスコードを返した場合、Amazon S3 はオペレーションを再試行します。

Amazon S3 バッチ操作の詳細については、*Amazon S3 デベロッパーガイド*の [バッチ操作の実行](https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops.html)を参照してください。

Amazon S3 バッチ操作で Lambda 関数を使用する方法の例については、*Amazon S3デベロッパーガイド*の [Invoking a Lambda function from Amazon S3 batch operations](https://docs.aws.amazon.com/AmazonS3/latest/dev/batch-ops-invoke-lambda.html) を参照してください。

# Amazon SNS 通知を使用した Lambda 関数の呼び出し
<a name="with-sns"></a>

Lambda 関数を使用して、Amazon Simple Notification Service (Amazon SNS) 通知を処理することができます。Amazon SNS では、トピックに送信されるメッセージのターゲットとして Lambda 関数がサポートされます。関数は、同じアカウントまたは他の AWS アカウントのトピックにサブスクライブできます。詳細なチュートリアルについては、「[チュートリアル: Amazon Simple Notification Service での AWS Lambda の使用](with-sns-example.md)」を参照してください。

Lambda は、標準 SNS トピックの SNS トリガーのみをサポートします。FIFO トピックはサポートされていません。

Lambda は、メッセージをキューに入れ、再試行を処理することで、SNS メッセージを非同期的に処理します。Amazon SNS が Lambda に到達できない場合、またはメッセージが拒否される場合、Amazon SNS は、数時間にわたって間隔を増やして再試行します。詳細については、Amazon SNS のよくある質問の中の[信頼性](https://aws.amazon.com/sns/faqs/#Reliability)を参照してください。

**警告**  
Lambda 非同期呼び出しは各イベントを少なくとも 1 回処理し、レコードの重複処理が発生する可能性があります。重複するイベントに関連する潜在的な問題を避けるため、関数コードを冪等にすることを強くお勧めします。詳細については、AWS ナレッジセンターの「[Lambda 関数を冪等にするにはどうすればよいですか?](https://repost.aws/knowledge-center/lambda-function-idempotent)」を参照してください。

## Powertools for AWS Lambda のべき等性ユーティリティ
<a name="services-sns-powertools-idempotency"></a>

Powertools for AWS Lambda のべき等性ユーティリティは、Lambda 関数をべき等にします。Python、TypeScript、Java、および .NET で使用できます。詳細については、Powertools for AWS Lambda (Python) ドキュメントの「[べき等性ユーティリティ](https://docs.powertools.aws.dev/lambda/python/latest/utilities/idempotency/)」、Powertools for AWS Lambda (TypeScript) ドキュメントの「[べき等性ユーティリティ](https://docs.aws.amazon.com/powertools/typescript/2.1.1/utilities/idempotency/)」、Powertools for AWS Lambda (Java) ドキュメントの「[べき等性ユーティリティ](https://docs.powertools.aws.dev/lambda/java/latest/utilities/idempotency/)」、および Powertools for AWS Lambda (.NET) ドキュメントの「[べき等性ユーティリティ](https://docs.powertools.aws.dev/lambda/dotnet/utilities/idempotency/)」を参照してください。********

**Topics**
+ [Powertools for AWS Lambda のべき等性ユーティリティ](#services-sns-powertools-idempotency)
+ [コンソールを使用した Lambda 関数の Amazon SNS トピックトリガーの追加](#sns-trigger-console)
+ [Lambda 関数の Amazon SNS トピックトリガーの手動追加](#sns-trigger-manual)
+ [SNS イベントシェイプのサンプル](#sns-sample-event)
+ [チュートリアル: Amazon Simple Notification Service での AWS Lambda の使用](with-sns-example.md)

## コンソールを使用した Lambda 関数の Amazon SNS トピックトリガーの追加
<a name="sns-trigger-console"></a>

SNS トピックを Lambda 関数のトリガーとして追加する最も簡単な方法は、Lambda コンソールを使用することです。コンソールからトリガーを追加すると、Lambda は SNS トピックからのイベントの受信を開始するために必要なアクセス許可とサブスクリプションを自動的に設定します。

**SNS トピックを Lambda 関数のトリガーとして追加するには (コンソール)**

1. Lambda コンソールの[関数ページ](https://console.aws.amazon.com/lambda/home#/functions)を開きます。

1. トリガーを追加する対象の関数の名前を選択します。

1. **[設定]** を選択し、**[トリガー]** を選択します。

1. **[トリガーを追加]** を選択します。

1. **[トリガーの設定]** の下のドロップダウンリストから **[SNS]** を選択します。

1. **[SNS トピック]** で、サブスクライブする SNS トピックを選択します。

## Lambda 関数の Amazon SNS トピックトリガーの手動追加
<a name="sns-trigger-manual"></a>

Lambda 関数の SNS トリガーを手動で設定するには、次のステップを完了する必要があります。
+ 関数に対するリソースベースのポリシーを定義して、SNS がその関数を呼び出すことを許可します。
+ Lambda 関数を Amazon SNS トピックにサブスクライブします。
**注記**  
SNS トピックと Lambda 関数が異なる AWS アカウントにある場合は、SNS トピックへのクロスアカウントサブスクリプションを許可するための追加のアクセス許可も付与する必要があります。詳細については、「[Amazon SNS サブスクリプションのクロスアカウントのアクセス許可を付与する](with-sns-example.md#with-sns-subscription-grant-permission)」を参照してください。

AWS Command Line Interface (AWS CLI) を使用して、これらの両方のステップを完了できます。まず、SNS 呼び出しを許可するためのリソースベースのポリシーを Lambda 関数に対して定義するには、次の AWS CLI コマンドを使用します。`--function-name` の値は Lambda 関数名に置き換え、`--source-arn` の値は SNS トピック ARN に置き換えてください。

```
aws lambda add-permission --function-name example-function \
    --source-arn arn:aws:sns:us-east-1:123456789012:sns-topic-for-lambda \
    --statement-id function-with-sns --action "lambda:InvokeFunction" \
    --principal sns.amazonaws.com
```

関数を SNS トピックにサブスクライブするには、次の AWS CLI コマンドを使用します。`--topic-arn` の値は SNS トピック ARN に置き換え、`--notification-endpoint` の値は Lambda 関数 ARN に置き換えてください。

```
aws sns subscribe --protocol lambda \
    --region us-east-1 \
    --topic-arn arn:aws:sns:us-east-1:123456789012:sns-topic-for-lambda \
    --notification-endpoint arn:aws:lambda:us-east-1:123456789012:function:example-function
```

## SNS イベントシェイプのサンプル
<a name="sns-sample-event"></a>

Amazon SNS は、メッセージやメタデータが含まれたイベントを使用して、関数を[非同期的に](invocation-async.md)呼び出します。

**Example Amazon SNS メッセージイベント**  

```
{
  "Records": [
    {
      "EventVersion": "1.0",
      "EventSubscriptionArn": "arn:aws:sns:us-east-1:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
      "EventSource": "aws:sns",
      "Sns": {
        "SignatureVersion": "1",
        "Timestamp": "2019-01-02T12:45:07.000Z",
        "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==",
        "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem",
        "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
        "Message": "Hello from SNS!",
        "MessageAttributes": {
          "Test": {
            "Type": "String",
            "Value": "TestString"
          },
          "TestBinary": {
            "Type": "Binary",
            "Value": "TestBinary"
          }
        },
        "Type": "Notification",
        "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=arn:aws:sns:us-east-1:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486",
        "TopicArn":"arn:aws:sns:us-east-1:123456789012:sns-lambda",
        "Subject": "TestInvoke"
      }
    }
  ]
}
```

# チュートリアル: Amazon Simple Notification Service での AWS Lambda の使用
<a name="with-sns-example"></a>

このチュートリアルでは、Lambda 関数を 1 つの AWS アカウント で使用して、別の AWS アカウント で Amazon Simple Notiﬁcation Service (Amazon SNS) トピックをサブスクライブします。Amazon SNS トピックにメッセージを発行すると、Lambda 関数がメッセージの内容を読み取り、Amazon CloudWatch Logs に出力します。このチュートリアルを完了するには、AWS Command Line Interface (AWS CLI) を使用します。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_resources.png)


このチュートリアルを完了するには、次のステップを実行します。
+ **アカウント A** で、Amazon SNS トピックを作成します。
+ **アカウント B** で、トピックからメッセージを読み取る Lambda 関数を作成します。
+ **アカウント B** で、トピックへのサブスクリプションを作成します。
+ **アカウント A** の Amazon SNS トピックにメッセージを発行し、**[アカウント B]** の Lambda 関数がメッセージを CloudWatch Logs に出力することを確認します。

これらのステップを完了することで、Lambda 関数を呼び出すように Amazon SNS トピックを設定する方法を学べます。また、別の AWS アカウント のリソースに Lambda を呼び出す許可を与える AWS Identity and Access Management (IAM) ポリシーを作成する方法も学習します。

このチュートリアルでは、2 つの別々の AWS アカウント を使用します。この AWS CLI コマンドは、それぞれが別の AWS アカウント で使用されるように設定された 2 つの名前付きプロファイル `accountA` および `accountB` を使用して実行します。異なるプロファイルを使用するように AWS CLI を設定する方法については、バージョン 2 の AWS Command Line Interface ユーザーガイドの「[設定と認証情報ファイルの設定](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)」を参照してください。両方のプロファイルに同じデフォルトの AWS リージョン を設定してください。

2 つの AWS アカウント に対して作成した AWS CLI プロファイルが異なる名前を使用している場合、またはデフォルトのプロファイルと 1 つの名前付きプロファイルを使用している場合は、必要に応じて次の手順の AWS CLI コマンドを変更します。

## 前提条件
<a name="with-sns-prereqs"></a>

### AWS Command Line Interface のインストール
<a name="install_aws_cli"></a>

AWS Command Line Interface をまだインストールしていない場合は、「[最新バージョンの AWS CLI のインストールまたは更新](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)」にある手順に従ってインストールしてください。

このチュートリアルでは、コマンドを実行するためのコマンドラインターミナルまたはシェルが必要です。Linux および macOS では、任意のシェルとパッケージマネージャーを使用してください。

**注記**  
Windows では、Lambda でよく使用される一部の Bash CLI コマンド (`zip` など) が、オペレーティングシステムの組み込みターミナルでサポートされていません。Ubuntu および Bash の Windows 統合バージョンを取得するには、[Windows Subsystem for Linux をインストール](https://docs.microsoft.com/en-us/windows/wsl/install-win10)します。

## Amazon SNS トピックを作成する (アカウント A)
<a name="with-sns-create-topic"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_1.png)


**トピックを作成するには**
+ **アカウント A** で、次の AWS CLI コマンドを使用して Amazon SNS 標準トピックを作成します。

  ```
  aws sns create-topic --name sns-topic-for-lambda --profile accountA
  ```

  次のような出力が表示されます。

  ```
  {
      "TopicArn": "arn:aws:sns:us-west-2:123456789012:sns-topic-for-lambda"
  }
  ```

  トピックの Amazon リソースネーム (ARN) をメモしておきます。これは、このチュートリアルで後ほどトピックをサブスクライブするための許可を Lambda 関数に追加するときに必要になります。

## 関数実行ロールを作成する (アカウント B)
<a name="with-sns-example-create-iam-role"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_2.png)


実行ロールとは、AWS のサービス とリソースにアクセスする許可を Lambda 関数に付与する IAM ロールです。**アカウント B** で関数を作成する前に、CloudWatch Logs にログを書き込むための基本的なアクセス許可を関数に与えるロールを作成します。Amazon SNS トピックから読み取るアクセス許可は、後のステップで追加します。

**実行ロールを作成するには**

1. **アカウント B** で、IAM コンソールの[ロールのページ](https://console.aws.amazon.com/iam/home#/roles)を開きます。

1. [**ロールの作成**] を選択してください。

1. **[信頼できるエンティティタイプ]** で、**[AWS サービス]** を選択します。

1. **[ユースケース]** で、**[Lambda]** を選択します。

1. [**次へ**] を選択します。

1. 次の手順を実行して、基本的なアクセス許可ポリシーをロールに追加します。

   1. **[許可ポリシー]** 検索ボックスに **AWSLambdaBasicExecutionRole** と入力します。

   1. [**次へ**] を選択します。

1. 次の手順を実行して、ロールの作成を完了します。

   1. **[ロールの詳細]** にある **[ロール名]** には **lambda-sns-role** を入力します。

   1. [**ロールの作成**] を選択してください。

## Lambda 関数を作成する (アカウント B)
<a name="with-sns-example-create-test-function"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_3.png)


Amazon SNS メッセージを処理する Lambda 関数を作成します。この関数コードは、各レコードのメッセージコンテンツを Amazon CloudWatch Logs に記録します。

このチュートリアルでは Node.js 24 ランタイムを使用しますが、他のランタイム言語のサンプルコードも提供しています。次のボックスでタブを選択すると、関心のあるランタイムのコードが表示されます。このステップで使用する JavaScript コードは、**[JavaScript]** タブに表示されている最初のサンプルにあります。

------
#### [ .NET ]

**SDK for .NET**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を検索し、設定および実行する方法を確認してください。
.NET を使用した Lambda での SNS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using Amazon.Lambda.Core;
using Amazon.Lambda.SNSEvents;


// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace SnsIntegration;

public class Function
{
    public async Task FunctionHandler(SNSEvent evnt, ILambdaContext context)
    {
        foreach (var record in evnt.Records)
        {
            await ProcessRecordAsync(record, context);
        }
        context.Logger.LogInformation("done");
    }

    private async Task ProcessRecordAsync(SNSEvent.SNSRecord record, ILambdaContext context)
    {
        try
        {
            context.Logger.LogInformation($"Processed record {record.Sns.Message}");

            // TODO: Do interesting work based on the new message
            await Task.CompletedTask;
        }
        catch (Exception e)
        {
            //You can use Dead Letter Queue to handle failures. By configuring a Lambda DLQ.
            context.Logger.LogError($"An error occurred");
            throw;
        }
    }
}
```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Go を使用して Lambda で SNS イベントを消費します。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package main

import (
	"context"
	"fmt"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(ctx context.Context, snsEvent events.SNSEvent) {
	for _, record := range snsEvent.Records {
		processMessage(record)
	}
	fmt.Println("done")
}

func processMessage(record events.SNSEventRecord) {
	message := record.SNS.Message
	fmt.Printf("Processed message: %s\n", message)
	// TODO: Process your record here
}

func main() {
	lambda.Start(handler)
}
```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Java を使用した Lambda での SNS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord;


import java.util.Iterator;
import java.util.List;

public class SNSEventHandler implements RequestHandler<SNSEvent, Boolean> {
    LambdaLogger logger;

    @Override
    public Boolean handleRequest(SNSEvent event, Context context) {
        logger = context.getLogger();
        List<SNSRecord> records = event.getRecords();
        if (!records.isEmpty()) {
            Iterator<SNSRecord> recordsIter = records.iterator();
            while (recordsIter.hasNext()) {
                processRecord(recordsIter.next());
            }
        }
        return Boolean.TRUE;
    }

    public void processRecord(SNSRecord record) {
        try {
            String message = record.getSNS().getMessage();
            logger.log("message: " + message);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
```

------
#### [ JavaScript ]

**SDK for JavaScript (v3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/blob/main/integration-sns-to-lambda)リポジトリで完全な例を検索し、設定および実行する方法を確認してください。
JavaScript を使用した Lambda での SNS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
exports.handler = async (event, context) => {
  for (const record of event.Records) {
    await processMessageAsync(record);
  }
  console.info("done");
};

async function processMessageAsync(record) {
  try {
    const message = JSON.stringify(record.Sns.Message);
    console.log(`Processed message ${message}`);
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```
TypeScript を使用した Lambda での SNS イベントの消費。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SNSEvent, Context, SNSHandler, SNSEventRecord } from "aws-lambda";

export const functionHandler: SNSHandler = async (
  event: SNSEvent,
  context: Context
): Promise<void> => {
  for (const record of event.Records) {
    await processMessageAsync(record);
  }
  console.info("done");
};

async function processMessageAsync(record: SNSEventRecord): Promise<any> {
  try {
    const message: string = JSON.stringify(record.Sns.Message);
    console.log(`Processed message ${message}`);
    await Promise.resolve(1); //Placeholder for actual async work
  } catch (err) {
    console.error("An error occurred");
    throw err;
  }
}
```

------
#### [ PHP ]

**SDK for PHP**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
PHP を使用して Lambda で SNS イベントを消費します。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
<?php

/* 
Since native PHP support for AWS Lambda is not available, we are utilizing Bref's PHP functions runtime for AWS Lambda.
For more information on Bref's PHP runtime for Lambda, refer to: https://bref.sh/docs/runtimes/function

Another approach would be to create a custom runtime. 
A practical example can be found here: https://aws.amazon.com/blogs/apn/aws-lambda-custom-runtime-for-php-a-practical-example/
*/

// Additional composer packages may be required when using Bref or any other PHP functions runtime.
// require __DIR__ . '/vendor/autoload.php';

use Bref\Context\Context;
use Bref\Event\Sns\SnsEvent;
use Bref\Event\Sns\SnsHandler;

class Handler extends SnsHandler
{
    public function handleSns(SnsEvent $event, Context $context): void
    {
        foreach ($event->getRecords() as $record) {
            $message = $record->getMessage();

            // TODO: Implement your custom processing logic here
            // Any exception thrown will be logged and the invocation will be marked as failed

            echo "Processed Message: $message" . PHP_EOL;
        }
    }
}

return new Handler();
```

------
#### [ Python ]

**SDK for Python (Boto3)**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Python を使用して Lambda で SNS イベントを消費します。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event, context):
    for record in event['Records']:
        process_message(record)
    print("done")

def process_message(record):
    try:
        message = record['Sns']['Message']
        print(f"Processed message {message}")
        # TODO; Process your record here
        
    except Exception as e:
        print("An error occurred")
        raise e
```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Ruby を使用した Lambda での SNS イベントの消費。  

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
def lambda_handler(event:, context:)
  event['Records'].map { |record| process_message(record) }
end

def process_message(record)
  message = record['Sns']['Message']
  puts("Processing message: #{message}")
rescue StandardError => e
  puts("Error processing message: #{e}")
  raise
end
```

------
#### [ Rust ]

**SDK for Rust**  
 GitHub には、その他のリソースもあります。[サーバーレスサンプル](https://github.com/aws-samples/serverless-snippets/tree/main/integration-sns-to-lambda)リポジトリで完全な例を見つけて、設定と実行の方法を確認してください。
Rust を使用して Lambda で SNS イベントを消費します。  

```
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use aws_lambda_events::event::sns::SnsEvent;
use aws_lambda_events::sns::SnsRecord;
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use tracing::info;

// Built with the following dependencies:
//  aws_lambda_events = { version = "0.10.0", default-features = false, features = ["sns"] }
//  lambda_runtime = "0.8.1"
//  tokio = { version = "1", features = ["macros"] }
//  tracing = { version = "0.1", features = ["log"] }
//  tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }

async fn function_handler(event: LambdaEvent<SnsEvent>) -> Result<(), Error> {
    for event in event.payload.records {
        process_record(&event)?;
    }
    
    Ok(())
}

fn process_record(record: &SnsRecord) -> Result<(), Error> {
    info!("Processing SNS Message: {}", record.sns.message);

    // Implement your record handling code here.

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .with_target(false)
        .without_time()
        .init();

    run(service_fn(function_handler)).await
}
```

------

**関数を作成するには**

1. プロジェクト用のディレクトリを作成し、そのディレクトリに切り替えます。

   ```
   mkdir sns-tutorial
   cd sns-tutorial
   ```

1. サンプル JavaScript コードを `index.js` という名前の新しいファイルにコピーします。

1. 以下の `zip` コマンドを使用して、デプロイパッケージを作成します。

   ```
   zip function.zip index.js
   ```

1. 次の AWS CLI コマンドを実行して、**アカウント B** に Lambda 関数を作成します。

   ```
   aws lambda create-function --function-name Function-With-SNS \
       --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
       --role arn:aws:iam::<AccountB_ID>:role/lambda-sns-role  \
       --timeout 60 --profile accountB
   ```

   次のような出力が表示されます。

   ```
   {
       "FunctionName": "Function-With-SNS",
       "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:Function-With-SNS",
       "Runtime": "nodejs24.x",
       "Role": "arn:aws:iam::123456789012:role/lambda_basic_role",
       "Handler": "index.handler",
       ...
       "RuntimeVersionConfig": {
           "RuntimeVersionArn": "arn:aws:lambda:us-west-2::runtime:7d5f06b69c951da8a48b926ce280a9daf2e8bb1a74fc4a2672580c787d608206"
       }
   }
   ```

1. 関数の Amazon リソースネーム (ARN) を記録します。これは、このチュートリアルで後ほど Amazon SNS が関数を呼び出せるようにする許可を追加するときに必要になります。

## 関数にアクセス許可を追加する (アカウント B)
<a name="with-sns-create-function-permissions"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_4.png)


Amazon SNS が関数を呼び出すには、[リソースベースのポリシー](access-control-resource-based.md)のステートメントでその関数にアクセス許可を付与する必要があります。AWS CLI `add-permission` コマンドを使用してこのステートメントを追加します。

**Amazon SNS アクセス許可を付与して関数を呼び出すには**
+ **アカウント B** で、前に記録した Amazon SNS トピックの ARN を使用して次の AWS CLI コマンドを実行します。

  ```
  aws lambda add-permission --function-name Function-With-SNS \
      --source-arn arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda \
      --statement-id function-with-sns --action "lambda:InvokeFunction" \
      --principal sns.amazonaws.com --profile accountB
  ```

  次のような出力が表示されます。

  ```
  {
      "Statement": "{\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":
        \"arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda\"}},
        \"Action\":[\"lambda:InvokeFunction\"],
        \"Resource\":\"arn:aws:lambda:us-east-1:<AccountB_ID>:function:Function-With-SNS\",
        \"Effect\":\"Allow\",\"Principal\":{\"Service\":\"sns.amazonaws.com\"},
        \"Sid\":\"function-with-sns\"}"
  }
  ```

**注記**  
Amazon SNS トピックを持つアカウントが[オプトイン AWS リージョン](https://docs.aws.amazon.com/accounts/latest/reference/manage-acct-regions.html) でホストされている場合、プリンシパルでリージョンを指定する必要があります。例えば、アジアパシフィック (香港) リージョンの Amazon SNS トピックを使用している場合、プリンシパルに「`sns.amazonaws.com`」ではなく「`sns.ap-east-1.amazonaws.com`」を指定する必要があります。

## Amazon SNS サブスクリプションのクロスアカウントのアクセス許可を付与する (アカウント A)
<a name="with-sns-subscription-grant-permission"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_5.png)


**アカウント B** の Lambda 関数が **アカウント A** で作成した Amazon SNS トピックをサブスクライブするには、**アカウント B** にトピックをサブスクライブするアクセス許可を付与する必要があります。AWS CLI `add-permission` コマンドを使用してこのアクセス許可を付与します。

**トピックをサブスクライブする許可をアカウント B に付与するには**
+ **アカウント A** で、次の AWS CLI コマンドを実行します。以前に記録した Amazon SNS トピックの ARN を使用します。

  ```
  aws sns add-permission --label lambda-access --aws-account-id <AccountB_ID> \
      --topic-arn arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda \  
      --action-name Subscribe ListSubscriptionsByTopic --profile accountA
  ```

## サブスクリプションを作成する (アカウント B)
<a name="with-sns-create-subscription"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_6.png)


**アカウント B** で、Lambda 関数によってチュートリアルの最初に**アカウント A** で作成した Amazon SNS トピックをサブスクライブします。メッセージがこのトピック (`sns-topic-for-lambda`) に送信されると、Amazon SNS は**アカウント B** の Lambda 関数 `Function-With-SNS` を呼び出します。

**サブスクリプションを作成するには**
+ **アカウント B** で、次の AWS CLI コマンドを実行します。トピックを作成したデフォルトのリージョンと、トピックおよび Lambda 関数の ARN を使用します。

  ```
  aws sns subscribe --protocol lambda \
      --region us-east-1 \
      --topic-arn arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda \
      --notification-endpoint arn:aws:lambda:us-east-1:<AccountB_ID>:function:Function-With-SNS \
      --profile accountB
  ```

  次のような出力が表示されます。

  ```
  {
      "SubscriptionArn": "arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda:5d906xxxx-7c8x-45dx-a9dx-0484e31c98xx"
  }
  ```

## メッセージをトピックに発行する (アカウント A とアカウント B)
<a name="with-sns-publish-message"></a>

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/services-sns-tutorial/sns_tut_steps_7.png)


**アカウント B** の Lambda 関数が **アカウント A** の Amazon SNS トピックにサブスクライブされたので、トピックにメッセージを発行してセットアップをテストします。Amazon SNS が Lambda 関数を呼び出したことを確認するには、CloudWatch Logs を使用して関数の出力を表示します。

**トピックにメッセージを発行して関数の出力を表示するには**

1. テキストファイルに「`Hello World`」と入力して、`message.txt` として保存します。

1. テキスト ファイルを保存したのと同じディレクトリから、**アカウント A** で次の AWS CLI コマンドを実行します。自分のトピックの ARN を使用します。

   ```
   aws sns publish --message file://message.txt --subject Test \
       --topic-arn arn:aws:sns:us-east-1:<AccountA_ID>:sns-topic-for-lambda \
       --profile accountA
   ```

   これにより、メッセージが Amazon SNS によって承諾されたことを示す、一意の識別子を持つメッセージ ID が返されます。次に、Amazon SNS は、メッセージをトピックのサブスクライバーに配信しようと試みます。Amazon SNS が Lambda 関数を呼び出したことを確認するには、CloudWatch Logs を使用して次の手順で関数の出力を確認します。

1. **アカウント B** で、Amazon CloudWatch コンソールの [[ロググループ]](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups) ページを開きます。

1. 関数のロググループの名前を選択します (`/aws/lambda/Function-With-SNS`) 。

1. 最新のログストリームを選択します。

1. 関数が正しく呼び出されていれば、トピックに発行したメッセージの内容を示す次のような出力が表示されます。

   ```
   2023-07-31T21:42:51.250Z c1cba6b8-ade9-4380-aa32-d1a225da0e48 INFO Processed message Hello World
   2023-07-31T21:42:51.250Z c1cba6b8-ade9-4380-aa32-d1a225da0e48 INFO done
   ```

## リソースのクリーンアップ
<a name="cleanup"></a>

このチュートリアル用に作成したリソースは、保持しない場合は削除できます。使用しなくなった AWS リソースを削除することで、AWS アカウント アカウントに請求される料金の発生を防ぎます。

**[Account A]** (アカウント A) で、Amazon SNS トピックをクリーンアップします。

**Amazon SNS トピックを作成するには**

1. Amazon SNS コンソールで [[Topics (トピック)] ページ](https://console.aws.amazon.com//sns/home#topics:)を開きます。

1. 先ほど作成したトピックを選択します。

1. [**削除**] を選択します。

1. テキスト入力フィールドに **delete me** を入力します。

1. **[削除]** を選択します。

**[Account B]** (アカウント A) で、実行ロール、Lambda 関数、および Amazon SNS サブスクリプションをクリーンアップします。

**実行ロールを削除する**

1. IAM コンソールの [[ロール]](https://console.aws.amazon.com/iam/home#/roles) ページを開きます。

1. 作成した実行ロールを選択します。

1. **[削除]** を選択します。

1. テキスト入力フィールドにロールの名前を入力し、**[削除]** を選択します。

**Lambda 関数を削除するには**

1. Lambda コンソールの [[関数]](https://console.aws.amazon.com/lambda/home#/functions) ページを開きます。

1. 作成した関数を選択します。

1. **[アクション]** で、**[削除]** を選択します。

1. テキスト入力フィールドに **confirm** と入力し、**[Delete]** (削除) を選択します。

**Amazon SNS サブスクリプションを削除するには**

1. Amazon SNS コンソールの[Subscriptions page](https://console.aws.amazon.com//sns/home#subscriptions:)] (サブスクリプションページ) をを開きます。

1. 作成したサブスクリプションを選択します。

1. [**Delete**] (削除) を選択し、**削除**します。