AWS Lambda
開発者ガイド

AWS Lambda 関数を使用する際のベストプラクティス

AWS Lambda の使用時に推奨されるベストプラクティスを以下に示します。

関数コード

  • Lambda ハンドラーをコアロジックから分離します。 これにより、関数の単体テストが実行しやすくなります。Node.js では、次のようになります。

    exports.myHandler = function(event, context, callback) { var foo = event.foo; var bar = event.bar; var result = MyLambdaFunction (foo, bar); callback(null, result); } function MyLambdaFunction (foo, bar) { // MyLambdaFunction logic here }
  • 実行コンテキストの再利用を活用して関数のパフォーマンスを向上させます。 関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを /tmp ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、実行時間とコストが節約されます。

    呼び出し間でデータが漏れるのを防ぐため、実行コンテキストを使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラ内のメモリに保存できない変更可能な状態に依存している場合は、ユーザごとに個別の関数または個別のバージョンの関数を作成することを検討してください。

  • AWS Lambda 環境変数 を使用してオペレーショナルパラメータを関数に渡します。 たとえば、Amazon S3 に書き込む場合、書き込み先のバケットの名前はハードコーディングせずに、環境変数として設定します。

  • 関数のデプロイパッケージの依存関係を制御します。AWS Lambda 実行環境には、Node.js および Python ランタイムの AWS SDK などのライブラリがいくつか含まれています (詳細なリストについては、「AWS Lambda ランタイム」を参照してください)。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda ではこれらのライブラリを定期的に更新します。この更新に伴って、Lambda 関数の動作が微妙に変わる場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。

  • デプロイパッケージのサイズをランタイムに必要な最小限のサイズにします。これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。Java または .NET Core で作成した関数の場合は、デプロイパッケージの一環として AWS SDK ライブラリ全体をアップロードしないようにします。代わりに、SDK のコンポーネントを必要に応じて選別するモジュール (DynamoDB モジュール、Amazon S3 SDK モジュール、Lambda コアライブラリなど) を使用します。

  • Java で記述されたデプロイパッケージを Lambda で解凍する所要時間を短縮します。そのために、依存する .jar ファイルを別個の /lib ディレクトリに収納します。これで関数のすべてのコードを多数の .class ファイルと一緒に単一の Jar に収納するよりも高速化されます。手順については、「Java の AWS Lambda デプロイパッケージ」を参照してください。

  • 依存関係の複雑さを最小限に抑えます。 フレームワークを単純化して、実行コンテキスト起動時のロードを高速化します。たとえば、Spring Framework などの複雑なフレームワークよりも、DaggerGuice などの単純な Java 依存関係インジェクション (IoC) フレームワークを使用します。

  • Lambda 関数内で、任意の条件が満たされるまでその関数自身を自動的に呼び出すような再帰的なコードを使用しないでください。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。誤ってこのようなコードを使用した場合は、関数の同時実行数の制限を 0 に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。

Function Configuration

  • Lambda 関数のパフォーマンステストは、最適なメモリサイズ設定を選択する上で欠かせない部分です。メモリサイズが増えると、関数で利用できる CPU も同様に増加します。関数のメモリ使用量は、呼び出しごとに決定され、AWS CloudWatch Logs で表示できます。次に示すように、呼び出しごとに REPORT: エントリが作成されます。

    REPORT RequestId: 3604209a-e9a3-11e6-939a-754dd98c7be3 Duration: 12.34 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 18 MB

    Max Memory Used: フィールドを分析することで、関数のメモリが不足しているか、関数のメモリサイズをオーバープロビジョニングしているかを判断できます。

  • Lambda 関数のロードテストにより、最適なタイムアウト値を決定します。関数の実行時間を分析し、依存関係サービスの問題に伴って関数の同時実行が必要以上に増えるような状況をより的確に判定します。これは、Lambda のスケーリングを処理しない可能性があるリソースに対して Lambda 関数からネットワークの呼び出しを行うときに特に重要です。

  • IAM ポリシーの設定時に最も制限的なアクセス許可を使用します。 Lambda 関数に必要なリソースとオペレーションを把握し、実行ロールをこれらのアクセス許可に制限します。詳細については、「AWS Lambda アクセス許可」を参照してください。

  • AWS Lambda の制限 について理解を深めます。 ランタイムのリソース制限を決定する際に、ペイロードサイズ、ファイル記述子、および /tmp スペースが見過ごされがちです。

  • 使用しなくなった Lambda 関数を削除します。 削除することで、未使用の関数がデプロイパッケージサイズの制限対象として不必要にカウントされなくなります。

  • イベントソースとして Amazon Simple Queue Service を使用している場合、関数の予想実行時間の値が、キューの可視性タイムアウトの値を超えていないことを確認してください。これは、CreateFunctionUpdateFunctionConfiguration のいずれにも適用されます。

    • CreateFunction の場合、AWS Lambda における関数の作成プロセスは失敗します。

    • UpdateFunctionConfiguration の場合、関数の呼び出しが重複する可能性があります。

アラームとメトリクス

  • AWS Lambda のメトリクス および CloudWatch アラームを使用して、Lambda 関数コード内からはメトリクスを作成または更新しないようにします。Lambda 関数の状態を追跡する方法としてより効率的であり、開発プロセスの早期に問題を把握できます。たとえば、Lambda 関数の推定される実行所要時間に基づいてアラームを設定し、関数コードに起因するボトルネックやレイテンシーに対処できます。

  • ログ記録のライブラリと AWS Lambda メトリクスおよびディメンションを活用して、アプリケーションエラー (ERR、ERROR、WARNING など) を見つけます。

ストリームイベントの呼び出し

  • バッチおよびレコードの各種サイズのテストにより、関数がタスクを完了できるスピードに合わせて各イベントソースのポーリング間隔を調整します。BatchSize は、各呼び出しで関数に送信できるレコードの最大数を制御します。通常、バッチサイズが大きいほど、大きなレコードセット全体での呼び出しのオーバーヘッドをより効率的に吸収し、スループットを増大できます。

    デフォルトでは、Lambda はストリームからレコードが利用可能になるとすぐに、関数を呼び出します。ストリームから読み込むバッチに、1 つのレコードしか含まれない場合、Lambda は関数に 1 つのレコードのみを送信します。少数のレコードで関数を呼び出すことを避けるため、[batch window (バッチウィンドウ)] を設定して、最大 5 分間レコードをバッファするようイベントソースに指定できます。Lambda は、関数を呼び出す前に、完全なバッチを収集するか、バッチウィンドウの有効期限が切れるまで、ストリームから継続してレコードを読み取ります。

  • シャードを追加して Kinesis ストリーム処理のスループットを向上させます。 Kinesis ストリームは 1 つ以上のシャードで構成されます。 Lambda は、最大で 1 つの同時呼び出しを使用して各シャードをポーリングします。たとえば、ストリームに 100 個のアクティブなシャードがある場合は、最大で 100 個の Lambda 関数呼び出しが同時に実行されます。シャードの数を増やすと、直接的な結果として、Lambda 関数の同時呼び出しの最大数が増えます。また、Kinesis ストリーム処理のスループットが増える場合があります。Kinesis ストリームのシャード数を増やす場合は、データの適切なパーティションキー (パーティションキーを参照) を選択していることを確認し、関連レコードが同じシャードに割り当てられ、データが適切に配分されるようにします。

  • Amazon CloudWatch を IteratorAge で使用し、Kinesis ストリームが処理されているかどうかを判断します。たとえば、CloudWatch アラームを最大値の 30000 (30 秒) に設定します。