【実務・中級編】 WRED(Weighted Random Early Detection)による輻輳制御 – インフラ・物理&L2/L3ネットワーク基礎実践ガイド

ネットワークの「渋滞」を華麗にいなす:WREDが教えてくれるTCPの深淵

ネットワークエンジニアとして現場に立っていると、必ずと言っていいほどぶつかる壁がある。それが「バッファ溢れ(Tail Drop)」だ。

スイッチやルーターのキューがいっぱいになると、そこに来たパケットは問答無用で捨てられる。これが「Tail Drop」だ。一見すると公平だが、これが発生すると、その瞬間に通過していた複数のTCPセッションが一斉にウィンドウサイズを縮小し、その直後に一斉に再送を始める。いわゆる「TCPのグローバル同期現象」だ。ネットワーク全体が「渋滞しては動き出し、また渋滞する」という、あの忌々しい呼吸を繰り返すことになる。

この悪循環を断ち切り、川の流れのようにスムーズな通信を実現するために生まれたのが、今回解説する WRED(Weighted Random Early Detection) だ。

—

WREDとは何か? — 賢い「間引き」の美学

WREDは、キューがいっぱいになる前に、確率的にパケットを間引く技術だ。

「えっ、わざと捨てるの?」と思うかもしれないが、ここが面白い。TCPはパケットをロスすると「あ、混雑しているな」と判断して送信レートを落とす。WREDは、キューが完全に飽和する前に「少しだけ」パケットを捨てることで、特定のTCPセッションだけを先に減速させる。 全員が同時に減速するのではなく、一部を早めに間引くことで、ネットワーク全体が「混雑の一歩手前」で踏みとどまるように調整するのだ。

WREDを理解するための3つのパラメーター

WREDの設定で必ず出てくるのが以下の3つの閾値だ。これらを理解しないと、チューニングは不可能な暗闇と化す。

1. Minimum Threshold(最小閾値): この値まではパケットを絶対に捨てない。
2. Maximum Threshold(最大閾値): この値を超えると、設定された確率でドロップが始まる。
3. Mark Probability Denominator(ドロップ確率の分母): 最大閾値に達したときに、どれくらいの確率で捨てるかの逆数。例えば 10 なら、1/10の確率で捨てる。

これらは、キューの深さ(平均キュー長)を見て動的に変化する。瞬間的なバーストでドロップが起きないよう、指数加重移動平均(EWMA)を用いて「平均的な混雑具合」を監視するのが、WREDの賢いところだ。

—

実践:Cisco IOSでのWRED設定

例えば、社内バックボーンのルーターで、特定のQoSクラスに対してWREDを有効にする設定はこうだ。

! クラスマップを作成し、対象のトラフィックを定義
class-map match-any DATA-TRAFFIC
 match protocol http
 match protocol https

! ポリシーマップでWREDを適用
policy-map QOS-POLICY
 class DATA-TRAFFIC
  ! 平均キュー長が20〜40パケットの範囲でドロップを開始
  ! 最大ドロップ確率は 1/10 (10)
  random-detect exponential-weighting-constant 9
  random-detect min-threshold 20
  random-detect max-threshold 40
  random-detect mark-probability-denominator 10

ここで重要なのは exponential-weighting-constant だ。これは平均キュー長を計算する際の「忘却係数」のようなもの。この値を小さくすると、瞬間的なバーストの影響を強く受けるようになり、大きくすると、より長期的な混雑トレンドを重視するようになる。

—

アプリケーション開発者が知っておくべきこと

Web APIを設計する際、バックエンドエンジニアが意識すべきは「パケットロスが起きたときのTCPの挙動」だ。

もしあなたのAPIが、巨大なJSONレスポンスを一度に返しているなら、それはネットワークのバッファを圧迫する「大物」だ。もしWREDが効いているネットワークを通るなら、途中でパケットが間引かれ、TCPの再送制御が発生する。これによって、クライアント側の Fetch API や curl のレスポンスタイムが「数ミリ秒の遅延」から「数百ミリ秒の遅延」へと跳ね上がる。

Pythonでパケットロスをシミュレートしてみる

もし、あなたのAPIが不安定なネットワーク越しにどう見えるかを確認したいなら、tc (Traffic Control) コマンドと組み合わせて、テスト環境でパケットロスを意図的に起こしてみるのが一番だ。

# eth0インターフェースで 1% のパケットロスを発生させる
sudo tc qdisc add dev eth0 root netem loss 1%

# テスト後に設定を解除する
sudo tc qdisc del dev eth0 root

こうしてロスを発生させた状態で、curl で時間を計測してみると、WREDが効いている環境とそうでない環境での「渋滞の捌け方」の違いが手に取るようにわかるはずだ。

# APIの応答時間をミリ秒単位で確認
curl -w "Time: %{time_total}s\n" -o /dev/null -s https://api.example.com/data

—

現場からのアドバイス:WREDは魔法ではない

最後に、ネットワークスペシャリストとして一つだけ警告しておこう。

WREDは、あくまで「TCPが混雑を検知するのを助ける」ツールに過ぎない。UDPのような、パケットロスを気にしないプロトコルには全く効果がないし、そもそも帯域幅自体が不足している物理的な過負荷状態(オーバーサブスクリプション)を解決する魔法ではない。

真のトラブルシューティングでは、「なぜキューが溜まっているのか?」をまず突き止めること。それは特定のサーバーからの過剰なリクエストか、それとも帯域設計そのもののミスか。WREDはその「渋滞の緩和」には貢献するが、渋滞の原因を取り除くのは、あなたの設計と分析だ。

ネットワークは生き物だ。パケットの一つ一つにストーリーがある。WREDという「交通整理」を味方につけて、しなやかで止まらないサービスを構築してほしい。質問があれば、いつでも現場のコンソール越しに相談してくれ。

コメント

タイトルとURLをコピーしました