G-gen の佐々木です。当記事では、Google Cloud (旧称 GCP) のサーバーレスコンテナサービスである Cloud Run の セッションアフィニティ 機能について解説します。
セッションアフィニティを使用することで、同じユーザーからのリクエストを特定のコンテナインスタンスにルーティングすることができます。
前提知識:Cloud Run とは
Cloud Run はサーバーレスな環境でコンテナを実行できるサービスです。
セッションアフィニティは、Cloud Run のうち、HTTP リクエストをトリガーとしてコンテナアプリケーションを実行する Cloud Run services に関する機能となります。
Cloud Run services の詳細については以下の記事で解説しています。
Cloud Run におけるセッションアフィニティ
Cloud Run でコンテナインスタンスが複数起動しているとき、クライアントからのリクエストはいずれかのインスタンスにルーティングされます。セッションアフィニティ機能により、クライアントごとのリクエストを同じコンテナインスタンスにルーティングすることができます。
セッションアフィニティを有効にすると、Cloud Run はクライアントからのリクエストに対する応答にセッションアフィニティ Cookie を追加します。Cloud Run はこの Cookie を使用してクライアントを識別し、以降のリクエストを同じコンテナインスタンスにルーティングします。
ユースケース
セッションアフィニティがベストエフォートである (後述) という仕様上、使用できる場面はいくぶん限定的なものになります。従来の「ロードバランサによる Web/AP サーバへのセッションアフィニティ (スティッキーセッション)」のイメージとは、少し違った使い方になります。
以下のようなユースケースが想定されます。
Cloud Run の背後にある Cloud SQL からユーザーデータを読み出すようなケースを考えてみます。Cloud SQL から読み出したデータはキャッシュとしてコンテナインスタンスに保持して、セッションアフィニティを有効にすることで、同じユーザーがアクセスしてきたときはコンテナインスタンスに保持されたキャッシュを利用することができます。
このケースでは、クエリを省略することでレスポンス速度の向上が見込めるほか、データベースへの余計な接続を減らし、Cloud SQL インスタンスのスペックを低めに抑えることができます。元のデータは Cloud SQL のデータベースで永続化されているため、たとえセッションアフィニティが解除されたとしても、再度クエリが行われるだけでデータが失われることはありません。
また Google Cloud の公式ブログでは、ダッシュボードのバックエンドとして Cloud Run を使用している場合に、データベースに対するクエリ結果をコンテナインスタンスにキャッシュし、セッションアフィニティでユーザーごとのクエリのキャッシュを有効活用することでダッシュボードの応答性を高める例が紹介されています。
注意点
セッションアフィニティはベストエフォート
セッションアフィニティ Cookie の 有効期限(TTL)は 30 日 に設定されていますが、Cloud Run の自動スケーリングの仕様により、クライアントがアフィニティを持っているかどうかにかかわらず、コンテナインスタンスはスケールインのタイミングで削除されてしまいます。 これは「Cloud Run のセッションアフィニティはベストエフォートである」のように表現されます。
したがって、通常は Cloud Run の外部で永続化するようなデータをコンテナインスタンスに保持し、セッションアフィニティを使用してユーザーを同一インスタンスにルーティングする、といった使い方は推奨されません。
たとえば、ショッピングカートのデータをコンテナインスタンスに保持するような場合、リクエストの減少によってコンテナインスタンスがスケールインしたタイミングで、そのインスタンスに接続していたユーザのショッピングカートの情報が失われてしまいます。
また、インスタンスあたりの同時接続数の上限に当たっている場合や、CPU 使用率が高くなっている場合でも、アフィニティが解除されてしまう可能性があります。
リビジョンのトラフィック分割との併用
Cloud Run services では、サービスをデプロイしたり構成を変更したりすると、リビジョン(版) が作成されます。最新のリビジョンにリクエストを全てルーティングするだけではなく、複数のリビジョンに対してトラフィックを分割することができます。
Cloud Run のセッションアフィニティは リビジョン単位 で有効/無効にすることができ、トラフィック分割と併用した場合、セッションアフィニティが優先 されます。
たとえば、「リビジョン A とリビジョン B にトラフィックを 50 % ずつ分割し、リビジョン A のみセッションアフィニティを有効にしている」場合を考えます。リビジョン A にルーティングされたリクエストは Cookie によってその後もリビジョン A にルーティングされ、リビジョン B にルーティングされたリクエストは Cookie がないため次回も A・B ランダムにルーティングされます。したがって、リクエストは徐々にリビジョン A にシフトされていくことになります。
また、リビジョン A・B の両方でセッションアフィニティを使用した場合、あるユーザーをリビジョン A のみ、別のユーザーをリビジョン B のみにルーティングさせることが可能です。
しかしセッションアフィニティはあくまでもベストエフォートであり、コンテナインスタンスがスケールインで削除されるなどした場合、次のリクエストが同一のリビジョンにルーティングされる保証はありません。
プログラムから Cloud Run を呼び出す場合
Web ブラウザから Cloud Run にアクセスする場合は Cookie は透過的に処理されます。一般的な Web ブラウザでは、同じドメインのサイトにアクセスする際は、Cookie を付与してリクエストするためです。
しかしそのような仕様のないプログラムから Cloud Run を呼び出す場合、初回のリクエストに対する応答に付与された Cookie を後続のリクエストに明示的に追加する必要がある点に注意しましょう。
設定方法
セッションアフィニティは Cloud Run services のサービス作成時、もしくは更新時に有効化 / 無効化することができます。
佐々木 駿太 (記事一覧)
G-gen最北端、北海道在住のクラウドソリューション部エンジニア
2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。
趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。
Follow @sasashun0805