4 ポイント 投稿者 GN⁺ 2024-01-17 | 1件のコメント | WhatsAppで共有
  • SpeedbumpはGoで書かれたTCPプロキシで、プロキシされるTCPトラフィックに可変ネットワークレイテンシを追加して遅延状況をシミュレーションする
  • 基本レイテンシに正弦波、のこぎり波、矩形波、三角波形式のレイテンシ成分を加えることができ、複数のレイテンシ成分を同時に組み合わせられる
  • 例では、localhost:80宛てのトラフィックをポート2000でプロキシしつつ、100msの基本遅延、100msの正弦波振幅、1mの周期を適用する構成を示している
  • インストールは、リリースごとの事前ビルド済みバイナリのダウンロード、ソースからのgo build、またはkffl/speedbumpコンテナイメージの実行で行える
  • CLIに加えて、Goのlibパッケージ経由でライブラリとして利用でき、バッファサイズ・遅延キューサイズ・ログレベル・リッスンするホストやポートなどを引数で調整できる

TCP遅延シミュレーション用プロキシ

  • SpeedbumpはGoで書かれたTCPプロキシで、可変ネットワークレイテンシをシミュレーションできる
  • プロキシ先はCLIの<destination>引数で指定し、形式はhost:postと案内されている
  • 基本動作は、TCPトラフィックを宛先へプロキシしながら設定した遅延を追加する方式である

インストールと実行方法

  • 最も簡単なインストール方法は、各releaseAssetsに自動添付される事前ビルド済みバイナリをダウンロードすること
  • ソースからビルドするには、リポジトリをクローンした後にgo buildを実行する
  • コンテナで実行するには、kffl/speedbumpイメージを利用できる

基本的な使用例

  • ポート2000で待ち受け、localhost:80へTCPトラフィックをプロキシしながら、基本遅延100msと正弦波振幅100ms、周期1mを適用できる
    • この構成では、追加レイテンシの最大値は200ms、最小値は0になる
    • 実行例はspeedbump --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • 同じ構成をコンテナイメージで実行することもできる
    • 例はdocker run --net=host kffl/speedbump:latest --latency=100ms --sine-amplitude=100ms --sine-period=1m --port=2000 localhost:80
  • のこぎり波の遅延成分も設定できる
    • 例では、基本遅延300ms、のこぎり波振幅200ms、周期2m、ポート2000、宛先localhost:80の構成を示している
    • 実行コマンドはspeedbump --latency=300ms --saw-amplitude=200ms --saw-period=2m --port=2000 localhost:80

レイテンシ成分の組み合わせ

  • Speedbumpは複数のレイテンシ成分を同時に適用できる
  • READMEには、のこぎり波と正弦波を組み合わせた遅延グラフの例が含まれている

CLI引数とライブラリ利用

  • speedbump --helpspeedbump [<flags>] <destination>形式の使用法を提供する
  • 主なネットワーク設定は次のとおり
    • --host: 待ち受けるIPまたはホスト名。指定しない場合はすべてのネットワークインターフェースにバインドする
    • --port: 待ち受けポート。デフォルト値は8000
    • --buffer: TCP読み取りに使用するバッファサイズ。デフォルト値は64KB
    • --queue-size: 読み取りバッファを保存する遅延キューのサイズ。デフォルト値は1024
  • 遅延関連のデフォルト値と波形オプションを提供する
    • --latency: プロキシトラフィックに追加される基本レイテンシ。デフォルト値は5ms
    • --sine-amplitude, --sine-period: 正弦波レイテンシの振幅と周期
    • --saw-amplitude, --saw-period: のこぎり波レイテンシの振幅と周期
    • --square-amplitude, --square-period: 矩形波レイテンシの振幅と周期
    • --triangle-amplitude, --triangle-period: 三角波レイテンシの振幅と周期
  • 運用関連オプションも含まれる
    • --log-level: ログレベル。利用可能な値はDEBUGTRACEINFOWARNERROR
    • --version: アプリケーションのバージョンを表示する
  • SpeedbumpはGoライブラリとしても利用でき、libパッケージ経由で提供される
  • ライセンスはApache 2.0 License

