🐈

Cloudflare LoadBalancer の Session Affinity について

2024/09/17に公開

前回の記事でCloudflareのLoadBalancerを用いて2台のWebサーバ(Amazon EC2 + nginx)にトラフィックを分散させる手順をまとめました。
https://zenn.dev/kameoncloud/articles/aaca06bb775144
今日はLoadBalancerのオプションとして用意されているSession Affinityを試します。

Session Affinity とは

Sticky セッションとも言われます。通常ロードバランサーはリクエストを無作為ターゲットへルーティングします。前回の手順では2台のWebサーバを1:1で設定したため、ラウンドロビンでAとBへ振り分けられます。乱数が絡むので1回ごとにABABABABとなるわけではありませんが、長い目で見れば50:50になります。


リロードするたびにAとBが変わります。通常ブラウザでは暗黙的にブラウザキャッシュがHTMLに対して聞いていますが、デベロッパーツールを開きDisable Cacheにチェックを付けると挙動が確認できます。

フロントエンドアプリケーションが例えばクライアントブラウザとのセッション情報をウェブサーバの中で管理している場合、先ほどまでAと通信をしていたクライアントがBとの通信に切り替わるとセッション情報が失われるためアプリケーションにエラーが発生します。通常ロードバランサや負荷に応じでサーバ台数を増減させるオートスケーリングの機能を用いる場合、この手の情報は外部データストアに外出しして、必要に応じてセッションが復元できるようにしておく必要があります。こうすることでAで処理途中のセッションを抱えているクライアントブラウザがBとの通信に切り替わった場合セッションが即時に復元され処理が継続されます。

とはいえ、アプリケーションの改造が発生しますし、何より用いているフレームワークが対応していない場合やパッケージの場合改造が難しいケースもあります。そして外部データストアのコスト負担やWebサーバから外部データストアへの通信料などもコストとして考慮しなければならないため、理想通りのアーキテクチャを組めない場合があります。この場合に用いるのがSession Affinityという機能です。

一度クライアントがWebAと通信した場合、クッキーがセットされ、クッキーの有効期間の間は素のクライアントはWebAとのみ通信を行います。

さっそくやってみる

設定はとても単純です。
ロードバランサーの編集画面から以下のトグルをオンにするのみです。

方式を選択します。

この選択肢はクライアントをどのように識別するか?です。ブラウザ単位であればCookieを用いるのが一番簡単です。
Cloudflare Cookie およびクライアント IP フォールバックではクッキーがセットされていない新しい環境からのリクエストの場合IPアドレスをベースにクライアントを識別します。つまり初回アクセスに限定して、同じIPアドレスであれば同じWebサーバへルーティングされます。2回目以降はCookieの情報に従います(勿論初回と同じWebへアクセスします)
HTTP ヘッダーによるはベータ版の機能ですが、IPアドレスやクッキーに関係なく同じヘッダーであれば同じWebサーバへルーティングさせます。例えばPCとスマホで同じアプリにアクセスするケースが送致される場合などに便利です。

ここにはCookieの有効期間、セッションの切り捨て時間を指示します。セッションの切り捨てはセッションがアイドル状態(通信が行われていない時間間隔)を計測しています。

Session Affinity を用いた場合、セッション有効期間の間は同じターゲットへルーティングされます。この際Webに障害が発生した場合の挙動を設定します。
なし:同じWebへルーティングされ続け復旧を待ちます。
一時的: 指定された別のエンドポイントに、オリジナルのWebが復旧するまでルーティングされます。
スティッキー:Cookieを書き換え別のヘルスチェックが通っているWebに恒久的にルーティングされます。

なしで設定した場合以下の動作になります。
まず初回アクセス時にブラウザにクッキーがセットされます。

この時点でWebを落とすと以下になります。

通常のLoadBalancerであれば別のターゲットへルーティングされますが、Session Affinityが効いているためこのようなエラー画面になります。

Discussion