負荷分散クラスターのセッション、Cookie、トークン、およびセッションソリューションを完全に理解する

資格のあるポーターになって、他の人のメモをいくつかの情報で整理し、要約が非常に正しいことを確認してください。再印刷する前に自分のカタログを保存してください。いつか404として報告されるのではないかと心配しています。

実際、私は多くのソリューションを調べましたが、機能する実装のほとんどは、キャッシュを介したセッションの分散共有であることがわかりました。前の著者はポルノとPythonに基づいたセッション共有スキームを要約しました

さらに、セッションの分散共有のいくつかのJava実装が追加されます。

 

セッション、Cookie、トークンとは正確には何ですか

簡単な説明

書く前にセッションとクッキーに関する記事をたくさん読んだのですが、最初にクッキーがあり、次にセッションがあると言う人もいました。最初にセッションがあり、次にCookieがあると言う人もいます。はっきり言っているとは思いませんし、一般的に話します。この記事がすべての人に役立つことを願っています。
注:この記事では、読者がCookie、セッション、およびトークンの基本的な知識を持っている必要があります。

httpはステートレスプロトコルです

ステートレスとは何ですか?つまり、このリクエストは前のリクエストとは関係がなく、お互いを知らず、関連もありません。このステートレスの利点はスピードです。欠点は、私たちがしたい場合ということですwww.zhihu.com/login.htmlwww.zhihu.com/index.html関連付ける、あなたには、いくつかの手段やツールを使用する必要があります。

クッキー和セッション

httpのステートレスな性質により、特定のドメイン名のすべてのWebページが特定のデータを共有できるようにするために、セッションとCookieが表示されます。クライアントがサーバーにアクセスするためのプロセスは次のとおりです。

  • まず、クライアントはhttpリクエストをサーバーに送信します。
  • サーバーはクライアント要求を受け入れると、セッションを確立し、http応答をクライアントに送信します。この応答ヘッダーにはSet-Cookieヘッダーが含まれています。このヘッダーには、sessionIdが含まれています。Set-Cookieの形式は次のとおりです。詳細については、Cookieの詳細な説明を参照してください。
    Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
  • クライアントによって開始された2番目のリクエストでは、サーバーがset-Cookieを提供すると、ブラウザは自動的にCookieをリクエストヘッダーに追加します
  • サーバーはリクエストを受信し、Cookieを分解し、情報を検証し、検証が成功した後、クライアントに応答を返します。

リクエストプロセス

注意

  • Cookieは、セッションを実現する方法の1つにすぎません。最も一般的に使用されていますが、それが唯一の方法ではありません。URLを入力するなど、Cookieを無効にした後に保存する方法は他にもあります。
  • 現在、それらのほとんどはセッション+ Cookieですが、Cookieなしでセッションのみを使用するか、セッションなしでCookieのみを使用します。理論的には、セッション状態を維持できます。ただし、実際には、多くの理由から、通常は単独で使用されません。
  • セッションでは、クライアント側でIDを保存するだけで済みます。実際、サーバー側では大量のデータが保存されます。すべてのCookieが使用されている場合、データ量が多いと、クライアントにはそれほど多くのスペースがありません。
  • セッションではなくCookieのみを使用する場合、すべてのアカウント情報がクライアントに保存されます。ハイジャックされると、すべての情報が漏洩します。また、クライアントデータの量が多くなり、ネットワークを介して送信されるデータの量も多くなります

概要

つまり、セッションはユーザー情報ファイルテーブルのようなもので、ユーザーの認証情報やログインステータスなどの情報が含まれています。Cookieはユーザーパスです。

トークン

トークンはトークンとも呼ばれます。uid+ time + sign [+ fixed parameter]によるトークン
の認証方法は、一時的な証明書の署名に似ており、サーバー側のステートレス認証方法であり、RESTAPIに非常に適しています。シナリオ。ステートレスとは、サーバーがID認証に関連するデータを保存しないことを意味します。

組成

  • uid:ユーザーの一意のID
  • 時間:現在の時刻のタイムスタンプ
  • 記号:署名。第三者による悪意のあるスプライシングを防ぐために、ハッシュ/暗号化を使用して固定長の16進文字列に圧縮されます。
  • 固定パラメーター(オプション):データベース検索の繰り返しを回避するために、一般的に使用されるいくつかの固定パラメーターがトークンに追加されます

