...

TCPキープアライブ設定:ホスティングコンテキストにおける最適化

TCPキープアライブ これは、ホスティングにおけるリソース消費、待ち時間、ダウンタイムの挙動に直接影響する制御レバーです。適切なアイドル値、インターバル値、プローブ値により、接続のデッドスポットを減らし、NATのドロップを防ぎ、ウェブアプリケーションを ホスティング設定 確実にアクセスできる。.

中心点

  • パラメータアイドリング、インターバル、ターゲットにプローブをセット
  • デマケーションTCPキープアライブとHTTPキープアライブの比較
  • ソケットあたりサービス/Kubernetesポッドごとのオーバーライド
  • ファイアウォール/NATアイドルタイムアウトを積極的に考慮する
  • モニタリング測定、負荷テスト、微調整の繰り返し

TCPキープアライブの仕組み

起動させる キープアライブ ソケットレベルまたはシステムレベルで、スタックが非アクティブの時、定義された間隔で小さなプロー ブを送信する。調整可能な待機時間(アイドル)の後、システムは最初のチェックを送信する。その後、試行回数に達するまで、定義された間隔でさらなるプローブが続く。リモート・ステーションが無言のままであれば、接続を終了し、ファイル・ディスクリプタとバッファを カーネル フリーである。Keepaliveは、そうでなければ休止しているフローのライブネスステータスをチェックするので、ロジックは再送とは明らかに異なる。特に、多くの同時セッションがあるホスティング環境では、この動作は、そうでなければしばしば高い有効性の時にしか気づかないような、忍び寄るリークを防ぐ。 負荷 を感じる。.

ホスティングにおいてKeepaliveが重要な理由

欠陥のあるクライアント、モバイルネットワーク、攻撃的なNATゲートウェイは、しばしば問題を残します。 ゾンビ・コネクション, これは、keepaliveなしで長時間オープンされたままになる。これは、accept、worker、proxyプロセスにおいて、オープンソケット、RAM、CPUを消費し、レスポンスタイムを引き延ばす。このような死骸を早い段階で取り除き、リスナー、バックエンド、アップストリームをオープンにしておくために、適切な値を使います。 レスポンシブ. .この効果は、ピーク負荷時に特に顕著である。なぜなら、キューを埋めるデッドコネクションが少なくなるからである。そのため、私はHTTPやTLSのタイムアウトと一緒にKeepaliveを計画し 和気あいあい すべての層にまたがる交流。.

Sysctlパラメータ:実用的な値

Linuxでは、生産的なデフォルト値として非常に長い値が用意されている。 ホスティング環境 が合うことはほとんどない。ウェブサーバーの場合、通常はアイドル時間をかなり短めに設定して、ハングアップしているセッションをうまくクリアするようにしている。プローブの間隔を適度に保つことで、障害を素早く認識しつつも、チェックでネットワークを溢れさせないようにしている。プローブの数は、誤報と検出時間の間でバランスをとっている。 リソース. .IPv6については、それぞれのnet.ipv6変数に注意を払い、両方のプロトコルの一貫性を保つ。.

パラメータ スタンダード(Linux) ホスティングの推奨事項 ベネフィット
tcp_keepalive_time 7200s 600-1800s アイドル
tcp_keepalive_intvl 75s 10-60s 個々のプローブ間の距離
tcp_keepalive_probes 9 3-6 終了するまでの最大失敗回数

システム全体に基本値を設定し、sysctl経由で永続的に適用することで、再起動してもチューニング作業が破棄されないようにしている。さらに、初期値を文書化し、次のような効果を測定している。 エラー率 とレイテンシーのバランスを保つことができる。これにより、高速検出と追加ネットワーク・トラフィックのバランスを保つことができる。私はよく以下の行を出発点として使い、後でワークロードごとに調整する:

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5
sysctl -p

ソケットおよびプラットフォームごとのチューニング

グローバル・デフォルトで十分なことはほとんどない。 ソケットあたり-値を設定することで、繊細なバックエンドは長く生き、フロントエンドは素早くクリーンアップすることができる。Python、Go、Javaでは、SO_KEEPALIVEと特定のTCPオプションをソケットに直接設定する。Linuxでは、TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNTで制御し、Windowsではレジストリキー(KeepAliveTime、KeepAliveInterval)で制御する。Kubernetesでは、短命のAPIゲートウェイと長命のAPIゲートウェイを異なるように扱うために、ポッドまたはデプロイメントごとに設定を上書きする。 データベース-プロキシ。コンテナのセットアップでは、ホストのNATテーブルとCNIプラグインもチェックする。.

# の例 (Python, Linux)
インポートソケット
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)

