🧪

モダンな CDN による Edge サイド AB テスト

2020/12/16に公開
  • CDN 環境下の Web サービスでどうやって AB テストするか?
  • 対象の CDN は Edge でいろいろできるモダンなやつ

CDN 環境下での AB テスト

オリジンサーバーで AB テストによる表示パターン切り替え処理があるとする。この場合、レスポンスの HTML をキャッシュ対象にしていると、表示パターンのうちの 1 つが CDN Edge にキャッシュされてしまう。つまり、表示パターンはキャッシュ期限が切れるまで、固定化されてしまうので、AB テストは不可能ということになります。

しかし、CDN 環境下でも AB テストによる表示パターンの切り替えは実現可能です。以下で、CSR (クライアントサイドレンダリング) を使う方法と、SSR (サーバーサイドレンダリング) を使う方法について説明します。

CSR による AB テスト

パターンごとにレスポンス HTML を切り替えるのではなく、JavaScript によりクライアントサイドで表示を切り替える方法です。こちらはよく使われていて、一般的な手法だと思います。どのパターンでも HTML は同じになるので、HTML が CDN でキャッシュされていても問題ありません。AB テスト用のエンドポイントを叩いて、表示パターンを出し分ける形になるので、SPA の実装パターンとなんら変わりません。

AB テストツールである、Google オプティマイズや AMP の amp-experiment コンポーネントも CSR による AB テストになります。(amp-experiment コンポーネントによる AB テストは Google オプティマイズを使います。)

CSR による AB テストの懸念点

CSR でパターンを表示するので、JavaScript が動くまで表示することができません。これは、ユーザーのインタラクションで出現するような UI であれば問題ないですが、ページのファーストビューのように、高速に表示することが求められるような部分では問題になるかと思います。 Core Web Vitals 指標の一つである LCP (Largest Contentful Paint)の劣化も避けられません。

また、もともと SSR で実現されていた部分で AB テストのために CSR に切り替えるとなった場合、意図してないパフォーマンス劣化がテストによって発生してしまう可能性もあります。

SSR による AB テスト

CSR での AB テストに懸念があるなら SSR でやろうとなりますが、先に説明したように CDN 環境下では単純には実現できません。

SSR で単純に AB テストができない原因は、 単一 URL に対して、 単一のキャッシュが作られることにあります。つまり、 単一 URL に対して複数キャッシュを作ることができれば、 SSR でも表示パターンの切り替えができるはずです。

結論から言うと、Vary ヘッダーという HTTP ヘッダーを使えば、単一 URL に対して複数キャッシュを生成することができます。

Vary ヘッダー

Vary ヘッダーとはレスポンスヘッダーであり、構文は以下のようになります。

Vary: <header-name>, <header-name>, ...

<header-name> にはリクエストヘッダー名を指定します。ここに指定したヘッダーの値が異なる場合、レスポンスは同じURLでも別のオブジェクトとして扱われます。つまり、単一 URL で複数のキャッシュオブジェクトを生成することができるようになります。例えば、Vary ヘッダーに User-Agent ヘッダーを指定(Vary: User-Agent)したとすると、ユーザーエージェントごとにキャッシュが作られます。

Vary ヘッダーを AB テストで使う

まず、AB テスト用に以下のようなカスタムリクエストヘッダーを用意します。

ex. X-ABTest

  • テストパターン A のとき: X-ABTest: A
  • テストパターン B のとき: X-ABTest: B

このカスタムヘッダーを CDN とオリジンサーバーで利用します。以下に AB テストの構成を図にしました。

  1. CDN でパターンの振り分け
    CDN がユーザー識別子をもとに表示パターンが選択します(パターン A または パターン B)。ユーザー識別子は Cookie が存在すればそれを使います。Cookie がなければ新規作成して Cookie に付与します。

  2. CDN はリクエストを加工してオリジンサーバーにリクエスト
    CDN は振り分けたパターンをもとに、X-ABTest: A or B をリクエストヘッダーに付与してオリジンサーバーにリクエストします。

  3. オリジンサーバーで表示パターン作成
    オリジンサーバーで X-ABTest の値をもとに表示パターンを作成します。

  4. オリジンサーバーは Vary ヘッダーを付与してレスポンス
    オリジンサーバーは Vary: X-ABTest をレスポンスヘッダーに付与してレスポンスを返します。

  5. CDN でレスポンスをキャッシュ
    CDN はパターン A とパターン B でそれぞれキャッシュします。