1件のコメント

 
GN⁺ 2024-01-17
Hacker Newsのコメント
  • さまざまなActivityPub実装を、いろいろなネットワーク規模や条件でテストするために似たようなものを調べたことがあるが、必要なものはすでに自分のマシンにtcとして全部入っていた
    自分のディストリビューションでは iproute2 パッケージに含まれていて、説明はここにもある: https://wiki.archlinux.org/title/advanced_traffic_control
    特定のインターフェースに遅延を追加するには、tc qdisc add dev eth0 root netem delay 100msのように実行すればいい
    使いやすく、Dockerコンテナでもうまく動作し、遅延・パケット損失・重複のような条件を適用でき、すでにインストールされている可能性も高い

    • tc/netem/tbfは本当に素晴らしい。その上に簡単なPython GUIを作って、タッチスクリーンのケースに入れたPiで動かしたことがあるが、「パケットドロップ: [0%] [1%] [10%] [50%] / パケット破損: ...」のような小さな黒い箱で、顧客はかなり感心していた
      こういうフロントエンドが商用ハードウェア製品としてあまり見当たらないのは意外で、検索で見落としていないなら市場に存在しないようだ
    • tcの欠点は、受信パケットに適用しようとすると少し変で扱いづらいことだ
      以前、特定の商用衛星端末をまねるために自作のエミュレーターを作ったことがある。その端末はパケットをキューにため込み、特定のしきい値に達するか時間制限を超えるとまとめて一気に送り出していた。また、小さなパケットを「親切にも」キューの先頭へ並べ替えて遅延を減らそうとしていたが、TCPスタックはそれを非常に嫌っていた
    • speedbumpの良い点は、障害条件を時間に応じて変化させられることだ。tcにはそれができない
      時間とともに変化する衛星/RFの気象影響をシミュレーションするのにかなり役立つかもしれない
  • Netflixが作ったのがまさにこれで、名前はlatency monkeyだった
    下位サービスが「遅い」かどうかを判定するのは「利用不能」かどうかを判定するよりはるかに難しいと分かり、そのためサービスの低速化やネットワーク問題をどう処理するかを試す重要な方法だった
    実装は非常に単純で、設定可能な割合でパケットをドロップし、それによって再送を強制して、相手側にはパケットが遅れて順序も乱れた状態で到着するようにしていた
    最終的に、ネットワークアクセスに関するエラー処理コードで多くの問題を発見した

  • 対話型インターネットアプリケーションを作るすべてのソフトウェアエンジニアは、日常業務でこうしたツールを必ず使うべきだと思う。TCPだけでなくQUICも必要で、DNSまで対象にするなら理想的にはすべてのUDPも含めるべきだ
    作る側の人たちが金ぴかのCadillacのような計算環境しか使っていなければ、Webアプリの肥大化の90%は消えていただろうと確信している

  • 災害救援のようにネットワーク接続が断続的に切れる環境では、多くのアプリがひどい動作をする
    もっと多くのアプリ開発者が断続的な接続をシミュレーションしてテストすれば、他の人たちの助けになるかもしれない
    「Toxiproxy is a framework for simulating network conditions」(2021) https://news.ycombinator.com/item?id=29084277#29088775 からの内容:

    多くのアプリには、たとえばメールクライアントに期待されるような「送信トレイに保留する」機能がない

    • [ ] 典型的な #DisasterRelief の接続問題をシミュレーションするための、参考用 toxiproxy「テストケース変異器」セットを誰か作れないだろうか?
    • 一番嫌いなのは、パケット送信前にバッファを埋めないケースだ。そうなると、パケットドロップと高遅延によってTCP再送が発生するような劣悪なインターネット接続下では、突然120kpsしか出なくなる
      50バイトのパケットしか送っておらず、そのうち10個に1個が失われるからだ。その間、サーバーの1スレッドは有用な仕事ができない
  • Macでは内蔵ツールだけでも同じことができる

    # Setup pipe  
    sudo dnctl pipe 1 config bw 1Kbit/s delay 800
    
    # Setup matching pf rule  
    echo "dummynet out proto tcp from any to 127.0.0.1 port 11211 pipe 1" | sudo pfctl -f -
    
    # Turn on firewall  
    sudo pfctl -e
    
    # Test  
    time nc -vz 127.0.0.1 11211  
    Connection to 127.0.0.1 port 11211 [tcp/*] succeeded!  
    nc -vz 127.0.0.1 11211 0.01s user 0.00s system 0% cpu 1.333 total  
    
    • Dummynetとこれらの機能はFreeBSD由来で、そこではずっと昔から存在していた。15年以上前にこれでパケット損失テストをしたことがあるが、ちゃんと動いていた
  • しばらく更新されていないが、名前だけでも多くを物語るプロジェクトがある: https://github.com/tylertreat/comcast

  • 最近Macで遅いネットワークをシミュレーションしようとしてNetwork Link Conditionerを見つけたが、かなり良い。プロキシのようなものを設定する必要がない
    Xcode追加ツールからインストールする必要がある
    https://nshipster.com/network-link-conditioner/

  • Shopifyの優れたツールtoxiproxyも見る価値がある: https://github.com/Shopify/toxiproxy
    ネットワーキングライブラリを自前実装してテストする際にも非常に良いやり方だ。スタックは大半の不利な状況を正しく処理できるべきだからだ
    「カオスエンジニアリング」という発想は素晴らしい

    • 自分も最初はtoxiproxyを見つけたが、クライアント・サーバーモデルが自分には合わず、speedbumpはHTTP遅延シミュレーションという自分の用途にぴったりだった
      Webクローラー用の進捗表示バーを開発中だが、localhostでテストすると速すぎて問題があるのか分かりづらい
      speedbumpなら、podman run --net=host kffl/speedbump:latest --latency=1s --port=8001 localhost:8000を実行して、http://localhost:8001でクローラーをテストするだけでいい
      すっきりしたツールだ
  • Windowsで使ったことのある似たツールがある
    https://jagt.github.io/clumsy/

    • 10年ほど前に複数の大陸間ネットワーク状況をテストするのに使ったが、結果は現実によく合っていた。おすすめできる
    • 良さそうだが、スクリーンショットを見る限り、アダプター単位の適用というよりフィルター付きのシステム全体適用のように見える
  • FreeBSDにも ipfw の一部としてdummynetがあり、遅延、帯域制限、キューサイズ、パケット損失を注入できる。MacOSにあるものと同じ機能だ

    • Linuxのtcと同じようなもの?