AWS ALB経由のAPIリクエストで発生する502エラーの対処法

2025-01-07
広瀬 雅季
#
#
#

今回は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では、フルリモートであなたのスキルを活かし、活躍できるエンジニアを募集しております。 詳しくは採用ページをご確認いただき、お気軽にお問い合わせください。

株式会社グランドリームでは、AWSを駆使した開発からUI/UXデザインまで、Webアプリケーションに関するすべての要望に応えます。
まずは一度お気軽にご相談ください。

お問い合わせはこちら