プログラマーが信じがちな誤ったTCPの知識
(lwn.net)- NetworkManagerが一時的な接続不安定を「ネットワークなし」と判断するように、一部のソフトウェアは TCPの回復 よりも自己状態の判定を信頼するが、実際のネットワークでは危険になりうる
- 「送ったデータは届く」「双方は最終的に配送されたバイト列について合意する」「HTTPやSMTPのような アプリケーションプロトコル で保証できる」という考えは、状況によっては成り立たない
- ACK処理中に接続が切れると、送信側はそのセグメントが受信されたかを知ることができず、この限界は Two Generals’ Problem のように単一の2者TCPストリームだけでは解決できない
- SMTPもRFC 1047とRFC 2821でこの問題を扱っており、配送責任が移る瞬間には、接続失敗時に 重複送信 や欠落が起こりうる曖昧な区間がある
- 奇妙なネットワークを例外扱いしたり、Nagleアルゴリズム、輻輳制御、ICMP遮断のような細かな挙動を無視したりすると、実際の障害を誤って解釈しやすい
TCPより先にネットワーク状態を断定してしまう問題
- NetworkManagerを使っていたユーザーは、過去に寮やキャンパスのローミング環境で 無線接続の不安定さ を経験し、パケット損失が少しあるだけでシステム全体に「ネットワークなし」が通知される状況を体験した
- 当時のネットワークはすぐに回復する可能性があり、一般的な TCPの回復 は遅延時間の急増を伴っても、アプリケーションには透過的に見えることがあった
- この事例は、TCPが処理できる一時的な障害をアプリケーションやシステムコンポーネントが早々に失敗と解釈してしまう問題につながる
TCPについてよくある誤解
- 次の文はTCPを扱う際によく見られる考えだが、それぞれ少なくともある場合には 誤り である
- TCPは信頼できるので、送ったすべてのデータが相手に届く
- TCPはだいたい信頼できる
- TCPが完全な意味での信頼性を提供しなくても、送信者と受信者は最終的にどのバイトが送られたかを正確に合意する
- HTTPやSMTPのようなメッセージ指向の アプリケーションプロトコル をTCP上に作れば、そのような保証を作れる
- TCPパケットというものがある
- TCPパケットというものはない
- よく知られたリモートホストに接続できなければオフラインである
- Nagleアルゴリズムは良い
- Nagleアルゴリズムは悪い
- Nagleアルゴリズムを気にする必要はない
- TCPはネットワークを通る双方向Unix pipeのようなものだと考えれば十分である
- ネットワークがTCPに透過的ならIPにも透過的である
- ネットワークがHTTP/1.1に透過的ならTCPにも透過的である
- 標準プロトコルに透過的でない奇妙なネットワークは例外的なので無視してよい
- TCPはIPの上に実装される
配送されたバイト列について正確に合意しにくい理由
- TCPの信頼性に関する前述の1〜4番の問題は、Two Generals’ Problem と結びついている
- ACKがまだ処理中の状態で接続が切れると、送信側にはそのセグメントが受信されたかを確認する方法がない
- この限界は、TCPの上に複雑な層を積み重ねても消えない
- 単一の2者TCPストリームの上ではこの保証を作れず、そのような保証には Paxos や Raft に似た方式と最低3ノードが必要になる
- 同種の問題はTCPだけでなく、UDPやIPベースの2者サービスにも当てはまる
SMTPが明らかにする配送責任のグレーゾーン
- SMTPは、双方がメッセージ受信の成否を明示的に気にしなければならないサービスであり、この問題がよく表れる
- RFC 1047はSMTPの観点からこの問題を扱い、RFC 2821は実装がRFC 1047の中核的な助言に従うべきだと定めている
- SMTPの例では、次の状態が区別される
- クライアントからサーバーへ電子メールが送信されたと双方が合意する地点に到達できる
- サーバーが電子メール配送の責任を負ったと双方が合意する地点にも到達できる
- しかしその前に、誰が現在電子メール配送の責任を負っているのかが曖昧な状態を必ず通過しなければならない
- この曖昧な状態で接続が切れると、電子メールが 重複 したり 欠落 したりする
- SMTP仕様は電子メールを重複させる側を定めているが、実際の実装でどの程度テストされているかは分からない
- PaxosやRaftの目的は、最終状態そのものを達成すること以上に、このような曖昧な状態を防ぐことにある
2者合意において残る知識の限界
- あるコメントでは、信頼できないが悪意はないリンクでも、2当事者があるバイト集合について「配送され、かつ双方がその事実を知っている」と合意できると見ている
- 補足の議論では、一方の当事者は合意集合に少なくとも先頭Nバイトが含まれることは分かるが、合意集合が正確に先頭Nバイトであるとは分からないと整理されている
- したがって、「確実に配送され、双方が知っている」バイト集合は存在しうるとしても、その先には送信者と受信者が互いの知識状態を確定できない グレーゾーン が残る
- この違いを見落とすと、分散システムで奇妙な障害が起こりやすい
現実のネットワークと下位層の落とし穴
- 「標準プロトコルに透過的でない奇妙なネットワークは無視してよい」という考えは、何度も問題を引き起こしてきた
- buffer bloat は、ルーターが輻輳制御メカニズムを壊してしまう事例として扱われる
- ICMPを遮断したり、理解できないトラフィックを破棄したりするネットワークも問題になりうる
- 「輻輳制御を知る必要はない」という考えも、TCPを誤解した例に近い
- 下位の例として、「欲しい速度が出ないならTCP接続を複数開けばよい」という発想がある
まだコメントはありません。