お店

トークンは通常、クライアントのlocalStorage、cookie、またはsessionStorageに保存されます。通常、サーバー上のデータベースに保存されます

トークン認証プロセス

トークンの認証プロセスはCookieと非常によく似ています

  • ユーザーがログインした後、サーバーは成功後にトークンをクライアントに返します。
  • クライアントはデータを受信して​​クライアントに保存します
  • クライアントはサーバーに再度アクセスし、トークンをヘッダーに配置します
  • サーバー側はフィルターを使用して検証します。検証が成功した場合は要求されたデータが返され、検証が失敗した場合はエラーコードが返されます

トークンはcsrfに抵抗できますが、cookie + sessionは抵抗できません

ユーザーが銀行のWebページにログインしている場合、そのWebページはcsrf攻撃から保護されていません。攻撃者は画像を挿入できhttp://www.bank.com/api/transfer?count=1000&to=Tomます。画像のsrcはです。session + cookieの場合、ユーザーはWebページを開いたときにすでに1,000元をトムに送金しています。セッションが確立されると、現在のドメインページとページパスの下のすべてのページがCookieを共有するためです。imgリクエストの時点で、ブラウザによってCookieがリクエストヘッダーに自動的に追加されます。ただし、トークンは異なります。開発者は、リクエストを開始するたびに、手動でトークンをリクエストに追加します。つまり、ページを開いてimgをリクエストする場合、リクエストヘッダーにトークンはありません。

分散型の場合のセッションとトークン

セッションは常にステートフルであり、通常はサーバーのメモリまたはハードディスクに保存されることはすでにわかっています。サーバーが分散またはクラスター化されると、セッションは負荷分散の問題に直面します。

  • 複数のサーバーで負荷分散を行う場合、複数のサーバーがセッションを共有しないため、現在のユーザーがログインしているかどうかを確認するのは困難です。この問題は、セッションをサーバーに保存することでも解決できますが、負荷分散の効果を完全に実現することはできません。

トークンはステートレスであり、すべてのユーザー情報はトークン文字列に格納されます

  • クライアントはログインしてサーバーに情報を転送し、受信後、サーバーはユーザー情報(トークン)を暗号化してクライアントに送信します。クライアントはトークンをlocalStroageなどのコンテナーに格納します。クライアントはアクセスするたびにトークンを渡し、サーバーはトークンを復号化してユーザーが誰であるかを認識します。CPUの暗号化と復号化により、サーバーはストレージスペースを占有するためにセッションを保存する必要がないため、複数のサーバーの負荷分散の問題が解決されます。このメソッドはJWT(Json Web Token)と呼ばれます

総括する

  • セッションはサーバーに保存されます。サーバーは、通常Cookieに保存される一意の識別記号sessionIdを持つ状態リストとして理解できます。サーバーはCookieを受信した後にsessionIdを解析し、セッションリストを検索して対応するセッションを見つけます。クッキーに頼る
  • Cookieは、セッションIDを備えたトークンに似ており、クライアントに保存されます。通常、ブラウザはCookieを自動的に追加します。
  • トークンもトークンに似ています。ステートレスです。ユーザー情報はトークンに暗号化されます。トークンを受信すると、サーバーはトークンを復号化して、それがどのユーザーであるかを認識します。開発者が手動で追加する必要があります。
  • jwtは単なるクロスドメイン認証スキームです

 

 

負荷分散クラスターのセッションソリューション

序文

Webサイトに負荷分散を使用した後、直面しなければならない重要な問題は、セッションの処理方法です。PHP、Python、Ruby、Javaのいずれであっても、サーバーがセッションの保存に使用されている限り、負荷分散を行うときは、セッションを考慮する必要があります。

 

共有ディレクトリ:

  1. 問題はどこにありますか?どのように対処しますか?

  2. セッションの永続性(ケース:Nginx、Haproxy)

  3. セッションレプリケーション(ケース:Tomcat)

  4. セッション共有(ケース:Memcached、Redis)

 


問題はどこにありますか?

