Grandream
AWS ALB経由のAPIリクエストで発生する502エラーの対処法
今回はAWSのApplication Load Balancer(ALB)を使用したシステムでよく遭遇する502エラーについて、その原因と対処法を解説します。
発生する事象
ALBを経由してAPIサーバーへリクエストした際、稀に502エラーが返却されることがあります。具体的には以下のような状態になります:
- APIを叩いた側は502エラーを受け取っている
- ALBのメトリクスでも502エラーの記録がある
- しかし、API側にはエラーログが残っていない 🤔
原因
結論から言うと、以下の条件で発生します:
ALBのアイドルタイムアウト値 < API自体のkeepAlive値
これらの用語について説明します。
アイドルタイムアウト
これは、クライアント-ALB間、ALB-API間のコネクションが確立された後、一定時間データのやり取りがないと接続が切断される仕組みです。ALBのデフォルトでは60秒に設定されています。つまり、60秒間データのやり取りがないと自動的に切断されるということですね。
keepAlive
一方、keepAliveはコネクションを再利用するために一定時間維持する仕組みです。この値で「どのくらいの時間コネクションを維持するか」を指定します。
発生するケース
正常なケース
1. クライアントからALBへリクエスト: クライアント → ALB - APIサーバー
2. ALBからAPIへリクエスト: クライアント - ALB → APIサーバー
3. APIサーバーがレスポンスを返却: クライアント ← ALB ← APIサーバー
エラーが発生するケース
1. クライアントからALBへリクエスト: クライアント → ALB - APIサーバー
2. ALBからAPIへリクエスト: クライアント - ALB → APIサーバー
3. APIがレスポンスを返す前にALB-API間のコネクション切断: クライアント - ALB × APIサーバー
- API側は正常に処理して返そうとしますが、コネクションが切れているのでALBが受け取れない
4. ALBが502エラーを返却: クライアント ← ALB × APIサーバー
解決方法
解決方法はシンプルです。keepAlive値をALBのアイドルタイムアウト値より大きく設定しましょう。
以下にExpressでの実装例を示します:
const express = require('express');
const http = require('http');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
const server = http.createServer(app);
// Keep-Aliveタイムアウトの設定
// ALBのデフォルト値(60秒)より余裕を持って65秒に設定
server.keepAliveTimeout = 65000;
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
このように設定することで、ALBのコネクションが切れる前にAPI側のコネクションが切れることがなくなり、502エラーは解消されるはずです。
まとめ
今回は、ALB経由のAPIリクエストで発生する502エラーについて解説しました。エラーの原因は「ALBのアイドルタイムアウト値 < APIのkeepAlive値」という状態にあり、keepAlive値を適切に設定することで解決できます。
Grandream
株式会社グランドリーム
AI・システム開発のプロフェッショナルチームです。AIエージェント・業務自動化・Webシステム開発などを手がけています。