1 ポイント 投稿者 GN⁺ 2024-06-25 | 1件のコメント | WhatsAppで共有
  • ライブ動画やインターネット上の会話で重要なのは「信頼性のない配送」そのものではなく、古いデータを押しのけて最新データを時間どおりに届けること
  • ルーターが混雑したパケットを捨てずにキューへ長くため込むとbufferbloatが発生し、リアルタイムサービスではバッファリングより悪い遅延が起こりうる
  • UDPの上に直接プロトコルを作ると、再送、輻輳制御、暗号化、RTT推定、パス検証、フロー制御などを再実装する必要があるため、QUICライブラリを使うほうが安全
  • QUICだけでも、遅延ベースの輻輳制御、独立したストリーム分割、優先順位付けを組み合わせることで、データグラムなしに適時性を実現できる
  • QUIC・WebTransport・MoQ標準にはデータグラム対応が入っているが、新しい動画プロトコルをUDPの上に再び積み上げるより、Media over QUICの流れに合わせるほうがよいという結論

目標は「不安定さ」ではなく適時性

  • TCPとUDPの選択は、よく「信頼性のある配送」と「信頼性のない配送」として説明されるが、アプリケーションが求めているのは不安定さそのものではない
  • ライブ動画やインターネット上の会話では、古いデータをすべて受け取ることより、最新データが先に到着することのほうが重要
  • リアルタイム会話で、顔の上にバッファリングのスピナーが表示されたり、5秒前の音声を聞いたりする状況は避けるべき
  • ライブ動画業界とゲーム業界は、このような適時性のためにTCPストリームではなくUDPデータグラムをよく使う

データグラムとネットワークキュー

  • データグラムは送信元アドレスから宛先アドレスへ送られる0と1の封筒であり、一般に1200バイトが安全なサイズとして扱われる
  • データグラムはひそかに失われることがあり、順序が入れ替わって到着することもある
  • 物理層ではデータがアナログ信号に変わって媒体を通り、シリアライズ、デシリアライズ、バッファリング、キューイング、再送、破棄、破損、遅延、並べ替え、重複、損失が起こりうる
  • ネットワークに多すぎるデータが入ってくると、ルーターは任意のビットではなくパケット境界でデータを捨てる

Bufferbloatと輻輳制御

  • ルーターがパケットをすぐに捨てずキューにためると、bufferbloatが発生する
  • bufferbloatはすべてのパケットを数秒単位で遅延させることがあり、リアルタイム配送にとって最悪の状況を作る
  • キューイングを避けるには、パケット到着時刻のフィードバックでルーターのキューイングを推定し、送信者が送信量を減らしてキューを空にする必要がある
  • この領域は輻輳制御に該当し、無制限の速度でパケットを送る方式は惨事につながりうる

UDPの上に直接作ると背負う機能

QUICストリームで適時性を作る

  • QUICで適時性を達成する方法は3つに整理できる
    • バッファ膨張の回避: BBRのような遅延ベースの輻輳制御がキューイングを検知し、送信量を減らす
    • WebRTCのtransport-wide-ccは、よりよい方式の例と見なせる
    • ストリーム分割: 各ストリーム内部のバイトは順序があり信頼性をもって配送され、ストリームは動画フレーム、ゲーム更新、チャットメッセージ、JSON blobのような原子的な単位になりうる
    • ストリームの優先順位付け: ストリームは独立しているため順序と関係なく到着でき、QUICスタックに重要なストリームを先に届けるよう指示できる
    • 優先順位の低いストリームは飢餓状態になることがあり、帯域幅の無駄を避けるには閉じることができる
  • このアプローチがMedia over QUICの核心
  • データグラムのfire-and-forgetな性質は、リアルタイム遅延が必要なときにだけ適しており、それ以外ではQUICストリームを使える

データグラムをめぐる妥協と例外

  • QUICと関連標準にはデータグラム対応も含まれる
  • データグラム対応は、実装が些細で実験を許容できるという理由で含まれることがある
  • OPUSはFEC対応を内蔵しており、MoQが各オーディオ「frame」をデータグラムとして送る機能をサポートする例になる
  • 古いプロトコルであるDNSは例外にできるが、新しい設計ではDNS over HTTPSのような方向に従うほうがよいと見ている
  • 新しい動画プロトコルをUDPの上に再び作るより、Media over QUICに参加せよという結論につながる

