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

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

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

Lambda アプリケーションのベストプラクティスの詳細については、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 ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。

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

  • 永続的な接続を維持するには、keep-alive ディレクティブを使用します。Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「Node.js で Keep-alive を使用して接続を再利用する」を参照してください。

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

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

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

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

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

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

Function Configuration

  • Lambda 関数のパフォーマンステストは、最適なメモリサイズ設定を選択する上で欠かせない部分です。メモリサイズが増えると、関数で利用できる CPU も同様に増加します。関数のメモリ使用量は呼び出しごとに決定され、Amazon CloudWatch で表示できます。次に示すように、呼び出しごとに 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: フィールドを分析することで、関数のメモリが不足しているか、関数のメモリサイズをオーバープロビジョニングしているかを判断できます。

    関数のために適切なメモリの構成を見つけるには、オープンソースの AWS Lambda Power Tuning プロジェクトを使用することを推奨しています。詳細については、GitHub の AWS Lambda Power Tuning を参照してください。

    関数のパフォーマンスを最適化するためには、Advanced Vector Extensions 2 (AVX2) が利用可能なライブラリのデプロイも推奨されます。これにより、機械学習による推定、メディア処理、ハイパフォーマンスコンピューティング (HPC)、科学シミュレーション、財務モデリングなど、負荷が大きくなりがちなワークロードを処理できるようになります。詳細については、AVX2 を使用した高速な AWS Lambda 関数の作成を参照してください。

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

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

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

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

  • イベントソースとして Amazon Simple Queue Service を使用している場合、関数の予想呼び出し時間の値が、キューの可視性タイムアウトの値を超過していないことを確認してください。これは、CreateFunctionおよびUpdateFunctionConfigurationの両方に適用されます。

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

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

メトリクスおよびアラーム

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

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

ストリームの使用

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

    デフォルトでは、ストリーミングでレコードが使用可能になると、Lambda はすぐに関数を呼び出します。Lambda がストリーミングから読み取るバッチにレコードが 1 つしかない場合、Lambda は関数に 1 つのレコードだけを送信します。少数のレコードで関数を呼び出さないようにするには、バッチウィンドウを設定して、最大 5 分間レコードをバッファリングするようにイベントソースに指示できます。関数を呼び出す前に、Lambda は完全なバッチを収集するまで、またはバッチウィンドウの期限が切れるまで、ストリームからレコードを読み取り続けます。

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

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