HTTPキープアライブについて聞いたことがありますが、今のところ、リモートサーバーとのソケット接続を開きたいと思います。
これで、このソケット接続は永久に開いたままになりますか、それともHTTPキープアライブと同様にそれに関連するタイムアウト制限がありますか?
HTTPキープアライブについて聞いたことがありますが、今のところ、リモートサーバーとのソケット接続を開きたいと思います。
これで、このソケット接続は永久に開いたままになりますか、それともHTTPキープアライブと同様にそれに関連するタイムアウト制限がありますか?
回答:
TCPソケットは、閉じられるまで開いたままになります。
とはいえ、実際にデータを送信せずに接続の切断(ルーターの停止などの切断など)を検出することは非常に難しいため、ほとんどのアプリケーションは、確認のために、ある種のピンポン反応を頻繁に実行します。接続はまだ実際に生きています。
これで、このソケット接続は永久に開いたままになりますか、それともHTTPキープアライブと同様にそれに関連するタイムアウト制限がありますか?
短い答えはノー、それは永遠に開いたままにしません、それは数時間後にタイムアウトおそらくなります。したがって、はい、タイムアウトがあり、TCPキープアライブを介して強制されます。
マシンでキープアライブタイムアウトを構成する場合は、以下の「TCPタイムアウトの変更」セクションを参照してください。それ以外の場合は、残りの回答を読んで、TCPキープアライブがどのように機能するかを確認してください。
TCP接続は、接続の両端に1つずつ、合計2つのソケットで構成されます。一方が接続を終了したい場合RST
、もう一方が確認応答するパケットを送信し、両方がソケットを閉じます。
ただし、それが発生するまで、両側はソケットを無期限に開いたままにします。これにより、一方の側が意図的にまたは何らかのエラーのために、を介してもう一方の端に通知せずにソケットを閉じる可能性が残りRST
ます。このシナリオを検出し、古い接続を閉じるために、TCPキープアライブプロセスが使用されます。
Keep-Alivesの動作を決定する3つの構成可能なプロパティがあります。Linuxでは1です:
tcp_keepalive_time
tcp_keepalive_probes
tcp_keepalive_intvl
プロセスは次のように機能します。
tcp_keepalive_time
数秒間無音の場合は、空のACK
パケットを1つ送信します。1ACK
は独自の対応するもので応答しましたか?
tcp_keepalive_intvl
数秒待ってから、別のメッセージを送信しますACK
ACK
送信されたプローブの数がになるまで繰り返しtcp_keepalive_probes
ます。RST
て接続を終了します。このプロセスはほとんどのオペレーティングシステムでデフォルトで有効になっているため、もう一方の端が2時間11分(7200秒+ 75 * 9秒)応答しなくなると、デッドTCP接続は定期的にプルーニングされます。
デフォルトでは、接続が2時間アイドル状態になるまでプロセスが開始されないため、古いTCP接続は、プルーニングされる前に非常に長い時間残る可能性があります。これは、データベース接続などの高価な接続にとって特に有害な場合があります。
RFC 1122 4.2.3.6によると、TCPキープアライブパケットへの応答および/またはリレーはオプションです。
実装者は、TCP実装に「キープアライブ」を含めることができますが、この方法は広く受け入れられているわけではありません。キープアライブが含まれている場合、アプリケーションはTCP接続ごとにキープアライブをオンまたはオフにできる必要があり、デフォルトでオフになっている必要があります。
..。
データを含まないACKセグメントは、TCPによって確実に送信されないことを覚えておくことが非常に重要です。
キープアライブパケットにはデータが含まれておらず、厳密には必要ではなく、使いすぎるとインターウェブのチューブが詰まるリスクがあるためです。
ただし、実際には、帯域幅が安くなるにつれて、この懸念は時間の経過とともに減少してきました。したがって、キープアライブパケットは通常ドロップされません。たとえば、Amazon EC2のドキュメントでは、キープアライブを間接的に推奨しているため、AWSでホストしている場合は、キープアライブに頼っても安全ですが、マイレージは異なる場合があります。
残念ながら、TCP接続はOSレベルで管理されるため、Javaはのようなソケットごとのレベルでのタイムアウトの構成をサポートしていませんjava.net.Socket
。Java Native Interface(JNI)を使用してネイティブコードを呼び出してこれらのオプションを構成するJavaソケットを作成する試み3をいくつか見つけましたが、コミュニティで広く採用またはサポートされているようには見えません。
代わりに、構成をオペレーティングシステム全体に適用することを余儀なくされる場合があります。この構成は、システム全体で実行されているすべてのTCP接続に影響することに注意してください。
現在構成されているTCPキープアライブ設定は次の場所にあります。
/proc/sys/net/ipv4/tcp_keepalive_time
/proc/sys/net/ipv4/tcp_keepalive_probes
/proc/sys/net/ipv4/tcp_keepalive_intvl
これらのいずれかを次のように更新できます。
# Send first Keep-Alive packet when a TCP socket has been idle for 3 minutes
$ echo 180 > /proc/sys/net/ipv4/tcp_keepalive_time
# Send three Keep-Alive probes...
$ echo 3 > /proc/sys/net/ipv4/tcp_keepalive_probes
# ... spaced 10 seconds apart.
$ echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl
このような変更は、再起動しても持続しません。永続的な変更を行うには、次を使用しますsysctl
。
sysctl -w net.ipv4.tcp_keepalive_time=180 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=10
現在構成されている設定は、次のコマンドで表示できますsysctl
。
$ sysctl net.inet.tcp | grep -E "keepidle|keepintvl|keepcnt"
net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepcnt: 8
注目すべきことに、Mac OS Xはkeepidle
、keepintvl
秒を使用するLinuxとは対照的に、ミリ秒単位で定義します。
sysctl
再起動後もこれらの設定を保持するプロパティを設定できます。
sysctl -w net.inet.tcp.keepidle=180000 net.inet.tcp.keepcnt=3 net.inet.tcp.keepintvl=10000
または、それらをに追加することもできます/etc/sysctl.conf
(ファイルが存在しない場合はファイルを作成します)。
$ cat /etc/sysctl.conf
net.inet.tcp.keepidle=180000
net.inet.tcp.keepintvl=10000
net.inet.tcp.keepcnt=3
確認するWindowsマシンがありませんが、レジストリのそれぞれのTCPキープアライブ設定を見つける必要があります。
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
脚注
1.詳細についてはman tcp
を参照してください。
2.このパケットは、「キープアライブ」パケットと呼ばれることがよくありますが、TCP仕様では、単なる通常のACK
パケットです。Wiresharkのようなアプリケーションは、ソケット上の先行する通信を参照して、それに含まれるシーケンスと確認応答番号をメタ分析することにより、「キープアライブ」パケットとしてラベルを付けることができます。
3.基本的なGoogle検索から見つけたいくつかの例は、lucwilliams / JavaLinuxNetとflonatel / libdontdieです。
$ no -a | grep tcp_keep
コマンドを使用して現在のTCPキープアライブ設定を照会できます。
SO_KEEPALIVEソケットオプションを探しています。
JavaのソケットAPIを経由してアプリケーションに「キープアライブ」を公開しsetKeepAlive
及びgetKeepAlive
方法。
編集:SO_KEEPALIVEは、「実際の」データを送信せずにOSネットワークプロトコルスタックに実装されます。キープアライブ間隔はオペレーティングシステムに依存し、カーネルパラメータを介して調整できる場合があります。
データが送信されないため、SO_KEEPALIVEはネットワーク接続の活性のみをテストでき、ソケットが接続されているサービスの活性はテストできません。後者をテストするには、サーバーにメッセージを送信して応答を取得することを含む何かを実装する必要があります。
TCPキープアライブとHTTPキープアライブは非常に異なる概念です。TCPでは、キープアライブは、古い接続を検出するために送信される管理パケットです。HTTPでは、キープアライブは持続的接続状態を意味します。
これはTCP仕様によるものです。
キープアライブパケットは、ある間隔内に接続のデータまたは確認応答パケットが受信されなかった場合にのみ送信する必要があります。この間隔は構成可能である必要があり、デフォルトで2時間以上である必要があります。
ご覧のとおり、ほとんどのアプリケーションでは、デフォルトのTCPキープアライブ間隔が長すぎます。アプリケーションプロトコルにキープアライブを追加する必要がある場合があります。
HTTP/1.0
各要求/応答で、サーバーへの再接続が必要でした。以下のためにHTTP/1.1
、彼らは導入Keep-Alive
それは複数のファイルを要求すると「パイプライン」を可能に容易にするための応答を処理して行われた後、接続を殺さないためにサーバーを起動するために使用できるヘッダを、複数のリクエストを送信し、すべてのデータが返されるのを待ちます。
マスカレードNATの背後にいる場合(最近のほとんどのホームユーザーがそうであるように)、外部ポートのプールは限られており、これらはTCP接続間で共有する必要があります。したがって、マスカレードNATは、特定の期間データが送信されなかった場合に接続が終了したと見なす傾向があります。
これと他のそのような問題(2つのエンドポイントの間のどこか)は、合理的なアイドル期間の後にデータを送信しようとすると、接続が「機能」しなくなることを意味する可能性があります。ただし、データを送信しようとするまで、これを発見できない場合があります。
キープアライブを使用すると、接続が回線のどこかで中断される可能性が低くなり、接続の切断をより早く見つけることができます。
これは、キープアライブに関する補足資料であり、それをより詳細に説明しています。
http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO
Javaでは実際のキープアライブ時間を制御できないため、Linuxカーネル(またはprocベースのOS)を使用している場合は、例を使用してキープアライブ時間を変更できます。
JAVAソケット– TCP接続はOSレベルで管理され、java.net.Socketは、ソケットごとのレベルでキープアライブパケットのタイムアウトを設定する組み込み関数を提供しません。ただし、Javaソケットのキープアライブオプションを有効にすることはできますが、古いtcp接続の処理には、デフォルトで2時間11分(7200秒)かかります。この原因の接続は、パージする前に非常に長い間利用できます。そこで、ネイティブコード(c ++)を呼び出してこれらのオプションを構成するJava Native Interface(JNI)を使用するソリューションを見つけました。
**** Windows OS ****
Windowsオペレーティングシステムでは、keepalive_timeとkeepalive_intvlは構成できますが、tcp_keepalive_probesは変更できません。デフォルトでは、TCPソケットが初期化されると、キープアライブタイムアウトが2時間、キープアライブ間隔が1秒に設定されます。キープアライブタイムアウトのデフォルトのシステム全体の値は、ミリ秒単位の値をとるKeepAliveTimeレジストリ設定を介して制御できます。
Windows Vista以降では、キープアライブプローブ(データの再送信)の数は10に設定されており、変更できません。
Windows Server 2003、Windows XP、およびWindows 2000では、キープアライブプローブの数のデフォルト設定は5です。キープアライブプローブの数は制御可能です。Windowsの場合、WinsockIOCTLライブラリを使用してtcp-keepaliveパラメータを構成します。
int WSAIoctl(SocketFD、//ソケットを識別する記述子SIO_KEEPALIVE_VALS、// dwIoControlCode(LPVOID)lpvInBuffer、// tcp_keepalive構造体へのポインター(DWORD)cbInBuffer、//入力バッファーの長さNULL、//出力バッファー0、//のサイズ出力バッファ(LPDWORD)lpcbBytesReturned、//返されたバイト数NULL、// OVERLAPPED構造体NULL //完了ルーチン);
Linux OS
Linuxには、キープアライブのサポートが組み込まれています。キープアライブを使用するには、TCP / IPネットワークを有効にする必要があります。プログラムは、setsockoptインターフェイスを使用してソケットのキープアライブ制御を要求する必要があります。
int setsockopt(int socket、int level、int optname、const void * optval、socklen_t optlen)
各クライアントソケットは、java.net.Socketを使用して作成されます。各ソケットのファイル記述子IDは、Javaリフレクションを使用して取得します。
MicrosoftのドキュメントによるとWindowsの場合