HTTPキープアライブの無効化がなぜ性能劣化につながるのか──スモークテストでは見えない実負荷での影響

はじめに:設定変更で「なぜか遅くなった」という判断の分かれ目

Webサーバーの設定を調整する際、HTTPキープアライブ(Keep-Alive)の有効・無効を検討する場面があります。セキュリティ対策やメモリ圧迫への対応として無効化を検討するのは自然な判断です。しかし、スモークテストや軽い負荷テストでは問題が見えず、本番環境で投入した途端に「レスポンスが悪化した」という報告が上がることがあります。

この記事では、キープアライブの無効化がなぜ実負荷で性能に影響するのか、検証方法と判断ポイントを整理します。

キープアライブの役割と「無効化しても大丈夫」の落とし穴

HTTPキープアライブは、TCP接続を複数のHTTPリクエスト・レスポンス間で再利用する仕組みです。有効時は、クライアントとサーバー間の接続を一定時間保持し、次のリクエストで新しいTCP接続を張り直す手間を省きます。

無効化すると、リクエストごとにTCP接続のハンドシェイク(SYN、SYN-ACK、ACK)が発生します。ローカルネットワークでは数ミリ秒程度ですが、インターネット経由やモバイルネットワークではこのオーバーヘッドが積み重なります。

スモークテストで見えない理由:

  • テストは短時間に少数のリクエストを送る
  • ハンドシェイクのコストが全体に占める割合が小さい
  • ネットワーク遅延の変動が少ない環境

本番環境で顕在化する理由:

  • 複数のクライアントから継続的にリクエストが到着
  • モバイルクライアント、地理的に離れたユーザーからのアクセスがある
  • ネットワーク遅延が変動する
  • サーバーのコネクション数上限に達しやすくなる

検証環境の構築:キープアライブの有無を比較する

実際の影響を測定するため、Nginxを例に簡単な検証構成を組みます。

Nginxの設定例:

# キープアライブ有効の場合
http {
    keepalive_timeout 65;
    keepalive_requests 100;
}

# キープアライブ無効の場合
http {
    keepalive_timeout 0;
}

検証の構成:

  1. 同一サーバーに2つのNginxプロセスを起動(ポート8001、8002)
  2. 一方はキープアライブ有効、一方は無効に設定
  3. 同じ静的コンテンツを返すようにする
  4. 複数クライアントから並行リクエストを送信

負荷テストの実施方法:

# キープアライブ有効の場合(-k オプション)
ab -n 1000 -c 50 -k http://localhost:8001/

# キープアライブ無効の場合
ab -n 1000 -c 50 http://localhost:8002/

ここで重要なのは、-c 50(同時接続数50)という条件です。スモークテストでは通常 -c 1-c 5 程度で実行しますが、実負荷では複数ユーザーが並行アクセスします。

検証結果:何が変わるのか

実際に測定すると、以下のような傾向が観察できます。

レスポンスタイム(平均):

条件 平均応答時間 最大応答時間
キープアライブ有効 約50ms 約150ms
キープアライブ無効 約120ms 約500ms

差は環境によって異なりますが、無効化すると1.5~3倍の劣化が見られることが多いです。

スループット(1秒当たりのリクエスト処理数):

  • キープアライブ有効:約900 req/sec
  • キープアライブ無効:約400 req/sec

サーバーのコネクション数:

キープアライブ無効時は、同時接続数が増加し、サーバーのファイルディスクリプタ上限(ulimit)に近づきやすくなります。

なぜスモークテストでは見えないのか

テスト環境とのギャップを整理します。

テスト環境の特性:

  • 少数のリクエスト(数十~数百)
  • 短時間の実行
  • ネットワーク遅延が一定
  • CPU・メモリに余裕がある

このような条件では、TCP接続のハンドシェイクコストが全体に占める割合が小さく、統計的に有意な差が出ません。

本番環境の特性:

  • 継続的で大量のリクエスト
  • ネットワーク遅延の変動が大きい
  • サーバーリソースが逼迫する時間帯がある
  • クライアント側のタイムアウト設定が影響する

特にモバイルアプリやブラウザからのアクセスでは、キープアライブの有無がユーザー体験に直結します。

実務での判断ポイント

キープアライブを無効化すべきか、有効のままか判断する際の確認項目を整理します。

キープアライブを無効化する場合:

  • セキュリティ対策(Slowloris攻撃対策)が必須
  • リバースプロキシ経由でのアクセスに限定
  • クライアント数が少ない(社内ネットワークなど)
  • 接続時間が極めて短い(WebSocketなど別プロトコルに移行)

キープアライブを有効のままにする場合:

  • インターネット向けのサービス
  • モバイルクライアントからのアクセスがある
  • レスポンス性能が重要
  • Slowloris対策は keepalive_timeout を短く設定して対応

現場では、以下の構成が一般的です:

# セキュリティと性能のバランスを取った設定例
http {
    keepalive_timeout 15;      # 15秒で接続を切断
    keepalive_requests 50;     # 50リクエストで接続を切断
    client_max_body_size 10m;
}

短いタイムアウト値でもキープアライブの利点は残り、Slowloris攻撃の被害も軽減できます。

本番投入前に確認すべきこと

キープアライブの設定変更を本番に反映する際のチェックリスト:

  1. 本番相当の負荷でテストしたか → 最低でも同時接続数50以上、数分間の継続負荷
  2. ネットワーク遅延を考慮したか → ローカルテストだけでなく、WAN経由のテストも実施
  3. モバイルクライアントからのアクセスをテストしたか → タイムアウト設定の互換性確認
  4. サーバーのリソース上限を確認したか → ファイルディスクリプタ、メモリ、CPU
  5. ロードバランサーの設定は調整済みか → キープアライブの設定が複数層で一貫しているか

まとめ

HTTPキープアライブの無効化は、セキュリティ上の理由で検討される判断です。しかし、実負荷での影響は思いのほか大きく、スモークテストでは検出できません。

本番環境に反映する前に、必ず本番相当の負荷条件での検証を実施することをお勧めします。その際は、同時接続数、継続時間、ネットワーク遅延の変動を考慮した条件を設定してください。

多くの場合、完全な無効化ではなく、タイムアウト値を短く設定する方法で、セキュリティと性能のバランスが取れます。