最近、実稼働環境で問題を追跡するのにかなりの時間を費やしました。データベースサーバーが消失するとpoll()
、接続されたクライアントが最大2時間ハングします(libpqクライアントライブラリでの呼び出しの待機)。問題を掘り下げると、切断されたTCP接続がタイムリーに通知されるように、これらのカーネルパラメーターを調整する必要があることに気付きました。
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
上記の4つの値はUbuntu 12.04マシンのものであり、これらのデフォルトは現在のLinuxカーネルのデフォルトから変更されていないようです。
これらの設定は、既存の接続を開いたままにしておくことに大きく偏っており、キープアライブプローブでは非常にけちです。AIUI、デフォルトtcp_keepalive_time
の2時間は、リモートホストへの応答を待っているときに、キープアライブプローブを開始して接続がまだ有効であることを確認するまで2時間辛抱強く待つことを意味します。そして、リモートホストがキープアライブプローブに応答しない場合、それらのキープアライブプローブを9回(tcp_keepalive_probes
)、75秒間隔(tcp_keepalive_intvl
)で再試行するため、接続が実際に停止していると判断するまでにさらに11分かかります。
これは、フィールドで見たものと一致します。たとえば、psql
リモートPostgreSQLインスタンスに接続されたセッションを開始し、いくつかのクエリが応答を待っている場合、たとえば
SELECT pg_sleep(30);
そして、リモートサーバーが恐ろしい死を迎える(たとえば、そのマシンへのトラフィックを落とす)ので、接続が停止していると判断するまで、最大2時間11分間psqlセッションが待機しています。ご想像のとおり、これらのデフォルト設定は、たとえばデータベースフェイルオーバーイベント中にデータベースと通信するコードに深刻な問題を引き起こします。これらのノブを下げることは大いに役立ちました!そして、これらのデフォルトの調整を推奨するのは私だけではありません。
だから私の質問は:
- デフォルトはどのくらいの期間でしたか?
- これらのTCP設定をデフォルトにする最初の理由は何ですか?
- Linuxディストリビューションはこれらのデフォルト値を変更しますか?
そして、これらの設定の理論的根拠に関するその他の歴史や展望をいただければ幸いです。
TCP_KEEPIDLE
、クライアントコードの接続ごとに最初の3つを変更できることに注意してください。TCP_KEEPCNT
TCP_KEEPINTVL
TCP_USER_TIMEOUT
、net.ipv4.tcp_retries2
システム全体に設定する代わりに、ソケットオプションを指定することもできるはずです。もちろん、多くのアプリケーション(私の例のPostgreSQLなど)はまだサポートしてTCP_USER_TIMEOUT
いません。