CDN を利用した Edge AB テストのいいところ

  1. CDN Edge とオリジンサーバーで役割を分けられる
    CDN の役割はパターンを振り分けるだけであり、オリジンサーバーの役割はパターンを表示するだけとなります。これにより、それぞれのレイヤーでの責務がはっきりします。

  2. テストパターンがキャッシャブルになる
    テストパターンはそれぞれ CDN でキャッシュすることができます。これによりパフォーマンスがよくなり UX を毀損しにくくなります。

CDN を利用した Edge AB テストのよくないところ

  1. CDN Edge での処理が複雑かもしれない
    CDN とオリジンサーバーの責務はシンプルになると説明しましたが、実装は複雑になる可能性があります。例えば、CDN として Fastly を利用する場合、テストパターンの振り分け処理は VCL (Varnish Configuration Language)により記述することになります。VCL の熟練度があれば問題ないですが、サーバーサイドの言語と違う言語を書くことになるので、多少ハードルが高くなると思います。

  2. テストとパターンの数だけキャッシュが増殖する
    2 パターンを要するテストが 1 つだけなら、キャッシュは 2 つになります。仮に 2 パターンを要するテストが 2 つ同時に走っている場合はキャッシュは 4 つになります。つまり、テスト数とパターン数により倍々でキャッシュが増えていくことになります。キャッシュ数の増殖はキャッシュヒットレートの低下につながるので、パフォーマンス低下を引き起こす可能性があります。当然ですが、終わった AB テストの片付けは重要な作業になります。

CDN Edge での AB テストはどうするといいか?

CSR と SSR でどちらの方法が優れているかという話ではなく、適材適所でそれぞれを使いわければいいと考えています。ユーザーインタラクションが伴うような AB テストでは CSR しか選択肢はないですし、初期表示のようなパフォーマンスが求められるところでは SSR に分があります。今回紹介していないですが、CSR で使う AB テスト用のエンドポイントでもテストパターンの振り分けを CDN Edge に任せるということもできます。 この手法はアプリ等でも利用できます。

実際 Edge での AB テストを運用してみて、AB テストにかぎらず CDN Edge に処理を任せることで UX 最適化できるとこがたくさんありそうだと感じました。具体案はないですが、例えばコンテンツのパーソナライゼーションとかですかね。

リアルワールドの話

ここまで Vary ヘッダーの話をしてきましたが、実は Vary ヘッダーを自由度高く使える CDN は Fastly くらいしかありません。他のメジャーな CDN では、ヘッダー自体が無視されたり、消されたり、指定できるヘッダー値に制限があったりします。Fastly 並に自由度が高い CDN がありましたら、情報いただけるとありがたいです。Fastly での AB テスト方法は公式ドキュメントで紹介されています。VCL の書き方まで紹介されているので Fastly を使っている方はこのドキュメントを見るだけで実装できると思います。

Vary ヘッダーが自由に使えないからといって、CDN Edge で AB テストができないかと言ったらそうではありません。モダンな CDN はだいたい Edge でプログラム動かせるようになっているので、今回紹介したような構成で AB テストの設計ができると思います。Cloud CDN はできないかな。。。

まとめ

  • Vary ヘッダーを使えば1つの URL で複数のキャッシュが生成できる。
  • キャッシャブルなテストパターンはパフォーマンスがいい。
  • CDN Edge を利用した CDN 構成は、CDN とオリジンサーバーの責務がシンプルになる。
  • Vary ヘッダーを自由に使える CDN は Fastly だけ。

Discussion