Azure App ServiceのARRアフィニティ機能をオンにした時の負荷分散の挙動を観察してみた

2022.04.16

いわさです。

先日、App ServiceのARRアフィニティについて調べていました。

その過程で気づいたのですが、ARRアフィニティONの時のApp Serviceの負荷分散の様子がおもしろかったので紹介します。

ARRアフィニティを有効化

何はともあれ、ARRアフィニティの動作をまず確認します。
詳細は前回の記事を見て頂ければと思いますが、Basic以上でスケールアウトを2台以上に設定します。
デフォルトでARRアフィニティはオンになっています。

Cookieなしでリクエストを何度か送ってみると、異なるSet-Cookieが返却されると思います。
このCookieをクライアントから送信するとApp Serviceによって振り先のインスタンスが決められます。

Cookieなし

$ curl -I https://iwasa-backend.azurewebsites.net
HTTP/1.1 200 OK
:
Set-Cookie: ARRAffinity=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net
Set-Cookie: ARRAffinitySameSite=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net
:

$ curl -I https://iwasa-backend.azurewebsites.net
HTTP/1.1 200 OK
:
Set-Cookie: ARRAffinity=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net
Set-Cookie: ARRAffinitySameSite=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net
:

Cookieを指定してみます。

Cookieあり

$ curl -I -b 'ARRAffinity=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net' -b 'ARRAffinitySameSite=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net' https://iwasa-backend.azurewebsites.net
HTTP/1.1 200 OK
:

メトリックを確認

前述の方法でCookieなし、Cookieありでいくつかリクエストを送信しました。
Azureポータルからリクエストのメトリックを確認することが出来ますので見てみます。

464回リクエストを送信していました。
curlで手動です。指が疲れる。

バックエンドインスタンスは2台へ手動スケーリングさせてて、このメトリックは2台を合算したものが表示されています。
このままだと、どのインスタンスにどの程度リクエストが送信されたのかわからないですね。

メトリックの「分割を適用する」で「Instance」を指定するとインスタンスごとにグループを分割することが出来ます。よく出来ている。

分割したグラフが以下になります。

3つの時間帯に分けて、枠を描きました。
ここでは以下のようなリクエストの送り方をしていました。

  • 1つめは、Cookieなし
  • 2つめは、Cookieありで偏らせた
  • 3つめは、Cookieなしで均等になることを期待

1つめと2つめは概ね期待どおりですね。
Cookieを指定しなかった場合は分散化されていて、Cookieを指定した場合は集中していることがわかります。

3つめがちょっと意外でした。
てっきりラウンドロビンだと思っていたので1つめと同じように均等に分散されるのかと思っていました。

実際にはCookieを指定していないのにも関わらず1分間くらいは、先程偏らせたほう「ではない」インスタンスにリクエストが集中していました。
しばらくするとどちらのインスタンスにも分散されるようになり、最終的な良い感じのバランスになっています。
各インスタンスの負荷状況をうまい感じに見てくれているみたいですね。

Traffic Managerの記事には以下のように記述があったのでラウンドロビンなのかと思っていましたが、厳密には違うようです。

同じリージョンでのアプリのみの展開の場合、App Service はそのモードには関係なく、フェールオーバーとラウンド ロビンの機能を既に備えています。

おまけ:ARRアフィニティOFF

本題から全然外れますが、ARRアフィニティOFFの状態でCookieでインスタンスIDを指定してみました。
OFFにすると、Set-Cookieが設定されなくなるだけで分散のコントロールは出来るのだろうかという実験です。

Cookieを付与して送ってみたのですが、結果としては以下のように分散されました。
どうやらオフにすると、Set-Cookieが付与されなくなるだけではなく、Coookieを受け取らなくなるようです。そりゃそうか。

さいごに

前回のおまけみたいな記事ですが、今回はApp ServiceにてARRアフィニティ機能を使ってリクエストがどのように均等になるのか、偏らせたときにどういう挙動をするのかを確認してみました。

結果としてはインスタンスの負荷状況を見てうまいこと分散してくれていました。

スティッキーセッションだと、一部の負荷の高いユーザーが特定インスタンスに固定されてしまってボトルネックになる場合が懸念になると思いますが、App Serviceではうまいこと負荷を見ながら分散してくれているので、負荷が上がっているインスタンスに無条件で後続ユーザーを固定することを回避してくれてました。
とはいえ、パフォーマンスの観点からもアプリケーションをステートレスにしてARRアフィニティをオフにすることはドキュメントでも推奨されているので、ARRアフィニティ機能に甘えずに生きていきたいと思います。