Azure Static Web Apps で運用環境のリクエストの一部をプレビュー環境に送信出来るようになったので試してみた

2023.10.29

Azure Static Web Apps はフロントエンドを中心とする Web アプリケーションのビルド・デプロイ・ホスティングを行うことが出来るサービスです。

この Static Web Apps ですが、バージョンの異なる複数の環境をホスティングすることが出来るプレビュー環境という機能があります。
運用環境以外にステージング環境、開発環境など様々な用途で活用が可能なのですが、先日こちらのプレビュー環境で複数の環境でへトラフィックを分割することが出来る機能がプレビューリリースされました。

この機能を使うと、指定した割合の運用環境へのユーザーリクエストを別のプレビュー環境にルーティングさせることが出来ます。
カナリアリリースや A/B テストのユースケースで使うことが出来そうです。

本日はこちらの機能を使ってみたので紹介したいと思います。

プレビュー環境の用意

前提として、運用環境には次のリポジトリが統合されています。
なお、今回の機能は Static Web Apps のスタンダードプランで利用可能ですのでご注意ください。

ちなみに、デプロイされた環境は次のようなレスポンスを返却します。

% curl https://victorious-moss-08ede0800.4.azurestaticapps.net/
<html>
<head></head>
<body>
hoge add direct main
1
</body>
</html>

ここで、適当なブランチを作成して変更を加え、そこからプルリクエストを作成します。

プルリクエストが作成されると次のように自動でビルドとデプロイがされます。
運用環境ではなく対象ブランチ用の環境が新しく作成されています。

このあたりについては以前記事で紹介したことがありますので、そちらもご確認ください。

この時点では運用環境用のエンドポイントから、プレビュー環境にリクエストが送信されることはありません。
プレビュー環境ごとのエンドポイントを利用する必要があります。

% curl https://victorious-moss-08ede0800.4.azurestaticapps.net/
<html>
<head></head>
<body>
hoge add direct main
1
</body>
</html>

% curl https://victorious-moss-08ede0800-8.eastasia.4.azurestaticapps.net/
<html>
<head></head>
<body>
hoge add direct main
2
</body>
</html>

トラフィック分割の設定

では、アップデートで使えるようになったトラフィック分割機能を使ってみます。
Static Web Apps の Environments メニューから「Traffic splitting」を押下します。

デフォルトでは Production 環境に 100% のトラフィックが送信されるようになっていますが、ここで Add ボタンを押してみます。

別の環境が選択出来るようになっていますね。
トラフィックの何 % をどの環境に送信するかを構成することが出来ます。

なお、全環境あわせて 100% になるようにトラフィックの分割割合は設定する必要があります。

今回は次のように、運用環境に 6 割、プルリクエスト中の環境に 4 割を送信するような構成にしてみました。

試してみると、運用環境用のエンドポイントへ送信した際に次のように異なる環境のレスポンスが返却されるようになったことが確認出来ました。

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:08:35 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "68394741"
last-modified: Sat, 28 Oct 2023 23:44:38 GMT
set-cookie: StaticWebAppsTrafficSplittingCookie=default; path=/; secure; HttpOnly; domain=victorious-moss-08ede0800.4.azurestaticapps.net; expires=Mon, 28 Oct 2024 00:08:35 GMT; SameSite=None
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:08:36 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "07055730"
last-modified: Sat, 28 Oct 2023 23:55:05 GMT
set-cookie: StaticWebAppsTrafficSplittingCookie=8; path=/; secure; HttpOnly; domain=victorious-moss-08ede0800.4.azurestaticapps.net; expires=Mon, 28 Oct 2024 00:08:36 GMT; SameSite=None
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off
x-robots-tag: none

上記レスポンスから環境毎に Etag ヘッダーの値が異なることに注目してください。
連続で cURL でリクエストを送信すると Etag 値が次のように変化しました。

リクエスト Etag 値
1 回目 68394741
2 回目 07055730
3 回目 07055730
4 回目 68394741
5 回目 68394741
6 回目 07055730
7 回目 07055730
8 回目 68394741
9 回目 07055730
10 回目 07055730

60%、40% で分割されていそうですね。

スティッキーセッションが有効になっているようだ

先程のように cURL からリクエストを送信した場合はアクセスごとに環境が変わりました。
しかし、実際にブラウザで確認してみると同じアクセス元からは常に同じ環境のレスポンスが返却され混在することはありませんでした。

確認したみたところスティッキーセッション(セッションアフィニティ)が効いているようですね。
よく見ると先程のレスポンスに Set-Cookie ヘッダーでStaticWebAppsTrafficSplittingCookieというものが存在することが確認出来ます。
どうやらこちらを使って同一アクセス元を同じ環境に張り付かせているようです。

実際に対象 Cookie を設定してリクエストを送信してみると、どちらの環境にアクセスするかをクライアントの Cookie 値に従って振り分けていそうなことが確認出来ました。

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/ -H "Cookie: StaticWebAppsTrafficSplittingCookie=8"
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:21:05 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "07055730"
last-modified: Sat, 28 Oct 2023 23:55:05 GMT
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off
x-robots-tag: none

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/ -H "Cookie: StaticWebAppsTrafficSplittingCookie=8"
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:21:07 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "07055730"
last-modified: Sat, 28 Oct 2023 23:55:05 GMT
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off
x-robots-tag: none

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/ -H "Cookie: StaticWebAppsTrafficSplittingCookie=8"
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:21:10 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "07055730"
last-modified: Sat, 28 Oct 2023 23:55:05 GMT
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off
x-robots-tag: none

% curl -I https://victorious-moss-08ede0800.4.azurestaticapps.net/ -H "Cookie: StaticWebAppsTrafficSplittingCookie=default"
HTTP/2 200 
content-type: text/html
date: Sun, 29 Oct 2023 00:21:26 GMT
accept-ranges: bytes
cache-control: public, must-revalidate, max-age=30
etag: "68394741"
last-modified: Sat, 28 Oct 2023 23:44:38 GMT
content-length: 67
strict-transport-security: max-age=10886400; includeSubDomains; preload
referrer-policy: same-origin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-dns-prefetch-control: off

今回の場合だと default を送信すると運用環境へ、8 を送信するとプルリクエスト環境に送信されていました。

さいごに

本日は Azure Static Web Apps で運用環境のリクエストの一部をプレビュー環境に送信出来るようになったので試してみました。

これはなかなか良いですね!カナリアリリースなどを手軽に実現出来そうです。