HTTP Keep-Alive 対 TCP Keepalive

HTTP Keep-Aliveは複数のリクエストに対してコネクションをオープンにしておく。 TCP Keepaliveはトランスポートレベルで純粋な生存チェックを提供する。どちらのメカニズムもお互いを補完しますが、異なるターゲットとタイマーで動作します。HTTP/2とHTTP/3では、PINGフレームが部分的にKeepaliveの役割を引き継ぎますが、私はまだTCPレイヤーを追加的に保護しています。HTTPのタイムアウトはアプリケーションの表示に従って設定し、TCPの値は、HTTP/2およびHTTP/3の経済的なリリースに基づいて設定します。 リソース を揃える。HTTPページについてもっと詳しく知りたい場合は、以下のサイトが参考になる。 HTTPキープアライブタイムアウト.

ネットワーク・タイムアウトのチューニング:実用的

古典的なウェブホスティングのフロントエンドでは、300秒のアイドル、30~45秒のインターバル、4~6回のプローブで、非アクティブなセッションを素早く終了させることが多い。 キュー リーン。データベース接続は、短いビジー・フェーズが不要な切断を引き起こさないように、より忍耐強くされる。エッジやAPIゲートウェイでは、短時間の接続が多いので、タイムアウトも短くする。レイヤーの境界で矛盾が生じないように、TLSハンドシェイクのタイムアウト、リード/ライトのタイムアウト、アップストリームのタイムリミットと値を調和させる。段階的な最適化のために、コンパクトな チューニングフロー, これはメンテナンス・ウィンドウで使っている。.

ファイアウォール、NAT、クラウドのアイドルタイムアウト

多くのファイアウォールやNATゲートウェイは、300~900秒後に非アクティブなフローをカットする。 キープアライブ この間隔より短くなるようにする。そうしないと、アプリケーションは次のリクエストまで終了を認識できず、不必要な再試行を引き起こしてしまう。クラウドロードバランサーでは、TCPやコネクションのアイドルパラメータをチェックし、sysctlやプロキシの値と比較する。エニーキャストやマルチAZのセットアップでは、パスの変更が一見死んだように見えるリモートステーションにつながるかどうかをチェックし、特にこれらのゾーンのサンプル数を増やします。クライアント、プロキシ、ファイアウォール、バックエンドのチェーンを文書化し、以下のことができるようにします。 原因 を素早く滴下する。.

ウェブサーバー設定への統合

Apache、Nginx、HAProxyは、アプリケーション・レベルでHTTPパーシステンスを組織する。 TCP Keepaliveは実現する。Apache では KeepAlive をオンにし、KeepAliveRequests を制限し、KeepAliveTimeout を短くして、ワーカーが速やかに解放されるようにしています。Nginxではkeepalive_timeoutを短くし、keepalive_requestsを控えめにして効率的に再利用できるようにしています。HAProxy では、tcpka のようなソケットオプションかシステム側のデフォルトを使い、トランスポートのタイムアウトがプロキシのポリシーに合うようにしています。より詳細なウェブサーバの側面については ウェブサーバーチューニングガイド, それをTCPのカスタマイズと組み合わせている。.

モニタリング、テスト、メトリクス

各調整の効果を測定しており、以下のような分析には頼っていない。 直感. ss、netstat、lsofは、ESTABLISHED、FIN_WAIT、TIME_WAITコネクションの数と、リークが増加しているかどうかを示してくれる。メトリックスでは、アボート、RST、再送、レイテンシP95/P99、キュー長を監視している。値が限界に達したら、特にアイドル、インターバル、プローブに行く。合成負荷テスト(ab、wrk、Locustなど)を使って実際の使用パターンをシミュレートし、チューニングが目標のメトリクスに達しているかどうかを検証します。段階的に変更を展開し、変更前の時系列と変更後の時系列を比較する。 グローバル すべてのホストにデフォルトを配布する。.

エラーパターンとトラブルシューティング

インターバルを短く設定しすぎると、膨らんでしまう。 ネットワーク・トラフィック 一時的な障害が障害として解釈される危険性が高まります。プローブの数が少なすぎると、低速のネットワークではライブ接続を閉じてしまう。一方、アイドル時間が長すぎると、ソケットが輻輳し、アクセプト・バックログが増大する。私は、クライアント/サーバーからのRST、ECONNRESET、ETIMEDOUTのログをチェックし、方向性を認識します。主にモバイル・ユーザーに影響がある場合は、プローブと間隔を調整します。 死角 と睡眠状態が頻繁に起こる。.

様々なワークロードのための安全なデフォルト