ユーザー側から説明すると、ユーザーが負荷分散エージェントによってバックエンドサーバーAに初めてアクセスしてログインすると、ユーザーのログイン情報はサーバーAに保持されます。ユーザーが再度リクエストを送信すると、サーバーAにリクエストが送信される場合があります。負荷分散ポリシーの影響を受けます。サーバーBなどの別のバックエンドサーバーにプロキシします。このサーバーBにはユーザーのログイン情報がないため、ユーザーは再度ログインする必要があります。これはユーザーにとって耐え難いことです。したがって、負荷分散を実装するときは、セッションの問題を考慮する必要があります。

負荷分散では、セッション処理の場合、通常、次の方法があります。

    • セッションキープ

    • セッションレプリケーション

    • セッション共有

 

1.セッションの保持


セッション保持(セッション保持)は、私たちが目にする最も一般的な用語の1つです。セッション保持と負荷分散により、要求の分散が実行されると、各クライアントはバックエンド上の同じアプリケーションサーバーに固定アクセスできることが保証されます。セッション永続化スキームには、すべての負荷分散に対応する実装があります。そして、これはセッションの問題を解決するための負荷分散レイヤーにあります。

Nginxセッション保持の負荷分散を行います

Nginxの場合、セッション保持の方法を選択して負荷分散を実装できます。nginxのアップストリームは現在、5つの分散方法をサポートしており、そのうち2つの一般的なセッションソリューションであるip_hashとurl_hashがあります。注:後者は公式モジュールではなく、追加のインストールが必要です。

ip_hash()

各リクエストは、アクセスIPのハッシュ結果に従って割り当てられるため、各訪問者はバックエンドサーバーへの固定アクセスを持ち、セッション保持の方法を実現します。

例:

upstream bakend {
   ip_hash;
   server192.168.0.11:80;
   server192.168.0.12:80;
 }

Haproxyはセッション保持の負荷分散を行います

    優れたリバースプロキシおよび負荷分散ソフトウェアとして、Haproxyはセッション保持のためのさまざまな方法も提供します。最も一般的に使用される2つを以下に示します。

