tubo28's blog
つぼの 140 文字より長い文章置き場
About me

ロードバランサは Least Connections 戦略にしておけ

Last Modified: 2022-07-13T16:27:30+0900
Tags: middleware

ロードバランサにおいて Least Connections 戦略は、接続中の TCP コネクションが少ないバックエンドを優先的に選択するアルゴリズムでです。

Least Connections を使うと、単純なラウンドロビンと比べて以下のようなケースでより安定します。

  1. 一部のバックエンドが重くなったとき
  2. TCP コネクションを長く張り続けるサービスがスケールアウトしたとき

1 の「重くなる」とは、レスポンスタイムが悪化することとします。一部のバックエンドが重くなるとコネクションが開放されるのが遅れるため、Least Connections 戦略を使うと新しく来たリクエストがそのバックエンドに割り当てられなくなります。クライアントから見ると、重くないバックエンドに優先的につながるので一部の調子の悪さを隠蔽できます。重くなっているバックエンドから見ると、リクエストが来なくなるので回復も早くなることが見込めます。同じ理屈で起動直後のパフォーマンスが悪いサービス (Java や Scala のような JVM で動くサービスや、キャッシュによる高速化を図っているサービス) が水平オートスケールでスケールアウトしたときの不安定さも緩和されます。

2 は WebSocket や HTTP/2 を使うサービスが該当します。例えば稼働中のあるサービスのバックエンドが 2 台に冗長化されていて、それぞれ 50 本ずつ、合計 100 本の WebSocket のコネクションを捌いているとします。あるときそこに新たに 100 本のコネクションを求めるバースト負荷がかかり、オートスケールで 2 台のバックエンドが追加されたとします。すると、もしラウンドロビンを使っていると、新しいコネクションは 4 台に均等に分配されるので、各バックエンドのコネクション数は 125, 125, 25, 25 と不均等になります。Least Connections だとこうはならないわけです。クライアント側で TCP コネクションの最長寿命を設定して一定時間ごとに張り直すという回避策もありますが、それはクライアントの責務を逸脱しているので、できることならサーバー側でやるべきだと思います。

Least Connections の実現方法については、各バックエンドのコネクション数のテーブルから適当に探索すると O(n) や O(log n) となり遅そうです。しかし Envoy ではランダムに 2 つ選んだうちから小さい方を取るという少し賢いアルゴリズムが使われています。こうすると O(1) かつ実用的に十分な挙動になるそうです。

Supported load balancers — envoy tag-v1.23.0 documentation

現実的にほぼ全てのサービスは Least Connections で困らないので Istio の Envoy のデフォルトが少し前に Round Robin から Least Connections (LEAST_REQUEST) に変更されたらしいです。Nginx とかも脳死 Round Robin にしがちですが、良くないので気をつけなければいけませんね。

tubo28's blog
<< 賃貸マンションの探し方
>> Yamaha AG03 の設定