Apache APISIX を使用した Sticky Sessions - 理論編
July 27, 2023
Sticky sessions(スティッキーセッション)、またはセッションアフィニティは、リクエストを常に同じ上流ノードにルーティングするファサードとして機能するルーティングコンポーネントのメカニズムです。この記事では、スティッキーセッションの背景にある理由、利用可能な代替手段、およびApache APISIXを使用してそれらを実装する方法について説明します。
スティッキーセッションの必要性
スティッキーセッションは、データベースではなく上流ノードに状態を保存していた時代に人気を博しました。簡素化されたeコマースショップの例を使ってさらに説明します。
小さなeコマースサイトの基本的な構成は、Webアプリケーションとデータベースで構成されます。
ビジネスが成功すると、このアーキテクチャをスケールする必要が出てきます。垂直スケーリング(より大きなマシン)ができなくなったら、水平スケーリング(より多くのノード)を行う必要があります。追加のアプリノードがある場合、Webアプリノードの前にロードバランサーメカニズムを配置して、負荷を分散させる必要があります。
毎回データベースにアクセスするのはコストの高い操作です。頻繁にアクセスされないデータであれば問題ありません。しかし、リクエストごとにカートの内容を表示したい場合、いくつかの代替手段があります。Webアプリがサーバーサイドレンダリングを使用していると仮定すると、古典的な解決策は、カート関連のデータをWebアプリノードのメモリに保持することです。
ただし、ユーザーXのカートをノード1に保存する場合、ユーザーXのすべてのリクエストを同じノードに転送する必要があります。そうしないと、ユーザーはカートの内容を失ったように感じるでしょう。スティッキーセッション、またはセッションアフィニティは、同じユーザーを常に同じノードにルーティングするメカニズムです。
スティッキーセッションの制限
さらに進む前に、スティッキーセッションの重要な制限について説明する必要があります。データを保存しているWebアプリノードが何らかの理由でダウンすると、データは回復不能に失われます。上記のeコマースシナリオでは、ユーザーが時々カートを失うことを意味し、ビジネスの観点からは受け入れられません。
このため、スティッキーセッションはセッション複製と併用する必要があります。ノードに保存されたデータは、他のすべてのノードと同期してコピーされる必要があります。
セッション複製はすべての技術スタックに存在しますが、関連する仕様はありません。私はJVMに詳しいので、いくつかのオプションを紹介します:
- Tomcatはセッション複製を標準で提供しています
- Hazelcastは、さまざまなレベルで統合できるクラスタ化されたインメモリソリューションを提供しています
- Spring Sessionは、特定のソリューションの上に抽象化レイヤーを提供します
データがすべてのノード(またはリモートクラスタ)に複製されている場合、スティッキーセッションは不要だと思うかもしれません。可用性のみを考慮する場合は確かにそうです。しかし、パフォーマンスを考慮すると、データの局所性が重要です。ネットワーク経由で他の場所からデータを取得するよりも、現在のノードからデータを取得する方が高速です。
Apache APISIXでのスティッキーセッション
スティッキーセッションは、ロードバランサー、リバースプロキシ、APIゲートウェイにとって必須の機能です。しかし、Apache APISIXのドキュメントには、このトピックへの簡単な入り口が必要だと認めざるを得ません。
Apache APISIXは、_route_を_upstream_にバインドします。アップストリームは1つ以上のノードで構成されます。リクエストがルートに一致すると、Apache APISIXは利用可能なすべてのノードの中からリクエストを転送するノードを選択する必要があります。デフォルトでは、アルゴリズムは重み付きラウンドロビンです。ラウンドロビンは、1つのノードから次のノードへと順番に使用し、最後のノードの後は最初のノードに戻ります。重み付きラウンドロビンでは、重みがApache APISIXがノードに転送するリクエストの数に影響を与えます。
ただし、他のアルゴリズムも利用可能です:
- 一貫性ハッシュ
- 指数加重移動平均チャート
- 最小接続
- カスタムメイドのアルゴリズム
一貫性ハッシュは、NGINX変数、HTTPヘッダー、クッキーなどの値に応じて同じノードに転送することを可能にします。
HTTPはステートレスなプロトコルであることを覚えておいてください。そのため、アプリケーションサーバーは最初のレスポンスでクッキーを設定し、HTTPリクエスト間でユーザーを追跡します。これが「セッション」と呼ばれるものです。基盤となるセッションクッキーの名前を知る必要があります。異なるアプリケーションサーバーは異なるクッキーを配布します:
- JVMベースのサーバーでは
JSESSIONID
- PHPでは
PHPSESSID
- ASP.Netでは
ASPSESSIONID
- など
私は通常のTomcatを使用するので、セッションクッキーはJSESSIONID
です。したがって、2つのノードのApache APISIXドキュメントは次のようになります:
routes:
- uri: /*
upstream:
nodes:
"tomcat1:8080": 1 #1
"tomcat2:8080": 1 #1
type: chash #2
hash_on: cookie #3
key: cookie_JSESSIONID #4
- アップストリームノードを定義
- 一貫性ハッシュアルゴリズムを選択
- クッキーに基づいてハッシュ
- ハッシュするクッキーを定義
結論
この記事では、スティッキーセッションについて詳しく説明し、スティッキーセッションと常にセッション複製を使用すべき理由、およびApache APISIXでスティッキーセッションを実装する方法について説明しました。
さらに詳しく知りたい場合: