トラフィックを分割する

トラフィック分割機能を使用すると、トラフィックの配分比率を指定して 1 つのサービスの複数のバージョンにトラフィックを振り分けることができます。トラフィックの分割により、バージョン間で A/B テストを実行することが可能になり、機能を展開する際のペースを制御できます。

トラフィック分割は明示的にバージョンを対象にしない URL に適用されます。たとえば、次の URL は指定されたサービス内で使用可能なすべてのバージョンを対象としているのでトラフィックを分割します。

  • [MY_PROJECT].appspot.com - トラフィックを default サービスの複数のバージョンに分配します。
  • [MY_SERVICE].[MY_PROJECT].appspot.com - トラフィックを [MY_SERVICE] サービスの複数のバージョンに分配します。

リクエストがバージョンに到達する仕組みについては、リクエストがルーティングされる方法をご覧ください。

始める前に

バージョンにトラフィックを設定する前に、必要な権限がユーザー アカウントに含まれていることを確認してください。

キャッシュの問題を回避する

トラフィック分割を有効にする前に、潜在的なキャッシュ問題を考慮することをおすすめします。キャッシュの問題はどの App Engine アプリケーションにも存在する可能性があります(特に、新しいバージョンをデプロイする場合)。トラフィック分割を行うと、キャッシュ関連の小さな問題がより顕著になることがよくあります。

たとえば、トラフィックを 2 つのバージョン(A と B)に分割しているときに、キャッシュ可能な外部リソース(CSS ファイルなど)がバージョン間で変更されたとします。この状態で、クライアントがリクエストを送信し、そのレスポンスの中にキャッシュ済みファイルへの外部参照があるとします。ローカル HTTP キャッシュの中にそのファイルがあれば、ファイルはキャッシュから取り出されます。キャッシュされているのがファイルのどのバージョンであるか、あるいはアプリケーションのどのバージョンがレスポンスを送信したかは関係ありません。キャッシュ済みのリソースはレスポンス中に送信されたデータと互換性がない可能性があります。

キャッシュの問題を回避するには:

  • 動的なリソースの場合は、Cache-ControlExpires の両方のヘッダーを設定します。これらのヘッダーは、リソースが動的であることをプロキシに伝えるものです。両方のヘッダーを設定することをおすすめします。すべてのプロキシ サーバーが HTTP/1.1 の Cache-Control ヘッダーを適切にサポートしているとは限らないためです。

    キャッシュ全般についてさらに情報が必要な場合は、HTTP/1.1 RFC のヘッダー フィールドの説明ブラウザ セキュリティ ハンドブックのドキュメント キャッシュをご覧ください。

  • キャッシュ可能な静的リソースがバージョン間で変化する場合は、リソースの URL をバージョン間で変更します。静的リソースが異なる URL から提供される場合、両方のバージョンはプロキシ サーバーとブラウザ キャッシュで問題なく共存できます。

また、アプリで Vary: Cookie ヘッダーを設定すると、リソースの一意性がリクエストの Cookie と URL の組み合わせから計算されますが、この方法ではキャッシュ サーバーへの負荷が増加します。GOOGAPPUID が取りうる値は 1,000 個あり、したがってアプリの各 URL に入る可能性のあるエントリはそれぞれ 1,000 個ということになります。ユーザーとアプリの間のプロキシにかかる負荷の大きさによっては、キャッシュ ヒット率が下がる可能性があります。また、新しいユーザー群が特定のバージョンに追加されてから 24 時間は、それらのユーザーには引き続き、キャッシュされたリソースが提示される可能性があることも考慮に入れる必要があります。ただし、Vary: Cookie を使用すると、バージョン間で変わる静的リソースの名前をより簡単に変更できるようになります。

Vary: Cookie の手法はどのような状況でも有効というわけではありません。一般に、他の目的のためにアプリで Cookie を使用する場合は、プロキシ サーバーの負荷に与える影響を考慮する必要があります。codeninja に専用の Cookie があり、取りうる値が 100 個とすると、発生する可能性のあるキャッシュ エントリすべてのための領域はきわめて大きくなります(100 * 1,000 = 100,000)。最悪のケースでは、ユーザーごとに 1 個ずつ、一意の Cookie があります。この一般的な例としては、Google アナリティクス(__utma)と SiteCatalyst(s_vi)の 2 つがあります。このような場合は、ユーザーのそれぞれに個別のコピーが作成されるため、キャッシュのパフォーマンスが大幅に低下するとともに、アプリが消費する課金対象インスタンス時間も増加する可能性があります。

複数のバージョン間のトラフィック分割

分割のために 2 つ以上のバージョンを指定する際に、トラフィックの分割で IP アドレスと HTTP Cookie のどちらを使用するかを選択する必要があります。設定が簡単なのは IP アドレス分割ですが、Cookie 分割の方が精度では上回ります。詳しくは、IP アドレスによる分割Cookie による分割をご覧ください。

Console

GCP Console でトラフィックを分割するには、[バージョン] ページに移動します。

[バージョン] ページに移動

  1. トラフィックの分割先となる 1 つ以上のバージョンを選択します。
  2. [トラフィックを分割] をクリックし、以下を指定します。
    • トラフィックの分割に使用する方式
    • 各バージョンが受け取るトラフィックの割合

gcloud

Google Cloud SDK をインストールした後で、次のコマンドを実行して複数のバージョン間でトラフィックを分割します。次に例を示します。

gcloud app services set-traffic [MY_SERVICE] --splits [MY_VERSION1]=[VERSION1_WEIGHT],[MY_VERSION2]=[VERSION2_WEIGHT] --split-by [IP_OR_COOKIE]

詳細情報と追加のオプションについては、gcloud app services set-traffic リファレンスをご覧ください。

API

プログラムでトラフィックを移行するために Admin API を使用できます。詳細については、トラフィックの移行と分割をご覧ください。

IP アドレスによる分割

IP アドレスを基準としてアプリケーションへのトラフィックを分割する場合は、アプリケーションがリクエストを受け取ったときに、IP アドレスのハッシュが計算されて 0~999 の範囲内の値となり、この数値を使用してリクエストがルーティングされます。

IP アドレス分割には次のような重要な制約があります:

  • IP アドレスは、ある程度は同じものが反復して使用されますが、永久に同じというわけではありません。ユーザーが携帯端末で接続している場合は 1 回のセッション中に IP アドレスが変わることがあります。同様に、ノート PC で接続しているユーザーが自宅からカフェに移動した場合も、IP アドレスが変わることになります。その結果、IP アドレスの変動に伴ってアプリのユーザー エクスペリエンスが変わってしまう可能性があります。
  • IP アドレスは互いに無関係にバージョンに割り当てられるため、その結果としてのトラフィック分割はデベロッパーが指定したものとは多少異なります。ただし、アプリケーションが受信するトラフィックが増えるにつれて、実際の分割は目標値に近づきます。たとえば、トラフィックの 5% をある代替バージョンに配信するよう指定した場合に、最初にそのバージョンに送信されるトラフィックの割合は実際には 3~7% ですが、最終的な平均値は目標の 5% 近くになります。
  • アプリ間で内部リクエストを送信する必要がある場合は、Cookie 分割を使用してください。Google のクラウド インフラストラクチャ上で実行中のアプリの間で送信されるリクエストは、すべて同じバージョンに割り当てられている可能性が高い、少数の IP アドレスから発信します。したがって、すべての内部リクエストは単一の IP アドレスから送信されるリクエストに似た動作をする可能性があります。つまり、それらのリクエストはすべて同じバージョンにルーティングされるということです。その結果、内部リクエストは、IP に基づくトラフィック分割のために設定した割合を厳密には尊重しません。たとえば、アプリに対するすべてのトラフィックの 1% を受け取るようにバージョンを設定し、Google クラウド インフラストラクチャ アドレスが偶然そのバージョンに割り当てられた場合、すべての内部リクエストは割り当てられたバージョンにルーティングされるので、実際の結果は 1% をはるかに超える可能性があります。Google のクラウド インフラストラクチャの外からアプリに送信されたリクエストは、送信元 IP アドレスの分布がさまざまなので、予想通り処理されます。

Cookie を基準としてアプリケーションへのトラフィックを分割する場合、アプリケーションは HTTP リクエスト ヘッダーの中で GOOGAPPUID という Cookie を探します。この中に、0~999 の範囲内の値が格納されています。

  • Cookie が存在する場合、その値はリクエストをルーティングするために使用されます。
  • そのような Cookie が存在しない場合、リクエストはランダムにルーティングされます。

レスポンスに GOOGAPPUID Cookie が含まれていない場合、まずアプリが 0~999 の間のランダム値を持つ GOOGAPPUID Cookie を追加してから送信されます。

トラフィック分割に Cookie を使用すると、ユーザーをバージョンに正確に割り当てることが容易になります。トラフィック ルーティングの精度はターゲットの分割に対して 0.1% 近くになることがあります。ただし、Cookie 分割には次の制約があります。

  • モバイルアプリを開発したり、デスクトップ クライアントを実行したりする場合は、GOOGAPPUID Cookie を管理する必要があります。たとえば、Set-Cookie レスポンス ヘッダーが使用される場合、Cookie を保存し、以後の各リクエストで含める必要があります。ブラウザベースのアプリはすでにこのようにして自動的に Cookie を管理します。

  • 内部リクエストを分割する場合は、追加の作業が必要になります。Google のクラウド インフラストラクチャ内から送信されるすべてのユーザー リクエストでは、各リクエストでユーザーの Cookie を転送する必要があります。たとえば、アプリから送信されたリクエスト内のユーザーの Cookie を別のアプリまたはそれ自体に転送する必要があります。ユーザーから発信されたものでない内部リクエストを送信するのは推奨されないことに注意してください。

トラフィック分割の無効化

トラフィック分割を無効にするには、すべてのトラフィックを単一のバージョンに移行します。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Go の App Engine スタンダード環境