メインコンテンツへスキップ
検索

netstat がソケットを表示すると、スタックしているように見えることがあります。リモートアプリケーションが終了している場合や、OpenVOSアプリケーションも終了している場合もありますが、netstatはソケットを表示しています。この記事では、なぜこのようなことが起こるのか、そしてその対処法を説明します。

TCP の状態の簡単な紹介

tcp state diagram"でググると、たくさんの画像が出てきますが、かろうじて読めるものもあれば、かなり読めるものもあります。ウィキメディアには、非常に素晴らしい色分けされた画像があります (http://commons.wikimedia.org/wiki/File:TCP_state_diagram.png)。TCP RFC (793) (http://www.rfc-editor.org/rfc/rfc793.txt) には、ASCII のアート図があり、もちろん状態を詳細に説明しています。

ローカルアプリケーションかリモートホストのどちらかが何かをするのを待っているときにソケットが動かなくなることがあります。この状態には3つの状態があります。FIN_WAIT_2 の状態では、ソケットはリモートホストが接続を閉じるのを待っている。CLOSE_WAIT状態では、ローカルアプリケーションがソケットを閉じるのを待ち、ESTABLISHED状態では、リモートホストが送信ウィンドウを開くか、ローカルアプリケーションが何かを送信するのを待ちます。ローカル TCP スタックがデータを送信した後、リモートホストがスタックを取得できないことを確認するのを待っている場合、最終的にタイムアウトし、ローカルアプリケーションにエラーを通知してソケットを閉じます。

FIN_WAIT_2 状態

これはおそらく、CACに呼び出される最も一般的なスタックソケットのケースです。ローカルアプリケーションがソケットを閉じてしまい、終了した可能性があります。この状態でソケットがスタックする典型的な理由は、リモートアプリケーションがハングアップしていてソケットを読み込んでいないことです。

STCP パラメータ finwait2 を N > 0 に設定すると、FIN_WAIT_2 に N 秒間置かれた後にソケットが閉じられます。リリース 14.7.2bg、14.7.tl1、15.2.1aa、15.2.tel.af、15.3.0bd、15.3.tel.ag、16.2.1al、17.0.0ai、17.1 以降では、デフォルト値は 1200 で、それ以前のデフォルト値は 0 です (ソケットをタイムアウトさせたい場合は、自分で設定する必要があります)。現在の値は list_stcp_params analyze_system リクエストで確認できます。これらのリクエストに関するドキュメントは、http://stratadoc.stratus.com にある OpenVOS System Analysis (R073) マニュアルを参照してください。

CLOSE_WAIT状態

これは、次によくあるスタックしたソケットの状態です。CLOSE_WAIT 状態にあるソケットは、ローカルアプリケーションがソケットを閉じるのを待っている。ソケットがこの状態のままになる典型的な理由は、アプリケーションがソケットを読まなくなったためです。ソケットを閉じる最も簡単な方法は、ローカルアプリケーションを終了させることです。

ローカルアプリケーションを終了させることができない場合、唯一できることは、RST(リセット)フラグを設定したパケットを作成することです。このためには、ソケットで使用されているシーケンス番号を知っていること(dump_onetcb analyze_system requestで取得可能)、ローカルサブネット上の別のホストでカスタムIPパケットを構築して送信することができるユーティリティを持っていることが必要です。これらのユーティリティは、Windows とLinux システムで利用可能です。

ESTABLISHED 状態

ほとんどの場合、netstat はソケットを ESTABLISHED 状態で表示していますが、ソケットがスタックしている場合はどうやって見分けるのでしょうか?リモートホストがクラッシュしたり、ローカルホストとリモートホスト間のネットワークが10分以上故障していて、ローカルアプリケーションがリモートに何かを送信するのを待っているという報告があった場合、ソケットがスタックしていることは間違いありません。この場合、netstat が報告する送信キューの値 (ローカル IP アドレスのすぐ左にある番号) は 0 になります。 一方、送信キューの値が 0 よりも大きく、その状態が続いている場合、リモートホストがゼロウィンドウを宣伝している場合があります。

最初のケースでは、キープアライブがオンになっていない限り、ローカルアプリケーションが終了するまでソケットはESTABLISHED状態のままである。keep-aliveがオンになっている場合、キープアライブタイマーが切れると、STCPはキープアライブプローブを送信します。プローブが応答しない場合は再送されますが、数分後、数回の再送の後、接続は終了します。デフォルトではインターフェイスにはキープアライブが設定されていますが、ソケットにはデフォルトでは設定されていません。ソケットにキープアライブを設定するには、アプリケーションはsetsockopt関数呼び出しを使用する必要があります。詳細については、OpenVOS STREAMS TCP/IP プログラミング (R420) マニュアル(http://stratadoc.stratus.com)を参照のこと。デフォルトのキープアライブ時間は 2 時間です。つまり、最初のキープアライブプローブはリモートホストから最後の TCP セグメントを受信してから 2 時間後に送信されるので、我慢しなければなりません。それほど忍耐強くない場合は、キープアライブ時間やプローブ間の時間、プローブの数を analyze_system の set_stcp_parameter リクエストで調整することができます。詳細な解析なしにこれらのパラメータを変更することはお勧めしません。

ソケットにキープアライブが設定されていない場合、ソケットを所有しているアプリケーションを終了させるしかありません。それができない場合は、RSTフラグを設定したセグメントをソケットに送信することでソケットを閉じることができます。

2つ目のケースを確認するには、dump_onetcb analyze_systemリクエストで表示されたsndwsの値を確認してください。0の値はウィンドウが閉じられていることを示します。packet_monitor を実行して接続をトレースし、リモートホストからのセグメントの TCP ヘッダのウィンドウの値を確認することもできます。値が"n.a."の場合は0を示します。

これは回復可能な状態である可能性があることを強調しておきたい。アプリケーションが遅れてTCPスタックがウィンドウを閉じ、アプリケーションが追いつくとスタックがウィンドウを開きます。しかし、ほとんどの場合、アプリケーションが数分後に回復していない場合は、回復しないと思っていいと思います。例外は、プリンタの紙切れのようなものかもしれません。この状態のソケットは、それを作成したVOSアプリケーションが終了しても、この状態を維持することができます。

これらのソケットは、tcp_zerowin_abort_interval$ を N > 0 に設定することでクリーンアップされます。ソケットは、ゼロウィンドウの次の TCP セグメントを受信してから N 秒後にクリーンアップされます。ウィンドウプローブは、リモートホストの受信ウィンドウが閉じたままであることを確認するために100秒ごとに送信されますので、最悪の場合、100秒以内に返信が来ることになります。tcp_zerowin_abort_interval$のデフォルト値は0で、ソケットをクリーンアップする必要がない限り0のままにしておくことをお勧めします。その際には、10秒などの小さな値に設定し、ソケットのクリーンアップが完了したら0にリセットすることをお勧めします。 これにより、復旧可能なソケットをクリアするリスクを減らすことができると思います。

この値を設定するには、 analyze_system の set_longword リクエストを使用する必要があります。例えば、10に設定するには以下のようになります。
set_longword tcp_zerowin_abort_interval$ a

メニューを閉じる

© 2024 Stratus Technologies.