【入門編】 TCPタイムアウト設定の最適化とアイドルコネクションの維持 – クラウド&コンテナネットワーク実践ガイド

こんにちは!SREとして日々クラウドの荒波と格闘している筆者です。

皆さんは、クラウド上に構築したシステムで「数分間何も操作しないで放置していたら、データベースとの接続がプッツリと途切れてエラー画面になってしまった……」なんていう、冷や汗もののトラブルに直面したことはありませんか?

「さっきまで普通に動いていたのに、なぜ!?」と頭を抱えたくなるこの現象、実はクラウドのネットワークの「お約束」と、TCP通信の「無言のルール」がすれ違っていることが原因であることが多いのです。

今回は、AWSのNATゲートウェイなどを例に挙げながら、この厄介な「TCPタイムアウト」の正体を紐解き、ロングコネクションを安全に維持するための実践的なテクニックを優しく解説していきます。一歩ずつ、リラックスして読み進めていきましょう!

—

1. 郵便局の窓口ルールに例える「NATゲートウェイとアイドルタイムアウト」

まずは、パケットの気持ちになって現実世界に置き換えて考えてみましょう。

皆さんが、社外の重要なお取引先(外部APIサーバーなど)へ手紙を送るシーンを想像してください。社内のプライベートな空間(プライベートサブネット)にいるあなたたちは、外の世界に直接手紙を出すことができません。そこで、社外への窓口を一手に引き受けてくれる「総務部のおじさん(NATゲートウェイ)」にお願いして、手紙を代行発送してもらう仕組みになっています。

ここで、総務部のおじさんには厳格なルールがあります。
「最後のやり取りから350秒間(約6分間)、お互いのやり取り(通信)が全くなかったら、このファイルフォルダー(コネクションの記憶)は片付けちゃうからね!」

これが、クラウドのネットワーク機器に備わっている「アイドルタイムアウト」という仕組みです。おじさんの机のスペースには限りがあるため、ずっと喋っていない相手の記憶をいつまでも覚えておけないわけですね。

なぜこのタイムアウトが存在するのか?

インターネットの出入り口であるNATゲートウェイは、膨大な数のサーバーの通信を裏でさばいています。もし、何年も前に一度だけ通信したきりの「死んだコネクション」の記憶をずっと保持し続けたらどうなるでしょうか? ゲートウェイのメモリがパンクしてしまい、新しい通信ができなくなってしまいますよね。

そのため、「しばらく音沙汰がないなら、一度リセットして席を空けよう」という合理的な理由で、このタイムアウト値が設定されているのです。大抵のクラウドサービス(AWSのNAT Gatewayなど)では、このアイドルタイムアウト値が固定の 350秒 に設定されています。

—

2. 「何も話すことがない」けれど、繋ぎ続けたいときのジレンマ

さて、ここからが本題です。
例えば、WebブラウザとバックエンドのサーバーがWebSocketや長めのポーリング(ロングポーリング)、あるいは常時接続のデータベースセッションで繋がっているとします。

ユーザーが画面をじっと見つめて操作していない「アイドル状態」のとき、ネットワーク上にはデータが流れません。しかし、アプリケーションとしては「いつでもすぐに通信を再開できるように、この回線は繋ぎっぱなしにしておきたい!」わけです。

ここで先ほどの総務部のおじさんを思い出してください。
おじさんは、お互いが静かにしていると、こうカウントダウンを始めます。
「10秒経過……、100秒経過……、お、そろそろ350秒経つけど、まだ何も喋らないな……よし、もう用事はないものとみなして記憶を消去(切断)しちゃうぞ!」

そして350秒が経過した瞬間、おじさんは綺麗に記憶を消去します。
その直後、ユーザーが急に画面を操作してデータを要求したとします。「おーい、さっきの続きだよ!」と手紙を渡そうとしても、おじさんは「えっ、どなた様でしたっけ?もうファイルは捨てましたよ」と冷たく突っぱねてしまいます。これが、突然のコネクション切断エラーのメカニズムです。

—

3. 解決の切り札!「TCP Keep-Alive」という名の小声の挨拶

「じゃあ、350秒以内に何かしらのデータを無理やり送り続ければいいの?」
その通りです!データが流れていれば、おじさんのタイマーはリセットされ、カウントダウンは最初からやり直しになります。

とはいえ、アプリケーションの肝心なデータを無駄に送りたくはありませんよね。そこで登場するのが、TCPのプロトコル自体に備わっている機能「TCP Keep-Alive(キープアライブ)」です。

これは、人間関係に例えるなら、「定期的に『生きてる?』『うん、元気だよ』とアイコンタクトを交わす仕草」です。

