Lambda 関数の API Gateway 統合の問題をトラブルシューティングする方法を教えてください。
AWS Lambda 関数の Amazon API Gateway 統合の問題をトラブルシューティングしたいと考えています。
解決策
API ログ記録を有効にする
次の手順を実行します。
- API Gateway コンソールを開きます。
- ナビゲーションペインで [API] を選択し、該当する API を選択します。
- ナビゲーションペインで [ステージ] を選択し、該当するステージを選択します。
- [ログとトレース] で [編集] を選択します。
- [CloudWatch Logs] で、ドロップダウンリストからレベルを選択します。<br id=hardline_break/> 注: リクエストログと応答ログをすべて表示するには、[データトレース] オプションを選択し、ログレベルを [エラーと情報ログ] に設定します。データトレースにより、機密データがログに記録される可能性があるため、本番用 API では [データトレース] を有効にしないことをおすすめします。
- [詳細なメトリクス] を選択します。
- [カスタムアクセスのログ記録] で次の手順を実行します。<br id=hardline_break/> [アクセスログ記録の有効化] を選択します。<br id=hardline_break/> [アクセスログの宛先 ARN] で Amazon Data Firehose または CloudWatch ロググループの Amazon リソースネーム (ARN) を入力します。<br id=hardline_break/> 注: REST API のみが Firehose ARN をサポートしています。
- ログの形式を入力します。
- [保存] を選択します。
統合タイプを決定し、エラーを検証し、解決するための次のステップを実行する
次の手順を実行します。
-
Lambda プロキシ統合と Lambda カスタム統合のどちらが API Gateway で設定されているかを確認します。統合タイプを確認するには、[統合リクエスト] で [Lambda プロキシ統合] の値を確認します。
-
API Gateway のエラーが Lambda のエラーに対応していることを確認します。次の CloudWatch Logs Insights クエリを実行して、指定した期間におけるエラーステータスコードを確認します。
parse @message '(*) *' as reqId, message | filter message like /Method completed with status: \d\d\d/ | parse message 'Method completed with status: *' as status | filter status != 200 | sort @timestamp asc | limit 50 -
次の CloudWatch Logs Insights クエリを実行して、同じ期間の Lambda エラーログを検索します。
fields @timestamp, @message | filter @message like /(?i)(Exception|error|fail)/ | sort @timestamp desc | limit 20 -
ログで特定したエラーの種類に基づいて、次のいずれかを選択します。<br id=hardline_break/> 次のエラーが表示された場合は、「同時実行に関する問題の解決」セクションの手順を実行してください。
(#####) Lambda invocation failed with status: 429. Lambda request id: ########## () Execution failed due to configuration error: Rate Exceeded. (#####) Method completed with status: 500以下のエラーのいずれかが表示された場合は、「タイムアウトの問題の解決」セクションの手順を実行してください。<br id=hardline_break/> Lambda カスタム統合の場合
< Integration timeout: (#####) Method response body after transformations: {"errorMessage":"2019-08-14T02:45:14.133Z ########-####-####-####-############ Task timed out after ##.01 seconds"} > Integration timeout: (#####) Execution failed due to a timeout errorLambda プロキシ統合の場合
< Integration timeout: (#####) Endpoint response body before transformations: {"errorMessage":"2019-08-14T02:50:25.865Z ########-####-####-####-############ Task timed out after ##.01 seconds"} > Integration timeout: (#####) Execution failed due to a timeout error次のエラーが表示された場合は、「関数エラーの解決」セクションの手順を実行してください。
(#####) Execution failed due to configuration error: Malformed Lambda proxy response (#####) Method response body after transformations: {"errorMessage": "Syntax error in module 'lambda_function'"}
同時実行に関する問題の解決
Lambda 関数がスケールできない速度で API Gateway から追加のリクエストが届くと、429 スロットリングエラーまたは 500 エラーが発生します。
これらのエラーを解決するには、次の CloudWatch メトリクスを分析してください。 カウント (API Gateway)、スロットル (Lambda)、ConcurrentExecutions (Lambda)。次の点を考慮してください。
- カウント (API Gateway) は、指定された期間内の API リクエストの合計数です。
- スロットル (Lambda) はスロットルされた呼び出しリクエストの数です。すべての関数インスタンスがリクエストを処理し、スケールアップできる同時実行がない場合、Lambda は TooManyRequestsException エラーで追加のリクエストを拒否します。スロットリングされたリクエストやその他の呼び出しエラーは、呼び出しやエラーとしてカウントされません。
- ConcurrentExecutions (Lambda) は、イベントを処理する関数インスタンスの数です。この数が AWS リージョンの同時実行クォータに達すると、追加の呼び出しリクエストが制限されます。また、Lambda は、関数インスタンスの数が、関数に設定した予約済みの同時実行制限に達したときにも呼び出しリクエストを抑制します。
注: 詳細については、「API Gateway のメトリクス」および「Lambda での CloudWatch メトリクスの使用」を参照してください。
Lambda 関数に同時実行予約を設定した場合は、同時実行予約数を増やしてください。または、Lambda 関数から予約同時実行数を削除します。これにより、関数は予約されていない同時実行のプールから使用します。
Lambda 関数で同時実行予約を設定していない場合は、ConcurrentExecutions メトリクスを確認して使用状況を確認してください。詳細については、「Lambda クォータ」を参照してください。
タイムアウトの問題の解決
すべての API Gateway 統合のデフォルトの統合タイムアウト制限は 29 秒です。クォータリクエストを送信して、リージョン API とプライベート API のデフォルトの統合タイムアウト制限クォータを 29 秒より長くすることができます。ただし、統合タイムアウトを引き上げると、AWS アカウントでリージョンレベルのスロットルクォータを減らす必要がある場合があります。
注: 統合タイムアウト制限を引き上げる場合は、デフォルトのタイムアウト値である 29 秒から新しい値に必ず変更してください。たとえば、引き上げを適用したい統合のデフォルトのタイムアウト値である 29 秒を変更します。次に、新しい統合タイムアウト制限が有効になるように API を再デプロイします。
Lambda 統合を使用して API Gateway API を構築すると、次のいずれかのシナリオが発生する可能性があります。
- タイムアウト値が統合タイムアウト値より小さい。
- タイムアウト値が統合タイムアウト値より大きい。
Lambda 関数のタイムアウトが 29 秒未満の場合は、Lambda ログを確認してこの問題を調査してください。Lambda 関数を 29 秒後に実行する必要がある場合は、Lambda 関数を非同期で呼び出します。
Lambda 非同期呼び出しカスタム統合では、次の手順を実行します。
- API Gateway コンソールを開きます。
- ナビゲーションペインで [API] を選択し、目的の API を選択します。
- [リソース] を選択し、次に方法を選択します。
- [統合リクエスト] を選択します。
- [メソッドリクエスト] を選択します。
- [HTTP リクエストヘッダー] を展開します。
- [ヘッダーを追加] を選択します。
- [名前] にヘッダーの名前を入力します。例: X-Amz-Invocation-Type<br id=hardline_break/> 重要: 'Event' からヘッダーをマップする必要があります。一重引用符を使用する必要があります。
Lambda プロキシ統合では、関数 A と関数 B の 2 つの Lambda 関数を使用します。API Gateway は最初に関数 A を同期的に呼び出します。次に、関数 A は関数 B を非同期的に呼び出します。関数 B が非同期的に呼び出されると、関数 A は API Gateway に正常な応答を返すことができます。
Lambda プロキシ統合を使用する場合、統合をカスタム統合に変更できます。ただし、リクエストまたは応答を特定の形式に変換するには、マッピングテンプレートを設定する必要があります。詳細については、「バックエンド Lambda 関数の非同期呼び出しをセットアップする」を参照してください。
注: 非同期 Lambda 関数はバックグラウンドで実行されるため、クライアントは Lambda 関数からデータを直接受け取ることができません。永続データを保存するには、中間データベースが必要です。
関数エラーの解決
API を呼び出すときに関数エラーが発生した場合は、Lambda 関数に構文エラーがないか確認してください。このエラーは、Lambda 関数が API Gateway がプロキシ統合で期待する有効な JSON オブジェクトを返さなかった場合にも表示されます。
API Gateway の実行ログから、ログ内の AWS 統合エンドポイントの RequestID 値を確認できます。
(#####) AWS Integration Endpoint RequestId : YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY
次に、次の CloudWatch Logs Insights クエリを実行して、同じ特定の期間の Lambda ログを検索できます。
fields @timestamp, @message, @requestId, @logStream | filter @requestId = 'YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY' | sort @timestamp asc
このエラーを解決するには、「API とステージのログ記録を有効にする」セクションの手順を実施してください。
正しくない REST API ステータスコード応答を上書きする
API Gateway が誤ったステータスコードを返す場合は、マッピングテンプレートを作成して、誤ったステータスコードを正しいステータスコードに上書きします。REST API との非プロキシ統合では、ステータスコード応答を上書きできます。
注: このマッピングテンプレート設定は REST API にのみ適用されます。HTTP API については、「HTTP API の API Gateway 統合に対する応答ステータスコードをマッピングする方法を教えてください」を参照してください。
たとえば、API Gateway が Lambda 関数から 4## や 5## の代わりに 200 ステータスコードを返す場合は、次の手順を実行します。
-
API Gateway コンソールを開き、ナビゲーションペインで [API] を選択します。
-
REST API を選択し、[統合レスポンス] タブを選択します。
-
[統合レスポンス設定] で、[編集] を選択します。
-
[マッピングテンプレート] を展開し、[マッピングテンプレートの追加] を選択します。
-
[コンテンツタイプ] に application/json と入力します。
-
マッピングテンプレートエディタで、次のコードを入力します。
#set($inputRoot = $input.path('$')) $input.json("$") #if($inputRoot.toString().contains("error")) #set($context.responseOverride.status = 400) #end -
[保存] を選択します。
$context.responseOverride.status パラメータは、統合レスポンスペインで、デフォルトマッピングの代わりに、ステータスコードを 400 に上書きします。
詳細については、「API Gateway で REST API の API リクエストパラメータおよびレスポンスパラメータとステータスコードを上書きする」を参照してください。
REST API 統合で必要な CORS ヘッダーを返すように設定する
応答で必要な CORS ヘッダーを返すには、バックエンドの AWS Lambda 関数または HTTP プロキシサーバーを設定します。Access-Control-Allow-Origin ヘッダー値には、許可するドメインをリストとして含める必要があります。
プロキシ統合では、API Gateway で統合の応答を設定し、API のバックエンドが返す応答パラメータを変更することはできません。プロキシ統合では、API Gateway からバックエンド応答はクライアントに直接転送されます。必要な CORS ヘッダーを返すように Lambda 関数または HTTP 統合を設定する必要があります。
非プロキシ統合を使用する場合は、API Gateway で統合応答を手動で設定し、必要な CORS ヘッダーを返す必要があります。API Gateway コンソールを使用して CORS を設定します。コンソールは、必要な CORS ヘッダーを設定したリソースに自動的に追加します。
詳細については、「API Gatewayが CORS エラーを返す場合のトラブルシューティング方法を教えてください」を参照してください。
バイナリペイロード Lambda プロキシ統合
バイナリペイロードは、テキストペイロード以外のものを指します。たとえば、バイナリペイロードには、.jpeg ファイル、.gzip ファイルなどがあります。これには、.pdf アプリケーション、.jpeg 画像、.zip アプリケーションなどの一般的なバイナリデータが含まれます。
Lambda プロキシ統合のバイナリペイロードを処理するには、関数の応答を base64 でエンコードし、API の binaryMediaTypes を設定する必要があります。非プロキシ統合のバイナリペイロードを処理するには、メディアタイプを RestAPI リソースの binaryMediaTypes リストに追加する必要があります。
詳細については、「API Gateway での REST API のバイナリメディアタイプ」を参照してください。
関連情報
- 言語
- 日本語