送信元アドレスハッシュ(負荷分散はサポートされていません

Haroxyは、ハッシュ計算後にユーザーIPを固定実サーバーに割り当てます(nginxのip hashコマンドと同様)。

配置指令:balancesource

識別にCookieを使用します(明らかに、この安全でない操作は信頼できません

つまり、Haproxyは、ユーザーが初めてアクセスした後にユーザーのブラウザーにCookieを挿入し、ユーザーが次にアクセスしたときに、ブラウザーはこのCookieをHaproxyに持ってきて、Haproxyによる識別を行います。

配置指令:cookie  SESSION_COOKIE  insert indirect nocache

構成例は次のとおりです。

cookie SERVERID insert indirect nocache
server web01 192.168.56.11:8080 check cookie web01
server web02 192.168.56.12:8080 check cookie web02

セッション保持のデメリット:

セッションの保持はセッションの同期の問題を解決するようですが、他にもいくつかの問題があります。

  • 不均衡な負荷:セッション保持を使用しているため、絶対的な負荷分散が保証されないことは明らかです。

  • この問題は完全には解決されていません。バックエンドサーバーがダウンしている場合、このサーバーのセッションは失われ、このサービスリクエストに割り当てられたユーザーは引き続きログインする必要があります。

 


2.セッションレプリケーション

私たちの目標はすべてのサーバーでユーザーのセッションを維持することなので、各アプリケーションサーバーのセッション情報を他のサーバーノードにコピーするだけで十分でしょうか?これは、セッションを処理する2番目の方法であるセッションレプリケーションです。

 セッションレプリケーションはTomcatでサポートされています。セッションレプリケーションを完了するためのIPマルチキャスト(マルチキャスト)に基づいています。Tomcatのセッションレプリケーションは、次の2つのタイプに分けられます。

  • グローバルセッションレプリケーション:Delta Managerを使用して、セッション内の変更された情報をクラスター内の他のすべてのノードにレプリケートします。

  • 非グローバルレプリケーション:レプリケーションにBackup Managerを使用すると、指定されたバックアップノードにセッションがレプリケートされます。

    ただし、ここではセッションレプリケーションのTomcat構成については説明しません。要件がある場合は、主にセッションレプリケーションが大規模なクラスターに適していないため、Tomcatの公式ドキュメントを参照できます。著者の本番環境での実際の事例によると、クラスターが6ノードを超えるとさまざまな問題が発生するため、本番環境での使用はお勧めしません(同期によって遅延が発生する可能性があります

 

3.セッション共有


セッションの保持とセッションのレプリケーションは完全ではないため、セッションを統一された場所に配置して、クラスター内のすべてのノードが1つの場所でセッションにアクセスして問題を解決できるようにしてみませんか。

    セッションはどこに保存されますか?

Sessionの場合、頻繁に使用する必要があります。データベースに保存することもできますが、実際の本番環境では、MemcachedやRedisなどのパフォーマンスの高い分散KVデータに保存することをお勧めします。

 

PHP設定セッション共有

PHPを使用している場合は、おめでとうございます。構成は非常に簡単です。PHPは、2行の構成でセッションをMemcachedまたはRedisに保存できます。もちろん、事前に構成する必要があります。php.iniを変更します。

session.save_handler = memcache
session.save_path = "tcp://192.168.56.11:11211"

Redisを使用してセッション保存する

session.save_handler = redis
session.save_path ="tcp://localhost:6379"

注意:PHP用のmemcacheまたはredisプラグインをインストールすることを忘れないでください。

Tomcatはセッション共有を設定します

MSM(Memcached Session Manager)を使用して、セッションをMemcacheに保存することもできます。Githubアドレスは次のとおりです。https://github.com/magro/memcached-session-managerは現在Tomcat6.x7.xおよび8をサポートしています。 xバージョン。

Redisを使用したい場合は、オープンソースも利用できますが、残念ながら、Tomcat 8.xのバージョンは一時的にサポートされていません:https://github.com/jcoleman/tomcat-redis-session-manager

 

Django設定セッション共有

Djangoでは、セッションはミドルウェアを介して管理されます。アプリケーションでSessionを使用する場合は、settings.pyのMIDDLEWARE_CLASSES変数に「django.contrib.sessions.middleware.SessionMiddleware」を追加する必要があります。Djangoのセッションエンジンは、データベース、キャッシュ、ファイルの3つの場所にセッションを保存できます。

データベースを使用してセッションを保存します(効率的ではありません

データベースでサポートされているセッションを使用する場合は、INSTALLED_APPS設定に「django.contrib.sessions」を追加する必要があります。構成が完了したら、manage.pymigrateを実行してセッションデータを保存するデータベーステーブルをインストールしてください。

キャッシュを使用してセッションを維持する

単純なキャッシュセッションの場合:

SESSION_ENGINEを「django.contrib.sessions.backends.cache」に設定できます。この時点で、セッションデータはキャッシュに直接保存されます。ただし、キャッシュされたデータは永続的でない場合があります。キャッシュがいっぱいになるか、キャッシュサーバーが再起動すると、キャッシュされたデータがクリーンアップされる場合があります。

  データを永続的にキャッシュするには:

SESSION_ENGINEを「django.contrib.sessions.backends.cached_db」に設定できます。その書き込み操作はキャッシュを使用し、キャッシュへの各書き込みはデータベースに再度書き込まれます。読み取りセッションの場合、データがキャッシュにない場合は、データベースから読み取られます。両方のセッションのストレージは非常に高速ですが、単純なキャッシュは永続性を放棄するため高速です。ほとんどの場合、cached_dbバックエンドは十分に高速ですが、パフォーマンスの最後のポイントを絞り込み、セッションデータ損失のリスクを受け入れる必要がある場合は、cached_dbの代わりにキャッシュを使用できます。

ファイルを使用してセッションを保存する

ファイルを使用してセッションを保存することは、共有が難しいため、もはや議論ではありません。PHPは、デフォルトで/ tmpディレクトリにもセッションを保存します。

 

 

Cookie、Session、およびToken
は、Cookieとトークンの検証の違い
です。Cookieにセッションが
必要なのはなぜですか?CSRFトークンの設計が必要ですか?
Cookie、トークン、およびセッションの問題と解決策
負荷分散クラスターでのセッションソリューション
JWTの紹介
Json Webトークン入門チュートリアル

おすすめ

転載: blog.csdn.net/zw764987243/article/details/115033765