データ本体(中身)ではなく、ネットワークの接続が生きているかを確認するためだけの「空っぽのパケット(小声の挨拶)」を、裏でこっそりと一定間隔で送り続けます。これによって、NATゲートウェイのタイマーを常にリフレッシュし続け、おじさんに「まだこの回線は使ってますよ!」とアピールできるのです。

—

4. 実践!アプリケーションやOSでのパラメータ調整手法

それでは、実際にこのTCP Keep-Aliveをどのように設定すればよいのか、具体的な設定例を見ていきましょう。

実務では、主にOSのネットワーク層(Linuxのカーネルパラメータ)、あるいは利用しているプログラミング言語・データベースの接続設定の2箇所で調整を行います。

パターンA: Linuxカーネル全体で設定する場合(OSレベル)

お使いのLinuxサーバー(Amazon LinuxやUbuntuなど)で、OS全体としてTCP Keep-Aliveの頻度を調整したい場合は、/etc/sysctl.conf などの設定ファイルをいじります。

AWSのNAT Gatewayのタイムアウトが 350秒 であることを踏まえると、それよりも短い間隔(例えば 60秒ごと)で挨拶を送るように設定するのが安全です。

以下の設定を追加してみましょう。

# /etc/sysctl.conf の末尾などに追記する設定例

# 1. 最後にデータが流れてから、何秒後に最初のKeep-Aliveパケットを送り始めるか(例: 60秒)
net.ipv4.tcp_keepalive_time = 60

# 2. 最初の一回を送ったあと、返事がなかった場合に何秒おきに再送するか(例: 10秒)
net.ipv4.tcp_keepalive_intvl = 10

# 3. 何回連続で返事がなかったら「この接続はもうダメだ」と判断して切断するか(例: 5回)
net.ipv4.tcp_keepalive_probes = 5

設定を反映させるためには、以下のコマンドを実行します。

# 設定を即時反映させるコマンド
sudo sysctl -p

この設定により、およそ60秒ごとに「生きてる?」の確認が入るため、NATゲートウェイの350秒というタイムアウトの壁を余裕でクリアし続けられるようになります。

パターンB: Python(Requestsやデータベース接続)から制御する場合

アプリケーションコード側から明示的にKeep-Aliveの間隔を制御したい場合もあります。例えば、Pythonで外部APIと長く通信するようなケースです。

ソケットレベルやライブラリのオプションでKeep-Aliveを有効にするコードの書き方を見てみましょう。

import socket
import requests
from requests.adapters import HTTPAdapter

# セッションを作成してコネクションをプールする
session = requests.Session()

# アダプターを設定し、リトライや接続維持の挙動を整える
# (※実際のOSソケットレベルでのKeep-Alive有効化は、低水準のsocket操作やライブラリ依存になります)
adapter = HTTPAdapter(
    pool_connections=10,
    pool_maxsize=10,
    max_retries=3
)

session.mount('https://', adapter)

# 実際にリクエストを送る例
try:
    # 接続を維持(Keep-Alive)しながらリクエストを送信
    response = session.get('https://api.example.com/long-process', timeout=30)
    print(f"ステータスコード: {response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"通信エラーが発生しました: {e}")

データベース(PostgreSQLやMySQLなど)に接続する場合も、大抵のORMやドライバー(例: SQLAlchemy や pg_config)には、connect_args や設定ファイルを通じて keepalives_idle といったパラメータを渡す仕組みが用意されています。インフラ側のタイムアウト値と合わせて、必ずアプリケーション側でも適切な数値を指定するように心がけましょう。

—

5. まとめ:クラウドネットワークと仲良く付き合うために

今回は、NATゲートウェイのアイドルタイムアウトの仕様と、ロングコネクションを守るためのTCP Keep-Aliveの仕組みについて解説しました。

  • NATゲートウェイは、一定時間(例: 350秒)無言が続くとコネクションの記憶を忘れてしまう。
  • 対策として、TCP Keep-Aliveを使って定期的に「生きてますアピール」のパケットを流すことが重要。
  • OSの設定(tcp_keepalive_time)やアプリの接続設定を、クラウドの仕様(タイムアウト秒数)よりも短めにチューニングしよう。

「ネットワークの裏側で何が起きているのか」をイメージできるようになると、エラーに直面したときも慌てず騒がず、冷静に原因を特定できるようになります。

皆さんのインフラライフが、タイムアウトエラーに悩まされない、快適で安定したものでありますように!それではまた次回の技術解説でお会いしましょう。

コメント

タイトルとURLをコピーしました