セッションアフィニティ
最終更新日 2020年03月09日(月)
Table of Contents
セッションアフィニティ (スティッキーセッションとも呼ばれる) は、単一のアプリケーションインスタンス (Web dyno) でエンドユーザーから送信されたすべての HTTP リクエストを関連付けるプラットフォーム機能です。
セッションアフィニティを有効にする
セッションアフィニティを有効にするには、次のコマンドを実行します。
$ heroku features:enable http-session-affinity
セッションアフィニティは、Common Runtime のアプリケーションで使用できます。 現在、Private Spaces のアプリケーションでは使用できません。
セッションアフィニティとは
スティッキーセッションを使用すると、アプリケーションやフレームワークで、着信するトラフィックについての想定ができます。スティッキーセッションでは、dyno を追加したときに、単一の dyno システムで行っていた動作を継続できるように、おおよその想定ができます。
セッションアフィニティを使用しないシステムでは、プログラマがユーザーデータをメモリ (およびほかのどこか) に保存する方法を開発した場合、この方法は 1 つの dyno では問題なく動作します。ただし、システムが 2 つ以上の dyno に移行されると、異なる dyno で稼働しているサーバーが異なるリクエストを処理する可能性があります。つまり、異なるリクエストが異なるビューのサーバーデータとローカルデータを持つことになります。たとえば、あるユーザーがプロフィール写真を 1 つの dyno のディスク上に保存し、次のリクエストが別の dyno にヒットした場合、写真はその dyno にはありません。
セッションアフィニティにより、フレームワークの作成者や設計者は、複数のバックエンドシステムで発生しがちな難しい問題や要件を回避することができます。
スティッキーセッションで可能な想定には、ほかにも以下のような利点があります。
- より多くのデータをローカルのキャッシュに格納して状態をローカルのままにすると、データベース操作の件数が減ります。
- ソフトウェアの依存関係が減り、ローカルでの実行とテストが容易になる可能性があります。
- 多くの場合、ローカルでシステムの状況を判断するほうが、グローバルで判断するより簡単です。
注意
より一般的なケースで、選択したスティッキーセッションの実装に関わらず、以下のような問題が発生する可能性があります。
- dyno が無反応になる、または dyno のパフォーマンス低下、過負荷、クラッシュが発生し、ルーターに到着不能として表示される
- dyno の循環
- dyno のスケールアップ、スケールダウン
上記のすべてのケースで、短期間であったとしても、まだ稼働している dyno が新しい接続を受け付けないか、新しいリクエストを処理しないか、完全にダウンしてそれらを処理しなくなる場合があります。
そのような場合には、クライアントが別の dyno にリダイレクトされる可能性があります。セッションアフィニティのメカニズムはそのエンドポイントから再開されますが、元のものは放棄されます。
そのため、状況に応じて計画する必要があります。セッションアフィニティは、通常は最適化のために使用するもので、長期間の接続に代わるものではありません。
仕組み
Heroku のセッションアフィニティのメカニズムには、以下の特性があります。
- アプリの dyno 一式を接続または終了する効果が最小化されます。
- 無反応な dyno によってクライアントにダウンタイムが発生します。リクエストは別の dyno にルーティングされます。
- dyno は、プラットフォームや言語に関係なく、アプリケーション間で移植でき、アプリケーションを変更する必要がありません。
- HTTP Cookie をサポートしていれば、どの ISP またはインフラストラクチャのどのクライアントでも動作します。
前提条件として、HTTP Cookie が必要です。HTTP Cookie は、(IP アドレス方式や URL に基づく方式などのほかの手段に比べて) セッションアフィニティを実現する、最も信頼性があり、最も侵入されにくい手段であるためです。
アプリケーションでこの機能が有効化されるとすぐに、Heroku ルーターで新しいリクエストとレスポンスに heroku-session-affinity
という名前の HTTP Cookie が追加されるようになります。
この Cookie にはプライベートなアプリケーション情報は格納されず、動作させるためにリクエストまたはレスポンスの関連データは必要ありません。
この Cookie の値に基づき、Heroku ルーターは各リクエストに対して適切な dyno を識別できます。
また、Heroku ルーターは新しい dyno がいつ追加されたかも認識できるため、スケールアップイベントが発生したときに、新しいものを除くすべての dyno がリクエストに対応するようになるのではなく、すべての dyno のうちの一部が移行されて新しい dyno を占有します。
そのため、4 つの dyno にそれぞれ 10 件の接続があり、5 番目の dyno が追加された場合、すべてのリソースが均等に使用されるようにするために、既存のそれぞれの dyno から (平均して) 2 件程の接続が 5 番目の dyno にシフトされます。
その逆もあります。dyno がなくなると、その dyno の接続は利用可能なほかの dyno にランダムに再分散され、ほぼ均等な再分散が行われます。
セッションアフィニティを取り消す
スケールアップまたはスケールダウンを行うとリクエストは自動的に再分散されますが、必要な場合は手動でトラフィックを再分散することもできます。heroku-session-affinity
Cookie を消去すると、強制的に新しいランダムな dyno をクライアントに割り当てることができます。その後、次に発生したリクエストは Heroku ルーターで新規クライアントとして扱われ、新しい Cookie を設定することで新しい dyno が割り当てられます。
セッションアフィニティを無効にする
セッションアフィニティを無効にするには、次のコマンドを実行します。
$ heroku features:disable http-session-affinity