
TCPのサーバ側プログラムを改修する機会があった。
時々ではあるが、アプリケーション起動時に、サーバ側プログラムで
2分ほどの待ちが発生するとのこと。
TCPの知識はほとんどなかったため、この機会に勉強をした。
以下のサイトが分かりやすかった。
http://www.ne.jp/asahi/hishidama/home/tech/socket/tcp.html
このサイトは、以前JavaやScalaの学習をした際にもお世話になっている。
サイトの作者は相当熱心な勉強家であることがうかがえる。
技術者として尊敬している。
そちらに下記のように書かれている。
1 2 3 4 5 |
最初にクローズした(アクティブクローズ)側は、 最後に送ったACKが相手に届いたかどうかを確認することが出来ないので、 ネットワーク上に滞留した電文(ゴミ)が消えるまで待つ為の 再送待機(TIME_WAIT)状態になり、 一定時間(2~4分?OSによって異なる)経つとCLOSED状態になる。 |
たしかに今回サーバー側から先に切断しており、サーバー側がアクティブクローズ側になっている。
そしてサーバー側でnetstatコマンドで調べてみると、
利用しているポートがTIME_WAIT状態になっていた。
そしてその対策として、
1 2 3 4 5 6 7 |
また、アクティブクローズ側がSO_LINGERオプションで時間0をセットしている場合、 TIME_WAIT状態にならずにいきなりCLOSED状態になる。 このとき、(ライブラリによっては?)RSTを送信するみたいだ。 これにより相手にソケットがクローズされたことを知らせて 何も送ってこないようにして、待機状態を回避するんだろう。 もっとも、RSTが相手に届く保証も無ければ変な電文が送られてこない保証も無い訳で、 正しい手順では やはりTIME_WAIT状態になるべきだろう。 |
とのこと。
SO_LINGERオプションにより、強制的にclose状態にできるようだ。
だが、筆者も書いている通り、あまりよい方法とは言えないようだ。
以下のサイトなども、SO_LINGERオプションは推奨された方法ではなく、
本来あるべき姿は、クライアント側から切断するようなアーキテクチャにすることとのこと。
https://code.i-harness.com/ja/q/3954e9
ただ、すぐにでも解消したかったので、
今回は、とりあえずSO_LINGERオプションを使ってみることにした。
下記のサイトを参考に実装。
https://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxbd00/setopt.htm
その際に、LINGERを以下のように設定した。
1 2 |
l.l_onoff = 1; l.l_linger = 0; |
SO_LINGERをONにして、タイムアウトを0にした。
その結果、確かにTIME_WAIT状態に遷移しなくなりました!!!!
副作用がないのか心配ですが、とりあえずSO_LINGERオプションをONにして
様子をみたいと思います。
コメントフォーム