輻輳
輻輳制御
ネットワークに対して、ネットワークの帯域を超えたり、ルータのバッファを溢れさせるようなパケット量を送ると、そのパケットが破棄される。これが輻輳といわれる現象の概要。
そして、それがなるべく起こらないように、一度に送るサイズを window size という単位に抑え、帯域に余裕がありそうなら、この window size を増やして一度に送る量を増やす。
もし輻輳が起こったら、 window size を下げる、というような挙動をする。
これを輻輳制御という。
輻輳制御方式
window size をどのくらいの速さで増やし、輻輳が起こったらどのくらいまで減らすのかにはいくつかのアルゴリズムがある。
- Tahoe
- Reno
- New Reno
- Vegas
- BIG
- CUBIG
- CTCP
あたりが有名らしい。
基本は二つ。もしくはそのハイブリッド。
ロスベース
経路の状況などは考えず、単純に
パケットがロスしたら減らす、しなければ増やす。
遅延ベース
輻輳が起こる前には機器遅延が発生する という現象の特徴を活かし、
あらかじめ想定している RTT を下回ったら、輻輳が発生しそうだとして減らす。
そうじゃなければ増やす。
initial congestion window (InitCWN)
いずれにせよ、 window size は小さい値から始まり徐々に増えて行く。
この初期値はもともと 1 セグメントだった。
それが RFC2581 で 4 セグメントになり。 RFC6928 で 10 になった。
こうしてセグメントサイズが増やせるのは、昔に比べて回線環境が向上し、それを使い切るためには小さい値では最適ではなくなってきたという状況が影響していると思われる。
ちなみに InitCWN を 10 に上げようという話は Google が make the web faster の流れで調査した結果をもとにペーパーを書いて提案した模様。
- https://developers.google.com/speed/articles/tcp_initcwnd_paper.pdf
- https://developers.google.com/speed/protocols/tcpm-IW10
slow start
cwnd が小さいと、例えば回線も十分太く、相手のバッファも余っているのに、それが使いこなせない場合があるということ。
そして、それが徐々に大きくなっていく slow start のモデルは、帯域が使い切れる状態になるまで時間がかかるという事。
それでも、例えば大きな画像や動画を送るのであれば、同じ回線で cwnd がすぐに大きな値になり、そこからアルゴリズムで上下させながら最適な値に収束して行くため、そこまで大きなデメリットにはならない。
しかし、 HTTP/1.1(no keepalive) のように、リクエスト毎に細かくコネクションを切るような回線の使い方だと、ようやく cwnd が温まってもすぐに切れるか、そもそも上がりきる前に切れてしまうので、せっかく温まった回線が使えない。
張りっぱなしの意味
keepalive, websocket, http2 etc で、接続をとにかく貼りっぱなしにしたがる理由は、 3 way handshake の RTT による接続オーバーヘッドの現象もあるが、
そもそもせっかく温まった接続を使い回すことで、 window size 的にも効率が良くなるという問題もある。
一度張った接続は、大事に使う事でよりメリットが増えて行く訳だ。
すると、物理コネクション上で論理コネクション(http2 でいう stream) が欲しくなる。
貼りっぱなしたい理由はそういうところにもある。