1件のコメント

 
GN⁺ 2024-06-25
Hacker News のコメント
  • TCP の問題は HFT や映像のような帯域幅が大きく遅延に敏感な分野でよく話題になるが、低帯域・高遅延ネットワークでも TCP が特に優れているわけではない
    たとえば NB-IoT のように最悪の場合の往復遅延が 10 秒になる環境では、ハンドシェイクと MTU 探索に往復時間が浪費され、もはや役に立たないデータも送信し続けようとし、カバレッジが悪化して遅延が増えると、TCP はそれを輻輳によるパケット損失と見なして帯域幅を絞る
    また、ロードバランサーやミドルボックスが「4 秒間応答がないなら消えたのだろう」と接続を切ることもあり、TCP がデータ構造を考慮せずにパケットを分割するため、全体を受け取るまで解釈できない点も惜しい
    • TCP はすべてのデータが線形ストリームとして順番に到着すると仮定し、n 番目のパケットを受け取れなければ n+1 番目のパケットもアプリケーションに見せない
      場合によっては有用だが、n 番目がまだなくても n+1 番目を活用できるケースは多い
      大きなファイル転送では消失訂正符号で 5% のパケット損失を自動処理したり、fountain code を使って受信者が「全部受け取った」と言うまで送り続けたりすることもできる
      fountain code は深宇宙探査機がデータを送る方式で、木星や火星までの遅延はかなり深刻だ
    • TLS を使うと特にそうで、最近では TLS が事実上デフォルトに近い主要なユースケースになっている
      TCP ハンドシェイクが終わらないと TLS ハンドシェイクを始められないが、QUIC には初期ハンドシェイク内で TLS ネゴシエーションを処理するプロトコルレベルのサポートがある
      ネットワークプロトコルと暗号化をゆるく組み合わせられるほうがよりエレガントに見えるが、今やほぼすべての転送が暗号化される世界では、接続ごとに往復時間を 1 回減らせるという実用上の利点のほうが大きく見える
    • 最近は TCP の下にある Wi-Fi レイヤーも、弱い信号やノイズの多い信号によって生じた損失に対して独自に再送をかなり行っているのではないかと思う
    • NB-IoT が実際に最近使われているのか気になる。一時期ものすごく持ち上げられていた記憶はあるが、その後話題が消えた感じがする
  • 高周波センサーデータのストリーミングには、単に UDP データグラムを使っている
    R&D 側で QUIC を使う新しいシステムを作り、順序が入れ替わって到着する問題の大半を解決したが、アダプターなしで直接サポートしなければならないサードパーティ製センサーが UDP しか扱えないため、今でもすべてに UDP データグラムを使っている
    • 世界中のメディアアートシステムも、ほとんどが UDP 上の OSCを使っている
    • 高周波センサーデータで思い浮かんだが、TCP と比べた省電力の数値はあるのか気になる
    • そのシステムはどの言語で作ったのか気になる。かなり格好いい
    • UDP 上で信頼性を得るなら RoCE を使うこともできた
  • 些細な揚げ足取りに見えるかもしれないが、UDP を unreliable と呼ぶことには問題があると思う
    より一般的でより良い表現は best-effort であり、UDP はデータグラム配送をベストエフォートで試みるが、データグラムが破棄される可能性があるだけだ
    だからといって UDP が本質的に信頼できないという意味ではない
    https://en.wikipedia.org/wiki/Best-effort_delivery
    • best-effort はこの分野の外の人には婉曲で紛らわしい表現で、英語のネイティブ話者にとってもむしろそうかもしれない
      実際には A から B へメッセージを送るために最後まで頑張るという意味ではなく、「努力はした」に近い
      経路上のルーターが輻輳していたり、リンクフラップによって高速な再ルーティングの前に 50ms ほどブラックホールが生じたりしても、「まあ、やってはみた」ということになる
      一方で TCP の信頼的配送は何度も再試行し、アプリケーションに順序のそろったデータストリームを提供する
      reliable/unreliable も悪い用語かもしれないが、best-effort のほうが優れているとは言いにくい
      信頼的でないシステムは 95% くらいは素晴らしく、生のスループットにも良いが、最後の 5% が非常に大きな差を生むことが多い
    • ネットワーキングにおける best effort delivery は unreliable と比べて良いところのない逃げの用語なので、なくしてもいいレベルだ
      「努力」は通常、困難を前にしてある程度の粘り強さを意味するが、リソース問題が起きたからといってパケットを捨てるのは努力とは呼びにくく、best effort ならなおさらだ
      法律・ビジネス用語の “best efforts” は確約よりは弱いが、あからさまに手を引くことではない。しかしネットワーキングでの使い方はそれとはかなり違う
      それとは別に、UDP と TCP のチェックサムも、データグラムが配送されたときの完全性を十分に保証できず、ハードウェアより少し良い程度だ
    • 「データグラムが破棄される可能性がある」というのがまさに unreliable の意味だと思っていたが、どんな誤解を避けようとしているのかよく分からない
    • トランスポート層を unreliable と呼ぶのは良い表現ではない。信頼性は転送方式ではなくシステムの性質であり、TCP でも信頼性のないシステムを作れるし、UDP でも信頼性のあるシステムを作れる
      ただし best-effort は配送保証のために何か努力をしているような印象を与えるが、実際にはおかしそうに見えるパケットや、運悪く満杯のバッファに出会ったパケットをそのまま捨てるだけだ
      lossy が気に入っているが、これは「難しい問題は 2 つだけ」に当たる命名問題だ
    • 80 年代から unreliable transport と呼んできたし、実際それが正しい
      パケットが届かなければならないなら TCP を使い、大して問題でなければ UDP を使えばよい
      単純化した説明ではあるが、best effort は間抜けな用語で、そこに努力はない
  • ストリーム抽象化は、接続が切れたときに復旧が遅い、あるいはまったく復旧できない脆弱なプログラムをあまりに簡単に作れてしまい、トランスポート層にも制約をかけすぎていると思う
    輻輳制御は確かに必要だが、それ以外には疑問が多い
    データグラム優先の世界なら、複数のデータリンクを非常に効率よく束ねたり、ネットワーク境界をまたいで移動しても接続を切らずにローミングしたりすることに問題はなかったはずだ
    多くのアプリケーションは順序が入れ替わったフレームも追加コストなしで処理でき、UDP モデルに合わせて書けばはるかに速くなり得る
    • TCP が便利すぎるせいでソフトウェアがきちんと書かれないという主張でありながら、はるかに複雑なデータグラム優先の世界では完全に堅牢で効率的なソフトウェアが生まれると信じなければならない、というのは説得力に欠ける
      実際、信頼性の低い転送方式に移行したからといって、ソフトウェアが自動的により信頼的または効率的になるわけではない

