Linux の Socket について調べている。SO_REUSEADDR
について詳しい解説があって面白かったのでまとめ。
※これは、自分用メモなので、内容がとても雑です。
linux - How do SO_REUSEADDR and SO_REUSEPORT differ? - Stack Overflow
ポイント解説
the BSD socket implementation is the mother of all socket implementations
BSD の Socket 実装が全ての Socket 実装の母。この辺は、 Socket 通信の歴史を調べていた時にも見かけた情報。
Wikipedia にも詳しく載っていた。仕様としては Posix なのだけど、そもそもが BSD から来ているので、その実装の影響を受けていることを忘れるなと書いてあった。
–
There are a couple of basics you should know before we look at these two options. A TCP/UDP connection is identified by a tuple of five values:
{
, , , , }
コネクションは、上の5つの値で識別される。それぞれの値が設定されるタイミングは以下の通り。
値 | System Call |
---|---|
protocol | socket() |
src addr | bind() |
src port | bind() |
dest addr | connect() |
dest port | connect() |
SO_REUSEADDR
通常、echo サーバーなんかを自作すると、クライアント・サーバーのどちらから close された Socket は TIME-WAIT
に状態になり MSL (Max Segment Length) の時間待機します。
こうなってしまうと、再度同じ Host, Port で Socket を作成しようとすると、エラーになってしまいます。そこで、Socket の設定で SO_REUSEADDR
をセットしておけば、TIME-WAIT
状態の Socket が残っていても、再度 Socket が作成できるようになります。
SO_REUSEPORT
実装された時期は、Linux だと Kernel 3.9 以降のようです。上記の SO_REUSEADDR
と用途としては同じように使えるのですが、 UDP などでは再利用以外の効果を期待できるようですが、あまり理解できなかった…
とても参考になったサイト&メモ
SO_LINGER は TIME-WAIT の時間を設定するものじゃないよ。という話。 基本的に SO_LINGER は RST を 送りつけて Socket を強制破棄させる時に使うものなので、TCPのコンテキストを考えると使うべきじゃない。
Socket オプションの解説マニュアル。
net.ipv4.tcp_tw_recycle は廃止されました ― その危険性を理解する - Qiita
ISUCON とかで設定したことあったかなと思ったけど、もう廃止されていたし、使うべきでない(上記 RSTと同じ理屈。TCP のコンテキストに合ってない)
LinuxサーバーのTCPネットワークのパフォーマンスを決定するカーネルパラメータ – 1編 | NHN Cloud Meetup
めちゃくちゃ分かりやすくて泣いた。接続数が多すぎる場合は net.ipv4.tcp_tw_reuse
一択だ。
hard close:TCP コネクションを RST で切断する実装 - 【技術系】
RST で切断する実装をよく見かけるが、それはどうなんだね?という内容。同意。
TIME_WAIT 関連を日本語で調べるとよく出てきた。LB用途なら recycle は駄目だということも言及されており、良さそう。
まとめ
自作 echo サーバー作る時は、 SO_REUSEADDR
を設定して、なんども素早く Try & Error 出来るようにするといい。
ちなみに、TIME_WAIT は 2xMSLと書いてあったが、Linuxの場合は定数 TCP_TIMEWAIT_LEN
の値で決まっていて、Ubuntu 20.04 LTS だと 60 sec だった。これは定数なので、実行時に変更することは出来ないし、するべきでもない。
https://elixir.bootlin.com/linux/v4.5/source/include/net/tcp.h#L117
Hz ってどういう単位なんだろ…