【実務・中級編】 WFQ(Weighted Fair Queuing)およびWRR(Weighted Round Robin)キューイング – インフラ・物理&L2/L3ネットワーク基礎実践ガイド

帯域の「公平性」をどう定義するか:WFQとWRRが現場のエンジニアを救う理由

ネットワークインフラの世界で避けて通れないのが、「限られた帯域を誰にどれだけ配分するか」という問題です。特にクラウドネイティブな時代、Web APIのレスポンスが「他のバックグラウンド通信」に圧迫されて遅延する現象は、インフラエンジニアにとって避けて通れない悪夢です。

今日は、教科書の定義をなぞるだけでは決して理解できない、WFQ(Weighted Fair Queuing)とWRR(Weighted Round Robin)の「現場における魂」について、パケットの鼓動を感じながら解説していきましょう。

—

1. FIFOの限界:なぜ「公平」が必要なのか

ご存知の通り、スイッチやルータのデフォルトは FIFO(First-In First-Out)です。しかし、現代の複雑なトラフィックにおいて、FIFOは「強い奴が勝つ」という弱肉強食の世界です。サイズの大きなファイルを転送しているセッションが、小さなAPIリクエストをキューの最後尾に追いやり、レイテンシを跳ね上げる。これを解消するために生まれたのが、キューイングアルゴリズムの調整です。

WRR(Weighted Round Robin):単純明快な「重み付け」

WRRは、各キューに「重み」を割り当て、その比率に従って順番にパケットを送り出す方式です。

  • 動作原理: キュー1に重み3、キュー2に重み1を割り当てると、パケットの送り出しは「キュー1→キュー1→キュー1→キュー2」のサイクルを繰り返します。
  • 強み: 実装が非常に軽量で、ハードウェア(ASIC)への負荷が少ない。
  • 弱み: パケットサイズが不均一だと、公平性が崩れる(大きなパケットばかりのキューが実質的な帯域を占有する)。

WFQ(Weighted Fair Queuing):数学的に美しい「公平性」

WFQは、各フローのパケットが「もし全フローが均等に帯域を使ったら、いつ送り出されるはずか」という仮想的な終了時刻を計算し、その時刻が早い順にパケットをスケジューリングします。

  • 動作原理: フローごとに帯域を動的に割り当て、小規模なトラフィックを優先的に処理します。
  • 強み: 帯域の公平性が高く、設定が比較的自動化されている。
  • 弱み: 計算リソースを消費するため、超高速回線ではボトルネックになる可能性がある。

—

2. Cisco IOSでの設定実例:現場の勘所

現場でよくあるのは、特定のAPIトラフィック(例えば重要度の高い決済通信)に優先度を与えたいケースです。CiscoのMQC(Modular QoS CLI)を使った設定を見てみましょう。

! クラスマップで特定のトラフィックを識別
class-map match-any API-TRAFFIC
 match protocol http
 match protocol https

! ポリシーマップで重み付け(WRR相当の帯域保証)
policy-map QOS-POLICY
 class API-TRAFFIC
  bandwidth remaining percent 60  ! 全帯域の60%を優先的に割り当て
 class class-default
  fair-queue                      ! 残りはWFQで公平に処理

! インターフェースへの適用
interface GigabitEthernet0/1
 service-policy output QOS-POLICY

ここで重要なのは、bandwidth remaining percent です。単に「早い者勝ち」にするのではなく、保証帯域を確保しつつ、残りの帯域をWFQに委ねる。これが、障害対応で叩き上げられたエンジニアが到達する「落とし所」です。

—

3. アプリケーション層からの「可視化」とテスト

インフラ側でキューイングを設定しても、それが本当に効いているかを確認しなければ意味がありません。Pythonを使って、擬似的に帯域を枯渇させた際のレイテンシを計測してみましょう。

import requests
import time

# 複数リクエストを投げて、キューイングの影響(レイテンシ)を計測する
def test_api_latency(url):
    start_time = time.time()
    try:
        response = requests.get(url, timeout=5)
        latency = time.time() - start_time
        print(f"Status: {response.status_code}, Latency: {latency:.4f}s")
    except Exception as e:
        print(f"Error: {e}")

# 連続して大量のリクエストを投げて、帯域を圧迫させるシミュレーション
for i in range(10):
    test_api_latency("https://api.example.com/data")

このコードを実行しながら、ルータ側で show policy-map interface を叩いてみてください。pkts matched や dropped のカウンターが刻々と動く様を見るのは、ネットワークエンジニアにとって至福の瞬間です。

—

4. 運用上のTips:なぜ「設定」だけでは足りないのか

最後に、現場で泣きを見ないためのTipsを共有します。

1. MTUの不一致に注意せよ: WFQはパケットサイズの影響を受けます。経路上の MTU が異なると、想定外のフラグメンテーションが発生し、キューイングの計算が狂います。
2. シェーピングとの併用: WRRやWFQはあくまで「送出順序」を制御するものです。回線速度以上のトラフィックが流入する場合は、事前にTraffic Shapingでバーストを平滑化しておかないと、キューが瞬時に溢れ(Tail Drop)、意味を成しません。
3. モニタリングが全て: 「遅い」というクレームに対して「設定は入っています」と答えるのは素人です。SNMPやgNMIでドロップ率の変化をグラフ化し、トラフィックのスパイクと同期していることを証明して初めて、プロの仕事です。

ネットワークは生き物です。数式通りの挙動をしないことも多々あります。しかし、パケットの列の並びを想像し、それを制御するアルゴリズムの性格を理解していれば、どんな複雑なトラフィックの渋滞も、必ず解決の糸口は見つかります。

次回の運用作業では、ぜひ policy-map の中身をじっくり眺めてみてください。そこには、あなたの設計したインフラが「公平さ」を保とうともがく、健気な姿が見えるはずです。

コメント

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