私は、保守的だが生産に適した値から始め、それを測定した後に改良する。 ワークロード. .ウェブAPIは通常短いアイドル時間を必要とするが、データベースはかなり長い。ゾーンやプロバイダー間のプロキシは、パスのフラッターに対処するため、少し多めのプローブが有効です。インタラクティブなアプリケーションの場合は、間隔を短くし、プローブの数を増やす。この表は、コンパクトな方向性を示してくれる。.

サーバータイプ アイドル インターバル 試料 ヒント
ウェブホスティング・フロントエンド 300-600s 30-45s 4-6 短時間で大量のセッション
APIゲートウェイ 180-300s 20-30s 5-6 アイドリング・フェイズが多く、クリアが早い
データベースプロキシ 900-1800s 45-60s 3-5 コネクションの確立には金がかかる。
Kubernetesポッド 600-900s 30-45s 4–5 CNI/LBタイムアウトとの同期

TCP_USER_TIMEOUTと再送バックオフ

Keepaliveに加えて、私は特にデータ通信接続に以下を使用している。 tcp_user_タイムアウト, を使うことで、接続がアクティブにキャンセルされる前に、未確認のデータがどれだけの時間ソケットに残っているかを制御することができる。これは特にプロキシやAPIにとって重要であり、何分もハンガーをループさせるべきではありません。Keepalive(非アクティブ時に有効性をチェックする)とは対照的に、TCP_USER_TIMEOUTは、データが流れているにもかかわらずACKが返されない場合に有効になる。私が設定したのは ソケットあたり エラー発生時にトランスポートレベルがアプリのロジックより長く待たないように、アプリケーションのリード/ライトタイムアウトより少し下。.

#の例 (Go, Linux) - キープアライブとTCP_USER_TIMEOUT
d := net.Dialer{
    タイムアウト: 5 * time.Second、
    KeepAlive: 30 * time.Second、
    Control: func(ネットワーク、アドレス文字列、c syscall.RawConn) error { var err
        var err エラー
        c.Control(func(fd uintptr) { // 20秒間の未確認データ。
            // 20sの未確認データが許される
            err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 0x12, 20000) // TCP_USER_TIMEOUT
        })
        return err
    },
}
conn, _ := d.Dial("tcp", "example:443")

TCPのバックオフ(RTO拡張)とリトライ(tcp_retries2)もパケットロス時の動作に影響する。短すぎるユーザータイムアウトは、リモートステーションが到達可能であっても、ラフなネットワークではドロップアウトにつながる可能性がある。そのため、私は意図的に高速なエラー検出を目指す場合(エッジプロキシなど)にのみ、タイムアウトを厳しく設定しています。.

IPv6とオペレーティングシステムの機能

同じソケットごとのオプション(TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT)がIPv6にも適用される。カーネルのバージョンによっては、v4とv6のグローバル・デフォルトが一緒に適用される。 ss -o を実際のコネクションに変換する。Windowsでは、レジストリでデフォルトをカスタマイズし(KeepAliveTime、KeepAliveInterval)、個々のソケットにはSIO_KEEPALIVE_VALSを使う。オプションはBSDの派生版では異なる名前で呼ばれることがあるが、セマンティクスは同じままである。各プラットフォームで、アプリケーションのオーバーライドが実際にシステムのデフォルトを上回っているかどうか、コンテナー・ランタイムが名前空間を正しく継承しているかどうかを検証することが重要である。.

ウェブソケット、gRPC、ストリーミング

長寿命のストリーム(WebSocket、gRPC、サーバーが送信するイベント)は、適切にキープアライブを行うことで特に恩恵を受ける。私は2つのレベルから始めます:アプリケーションは定期的にPing/PONGを送信し(例えばWebSocketレベル)、TCPレイヤーは適度な間隔でセキュリティを確保する。これにより、NATが無言でフローを削除するのを防ぐことができる。モバイル・クライアントの場合は、省エネモードを考慮して、プローブの数を増やし、間隔を長くしています。gRPC/HTTP-2については、HTTP/2のPINGをTCP Keepaliveと調整し、あまり積極的に2回プローブしてバッテリーを消耗しないようにしている。.

Conntrack、カーネル、NATテーブル

アクティブなコネクション・トラッキングを持つLinuxホストでは、短すぎる nf_conntrack-タイムアウトは、たとえアプリが長く考えていたとしても、早期のドロップにつながる可能性がある。そのため、関連するタイマー(例えば. nf_conntrack_tcp_timeout_established)とキープアライブ間隔を設定することで、conntrackの締め切り前にサンプルが安全に到着するようにしている。強力なNAT(NodePort, egress NAT)を持つノードでは、conntrackテーブルとハッシュバケットのサイズを計画し、負荷によるグローバルな圧迫を避けるようにしている。クリーンなキープアライブ設定は、これらのテーブルを大幅に緩和します。.