むしろチームが対処すべき失敗モードと複雑さが大きく増える

  • 適切な誤り訂正符号があるアプリケーションでは、輻輳制御も選択肢の一つになり得る
    ただし接続のどこかに細いボトルネックがあるなら、どうせそのボトルネックで捨てられるパケットを大量に作り出しても、あまり意味はなさそう
  • どんな種類のアプリケーションを想定しているのか気になる。今TCPでよく書かれているシステムのうち、UDPに置き換えられるものは何だろう?
    Webサイト、音声、動画はたいてい順序が入れ替わったフレームとは相性が悪く、多くの場合、音声や動画が途切れることも望まれていない
    一部のビデオゲームは欠落したパケットを無視してもよいが、そういうものはすでにUDPで書かれている
  • あまり言及されない点として、輻輳が発生すると多くのネットワークはUDPパケットを先に捨てる
    そうしたパケットは再送されないはずなので、過剰なトラフィックを減らす効果的な方法だという考えからだ
    今ではUDP上で積極的に再送するプロトコルが出てきているが、それが状況をどう変えたのか気になる
    数年前、QUICがこのためにHTTP/1・HTTP/2と比べて再送の問題を抱えていた記憶もある
  • 記事自体の表現を使ってクリックベイト的なタイトルを変えようとした
    もっと代表的な文言を記事中で見つけられるなら、また変更できる
    HNのタイトル指針である「元のタイトルを使う。ただし誤解を招く場合や釣り気味の場合は例外」に従ったもの: https://news.ycombinator.com/newsguidelines.html
  • この記事の前提には同意しない。UDPは信頼性がないこと自体のためのものではなく、速度と効率を得る代わりに保証ではなくベストエフォート配信を選ぶというトレードオフだ
    アプリケーションによっては妥当である
    例えばリアルタイムのマルチプレイヤーゲームで処理が遅れると、ゲーム状態はすでに変わっているため、遅れた項目はもはや重要ではない
    高速取引アプリケーションでも、状況によっては100ms前の出来事ではなく、最新の市場データだけが重要になる
    • それは記事の前提ではなく、筆者が後で訂正する通念
      記事はUDPが適している例としてゲームやライブ動画も挙げている
    • 読み進めれば、記事も基本的にそう言っている
      最初に「通念」を提示し、その後それに反論する構成だ
  • データグラムベースであるべきものは、ローカル探索、ブロードキャスト、パケットカプセル化だ
    例えばDHCP、SLAAC、UPnP、mDNS、tinc、BitTorrentのようなローカル探索、ローカルネットワークストリーミングのようなブロードキャスト、WireGuard、IPSec、OpenVPN、VLANのようなカプセル化が該当する
    • 抜けているものとしてリアルタイムメディアがある
      再送はもちろん、順序並べ替えのためのバッファリングだけでも遅延が増えるので、誤り訂正やパケットロス隠蔽で損失を受け入れるほうがよい
    • 低レベルのネットワーキング知識があまりない立場として、こうしたユースケースでなぜデータグラムが必要なのか説明してもらえるのか気になる
    • ゲームも該当する
  • タイトルはばかげたクリックベイトで、筆者も冒頭で認めている
    UDPとTCPは動作とトレードオフが異なるので、ユースケースに合わせて選ぶ前に理解すべきだ、というだけの話だ
    「Xは絶対にするな」式の門番気取りは不要だ
    • コメントが投稿されてから10分の間にタイトルの「never」の前にアスタリスクが追加されたのでなければ、そのアスタリスクは明らかに細かい条件があることを示している
      タイトルだけ見ても、UDPを使わせないように門番気取りをする記事ではないことはかなり明らかだ
      実際、記事の最後で筆者はUDPベースのQUICの使用を提案している
  • ほとんどのアプリケーションや事例はセッションベースの接続を使うだろうが、データグラムを直接使う用途もあるので怖がる必要はない
    もちろん、はるかに多くの細部を自分で面倒見る必要がある
    おまけに、ネットワーキングの低レベルな側面を学ぶ良い方法でもある
    • ゲーム開発向けのSteamNetworkingMessages APIは、そのユースケースで内部を気にせずにこの方式をうまく使えるようにしてくれる