はい、承知いたしました。AWSのApplication Load Balancer(ALB)とAWS Lambdaを連携させ、非同期・同期イベントハンドリングを実現する際の、HTTPリクエスト・レスポンスのJSONペイロード変換とタイムアウト制御について、初心者の方にも分かりやすく、親しみやすいブログ記事を作成します。パケットの挙動や現場での知見を交えながら、実用的な情報をお届けします。
—
ALBをLambdaの「直接の門番」に!HTTPリクエストをイベントに変える秘密
皆さん、こんにちは! クラウド&コンテナネットワークの深淵へようこそ。今回は、AWSのロードバランサー、特にApplication Load Balancer(ALB)を使って、バックエンドにAWS Lambdaを直接つなげる、ちょっと面白い使い方に迫ります。
「え、LambdaってAPI Gatewayじゃないの?」と思われた方もいるかもしれませんね。確かに、LambdaをHTTPのエンドポイントとして公開する定番はAPI Gatewayです。でも、ALBを介してLambdaを呼び出すことで、また違った柔軟な使い方ができるんです。
特に、HTTPリクエストをLambdaに「イベント」として渡し、その結果をどう受け取るか、そして時間切れ(タイムアウト)にどう対応するか、この2つのポイントに焦点を当てて、郵便配達に例えながら、分かりやすく紐解いていきましょう!
郵便配達さん、ALBとLambdaのお届け物です!
まず、ALBとLambdaの連携を、身近な「郵便配達」に例えてみましょう。
- あなた(クライアント): 荷物を送りたい人。
- ALB: 大きな郵便局。たくさんの荷物(HTTPリクエスト)を受け付けて、適切な配達先(ターゲットグループ)に仕分けしてくれます。
- Lambda: 郵便局の奥にある、特別な荷物(イベント)を処理してくれる専門家。
- HTTPリクエスト: あなたが郵便局に預ける「荷物」。中身(リクエストボディ)や宛先(URL)、要望(HTTPメソッド)などが書かれています。
- HTTPレスポンス: Lambdaが荷物を処理した後、郵便局(ALB)を通じてあなたに返す「お返事」。
これまで、LambdaにHTTPリクエストを届ける場合、API Gatewayという「専用の窓口」を通していましたが、今回はALBという「大きな郵便局」の「直接の窓口」から、Lambdaという「専門家」に荷物を渡すイメージです。
ALBからLambdaへ:荷物の「形」を変える?(JSONペイロード変換)
ALBがLambdaをターゲットグループに設定すると、HTTPリクエストはLambdaにとって「イベント」として扱われます。ここで面白いのが、ALBがHTTPリクエストの情報を、Lambdaが理解しやすいJSON形式の「イベントペイロード」に変換してくれるという点です。
どんな情報がJSONになるの?
例えば、あなたが「GET /users?id=123」というHTTPリクエストをALBに送ったとしましょう。Lambda側から見ると、これは次のようなJSONイベントになるイメージです。
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/my-lambda-tg/xxxxxxxxxxxx"
}
},
"httpMethod": "GET",
"path": "/users",
"queryStringParameters": {
"id": "123"
},
"headers": {
"host": "my-alb-xxxx.ap-northeast-1.elb.amazonaws.com",
"user-agent": "curl/7.64.1"
// ... その他のヘッダー情報
},
"body": null, // GETリクエストなのでボディはnull
"isBase64Encoded": false
}
どうでしょう? 元のHTTPリクエストの「メソッド」「パス」「クエリパラメータ」「ヘッダー」といった情報が、すべてJSONのキーと値のペアになって、Lambdaに渡されているのが分かりますね。まるで、郵便配達さんが荷物の情報を分かりやすくリスト化してくれるかのようです。
LambdaからALBへ:お返事の「形」も重要!
Lambdaで荷物(イベント)を処理した後、ALBに「お返事」を返す必要があります。このお返事も、ALBがクライアント(あなた)にHTTPレスポンスとして返すために、決められたJSON形式で返す必要があるんです。
例えば、Lambdaが処理結果として「ユーザーID: 123 は存在しません」というメッセージを返したい場合、Lambda関数(Pythonで書いたと仮定)では、以下のようなJSONを返します。
import json
def lambda_handler(event, context):
# ここでイベント(HTTPリクエスト情報)を処理するロジックを書く
response_body = {
"message": "ユーザーID: 123 は存在しません。",
"status_code": 404 # HTTPステータスコードも指定できます
}
return {
"statusCode": 404, # ここでHTTPステータスコードを指定
"headers": {
"Content-Type": "application/json"
},
"body": json.dumps(response_body) # ボディは文字列にする必要があります
}
このJSONのポイントは以下の3つです。
statusCode: クライアントに返すHTTPステータスコードです。headers: レスポンスヘッダーを指定します。Content-Typeは重要ですね。body: レスポンスボディです。Lambdaで処理した結果をJSON形式にする場合は、json.dumps()で文字列に変換してから指定します。isBase64EncodedをtrueにしてBase64エンコードされたバイナリデータを返すことも可能です。
【重要】 Lambdaがこの形式でJSONを返さないと、ALBは「お返事」を正しく受け取れず、クライアントにエラーを返してしまうことがあります。まるで、郵便配達さんが、受け取りサインの代わりに奇妙な記号を書いてしまうようなものです。
時間切れ!パケットはどうなる?(タイムアウト制御)
さて、ここで現実的な問題です。郵便配達さんが荷物を届けに行くのに、あまりにも時間がかかりすぎたらどうなるでしょうか? 待っている側は困ってしまいますよね。
HTTP通信でも同じで、リクエストを送ったクライアントは、いつまでも応答を待ち続けるわけにはいきません。そこで、タイムアウトという仕組みがあります。
ALBとLambdaの連携では、主に2つのタイムアウトが関係してきます。
1. ALBのタイムアウト:
- ALBは、ターゲット(この場合はLambda)からの応答を待つ最大時間を設定できます。デフォルトは60秒です。
- これは、ALBが「このリクエスト、いつまで待てばいいんだっけ?」と判断する時間です。
- もしLambdaからの応答がこの時間内に返ってこなければ、ALBはクライアントに「504 Gateway Timeout」といったエラーを返します。
2. Lambdaのタイムアウト:
- Lambda関数自体にも、実行時間の最大値を設定できます。これは最小1秒、最大15分(900秒)です。
- これは、Lambda関数が「この処理、いつまで頑張ればいいんだっけ?」と判断する時間です。
- もしLambda関数がこの時間内に処理を終えられなければ、Lambdaサービスが実行を強制終了します。
どっちが先にタイムアウトする?
通常、ALBのタイムアウト(デフォルト60秒)よりも、Lambdaのタイムアウト(最大15分)の方が長いです。そのため、多くの場合、Lambda関数がタイムアウトして処理が中断されることになります。
もし、Lambda関数が10秒で完了するはずが、何らかの理由で1分以上かかってしまった場合、ALBの60秒タイムアウトが先に発生し、クライアントにはタイムアウトエラーが返ります。Lambda側では、60秒を超えた時点で処理が中断されますが、その結果をALBに返すことはできません。
タイムアウトをどう制御するか?
- Lambdaの処理を高速化する: これが一番根本的な解決策です。コードを最適化したり、必要なリソースを増やしたり(メモリ割り当てなど)して、Lambdaの実行時間を短縮しましょう。
- Lambdaのタイムアウトを適切に設定する: 処理にかかる時間を予測し、Lambdaのタイムアウトをそれよりも少し長めに設定します。しかし、無限に長くすることはできません。
- ALBのタイムアウトを調整する: 非常に稀なケースですが、Lambdaの処理がALBのデフォルトタイムアウト(60秒)を超えることが分かっている場合は、ALBのタイムアウトを延長することも検討できます。ただし、これはクライアント側の体験を損なう可能性があるので注意が必要です。AWSのドキュメントによると、ALBのタイムアウトは最大3599秒まで設定可能です。
【実用的な設定例】
ALBのターゲットグループ設定で、Lambdaのタイムアウトを意識した設定をしてみましょう。
- ALBのターゲットグループ作成時:
- Target type:
Lambda functionを選択します。 - Timeout: Lambda関数の実行時間に合わせて、適切に設定します。例えば、Lambdaが最大30秒かかると予測されるなら、ALBのタイムアウトも30秒以上に設定しておくと安心です。
- Lambda関数の設定:
- AWS Lambdaコンソールで、対象の関数を選択し、「設定」タブから「一般設定」の「タイムアウト」を、ALBのタイムアウトや想定される処理時間に合わせて調整します。
非同期 vs 同期イベントハンドリング
ここで、ALBとLambdaの連携が「非同期」と「同期」のどちらのパターンで使われるか、少し整理しておきましょう。
- 同期: クライアントがリクエストを送り、Lambdaでの処理結果をすぐにHTTPレスポンスとして受け取る場合。これは、今回説明してきた、ALBがLambdaのJSONレスポンスをクライアントに返すパターンです。
- 非同期: クライアントがリクエストを送った後、Lambdaでの処理完了を待たずにALBが応答を返し、Lambdaはバックグラウンドで処理を続ける場合。例えば、ALBはHTTP 202 Accepted (処理を受け付けました) を返し、LambdaはS3にファイルをアップロードしたり、別のサービスに通知したりするようなケースです。この場合、LambdaからのHTTPレスポンスは必ずしも必要ではなく、ALBからの応答も「受け付けました」というシンプルなもので構いません。
ALBをLambdaターゲットに直接指定した場合、基本的には同期的なリクエスト・レスポンスとして動作します。クライアントはLambdaからの処理結果をHTTPレスポンスとして受け取ります。
まとめ:ALBとLambdaの連携で広がる可能性
いかがでしたか? ALBをLambdaの「直接の門番」として使うことで、HTTPリクエストをJSONイベントとしてLambdaに渡し、その結果をHTTPレスポンスとして受け取る、という一連の流れがイメージできたのではないでしょうか。
- ALBはHTTPリクエストをLambdaが理解しやすいJSONイベントに変換してくれる。
- Lambdaは処理結果を、ALBがクライアントに返せるJSON形式で返す必要がある。
- ALBのタイムアウトとLambdaのタイムアウト、両方に注意して、適切な設定を行うことが重要。
この連携は、API Gatewayを使うよりもシンプルにLambdaをHTTPエンドポイントとして公開したい場合や、既存のALBのインフラを活用したい場合に非常に有効です。
「え、でもLambdaって、やっぱりAPI Gatewayを使った方がいいんじゃない?」と思われたあなた。ご安心ください! 次回は、API GatewayとLambdaの連携についても、その違いや使い分けについて、さらに深掘りしていきますよ。
まずは、今回学んだALBとLambdaの連携を、ぜひ皆さんの環境で試してみてくださいね! パケットがネットワークを駆け巡る感覚を、きっと掴めるはずです!
コメント