例:プロキシとウェブ・サーバー・ユニット

HAProxyでは、特にトランスポート側のキープアライブを有効にして、HTTPタイムアウトを一定に保っている:

# 抽出 (HAProxy)
デフォルト
  タイムアウトクライアント 60s
  タイムアウトサーバ 60s
  タイムアウト接続 5秒
  オプション http-keep-alive
  オプション tcpka # TCPキープアライブを有効にする(OSのデフォルトを使用)。

バックエンドアプリ
  サーバ s1 10.0.0.10:8080 check inter 2s fall 3 rise 2

Nginxでは、ワーカーを縛ることなく再利用するのが効率的だと思います:

# 抜粋 (Nginx)
keepalive_timeout 30s;
keepalive_requests 1000;
proxy_read_timeout 60s;
proxy_send_timeout 60s;;

私は、トランスポートとアプリケーションのタイムアウトが論理的に適合していることを確認しています:デッドライン」の防止はTCP/Keepaliveの仕事であり、アプリケーションのタイムアウトはビジネスロジックとユーザーの期待に対応する。.

実際の観測可能性

私はホスト上でKeepaliveの動作をライブで確認する:

  • ss: ss -tin 'sport = :443' が出演している。 -o タイマー. timer:(keepalive,30sec,0))、リトライ回数、送信/再送信Q。.
  • tcpdump私は休止状態の接続をフィルタリングし、アイドル時に定期的に小さなパケット/ACKを確認している。これにより、プローブが時間内にNATをトリガーするかどうかを認識することができる。.
  • ログ/メトリクス私は、RST/タイムアウトのピークと、アイドル/インターバル/プローブの変化を関連付ける。一定の負荷でオープンソケットが減少すれば、整理が成功したことを示す。.

再現性のあるテストのために、接続障害(例:インターフェイスのダウン、iptablesのDROP)をシミュレートし、ワーカーやプロセスがどれだけ早くリソースを解放するか、リトライが適切に機能するかを観察する。.

リソースとキャパシティ・プランニング

キープアライブは均衡の一部に過ぎない。私は、ulimit/nofile、, fs.file-max, net.core.somaxconn そして tcp_max_syn_backlog は私の接続番号と一致する。長すぎるアイドル時間には赤字が隠されており、短すぎる値は安定性をもたらすが、ユーザーに大きな打撃を与える。私は、負荷シナリオに基づいてバッファ(Recv-/Send-Q)とFDリザーブを計画し、GC/Workerとacceptキューが苦しむ前に、私のノードが本当にサポートできる同時アイドル接続数を測定します。.

TCPキープアライブに頼らない(だけ)場合

NATのない純粋な内部トラフィックで、接続数が少なく、アプリケーションのタイムアウトが明確な場合は、積極的なキープアライブを省き、アプリケーションに検出を任せることもある(プロトコル・レベルでのハートビートなど)。逆に、エッジやモバイルのシナリオでは、短いインターバル、少ないプローブを優先し、HTTP/2のPINGやWebSocketのPINGを追加する。重要なのは、決して単独でチューニングしないことだ:キープアライブ値は、リトライ、サーキットブレーカー、バックオフ戦略と調和していなければならない。.

ロールアウト戦略と検証

私は段階的に新しいデフォルトを導入している:まずカナリアホストを、次にAZ/ゾーンを、そしてフリート全体を。ビフォー/アフターの比較には、オープンコネクション、カーネルモードのCPU、P95/P99レイテンシー、エラーレート、再送信が含まれる。Kubernetesでは、ノード全体を変更する前に、sysctlネームスペースを設定するポッドアノテーションやinitコンテナを使ってテストする。こうすることで、リスクを最小限に抑え、再現可能な結果を保証します。.

簡単にまとめると

考え抜かれた TCP Keepaliveの設定により、非アクティブなコネクションを早期に削除し、リソースへの負担を軽減し、レスポンスタイムを安定させます。フロントエンドのアイドル時間は短く、ステートフルなバックエンドには長い値を選び、適度なインターバルと数回から中程度のプローブで安全を確保する。この値をHTTP、TLS、プロキシのタイムアウトと調和させ、ファイアウォールやNATのアイドル制限以下に保つ。各調整の後、直感に頼るのではなく、レイテンシー、エラー、CPUへの顕著な影響を測定する。こうして達成したのが 信頼できる ピーク負荷にうまく対応し、ユーザーフローを均等に提供できるプラットフォーム。.

現在の記事