皆さんこんにちは。私は再びCRUD エンジニアです。最近、同僚の 1 人が突然分散Seesion
イシューに注目し、その後二人で議論しました。今日はSession
分散ナレッジ ポイントを整理したいと思います。
多くのシステムでは、ユーザーのログイン機能がSession
実装されています。クライアントはユーザー名とパスワードを入力してリクエストを送信します。サーバーはリクエストを受信すると、現在対応するものを作成Session
して返します。ブラウザはそれを保存します。クライアントは、他のメソッドを呼び出してサーバーにリクエストを送信するときにそれを実行します。サーバーはリクエストを受信すると、そのリクエストが存在するかどうかを確認し、ユーザーがログインしているかどうかを判断します。Session
JessionId
cookie
JessionId
Session
分散環境では、Session
サーバーが 2 つのサーバー A と B にデプロイされている場合に問題が発生します。
ユーザーがログインすると、リクエストはサーバー A に送信されます。サーバー A はリクエストを作成してSession
返しますJessionId
。
ユーザーが個人情報を取得すると、リクエストはサーバー B に送信されますが、リクエストに含まれる対応する情報はJesssionId
サーバー B では見つかりませSession
ん。
このとき、サーバー B はクライアントに例外リマインダーを返します (ユーザーはログインしていません)。クライアントが戻り値を受け取ると、ユーザーは再びログイン インターフェイスにリダイレクトされたことがわかります。
次に、分散環境でSession
一貫性を実現する方法を見てみましょう。
1. クライアントストレージ
Session
分散環境では、クライアントからの複数のリクエストが複数のサーバーに到達する可能性があるため、戦略を変更して情報をクライアントに直接保存できますか?
答えはもちろん「はい」です。サーバーはSession
情報をサーバーに直接保存するcookie
ため、Session
サーバーのcookie
一貫性が確保されます。ただし、これはお勧めしません。一部の情報をサーバーに保存することはデータ セキュリティのリスクを引き起こす可能性があるためです。この情報はクライアントに公開されるため、重大なセキュリティ リスクが生じます。
欠点がある
- システムセキュリティの問題
- Cookieにはデータ型とデータサイズに制限があります
2. セッションコピー
サーバー A をSession
サーバー B にコピーし、Session
サーバー B をサーバー A にコピーして、2 つのサーバーのSession
整合性を保ちます。他の Web コンテナと同様にtomcat
、これらはすべてSession
レプリケーション機能をサポートしており、同じ LAN 内で 1 つのサーバーがSession
他のサーバーにブロードキャストします。
欠点がある
- 同じネットワーク セグメント内にサーバーが多すぎる場合、各サーバーがセッションをコピーするため、サーバー メモリが無駄に消費されます。
3. セッションの持続性
サーバーのリバース プロキシを使用してNginx
サーバー A とサーバー B をプロキシし、ip_hash
負荷戦略を使用してクライアントとサーバーをバインドします。つまり、クライアント A は初めてサーバー B にアクセスするため、2 回目のアクセスはサーバー B にも送信される必要があるため、不整合の問題は発生しませんSession
。
欠点がある
- サーバー A がダウンすると、クライアント A とクライアント B が
Session
失われ、クライアント A とクライアント B からのリクエストはすべて失敗します。
4. セッションの一元管理
この方法はすべてのサーバーをSession
均一に管理するもので、redis
他の高性能サーバーを使用して一元管理することもできSession
、Spring ではspirng-session
この方法で処理されるSession
一貫性の問題を公式に提供しています。これは、現在多くの企業で使用されている分散Session
ソリューションでもあります。
春季セッション実戦
Spring
Session
配布に対処するためのソリューションを提供しますSpring Session
。Spring Session
ユーザーセッションを管理するための API と実装を提供します。
Spring Session
redis
、 、などの一般的に使用されるリポジトリのサポートが提供されmongodb
、との透過的な統合が提供されます。つまり、開発者は、サポートされている実装を使用して実装を切り替えることができます。mysql
Spring Session
HttpSession
Spring Session
HttpSession
インターネット上でSpring Session
実装フローチャートを見つけて、パッケージングのリクエストとレスポンスを変更するためのフィルター
Spring Session
を追加しましたSessionRepositoryFilter
。パッケージ化されたリクエストは、メソッドSessionRepositoryRequestWrapper
を呼び出すgetSession()
ときに実際にSpring Session
実装されますSession
。
Spring Session
使い方は非常に簡単で、関連する依存関係を追加した後は、HttpSession
直接操作するだけで効果を得ることができます。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
yml
spring:
session:
# session 失效时间(分钟)
timeout: 86400
# session 使用redis存储
store-type: redis
# redis 配置
redis:
# redis 端口号
port: 6379
# redis 服务器地址
host: localhost
# redis库
database: 0
# redis 密码
password: 123456
セッションを使用する
public String test( HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("key_big_handsome","value:it is me");
return session.getAttribute("key_big_handsome").toString();
}
このメソッドを実行した後、redis を確認します。
- 最初のものは、
Session
Redis で有効期限を表すために使用されます。この kv には有用なデータは保存されず、Session
有効期限を表すために設定されているだけです。このキーRedis
の有効期限がSession
有効期限間隔になります。 Session
このIDを格納する 2 番目のものは、Set
一種のRedis
データ構造です。このキーの最後の 1681633260000 値は、次の 1 分にロールされたセッション有効期限の瞬間に基づいて計算されたタイムスタンプです。- 3 番目は、有効期限間隔、最新アクセス時刻など
Session
の詳細情報を保存するために使用されます。Session
attributes
Spring Session
spring:session:expirations:
その中にはスケジュールされたタスクがあり、対応する整数タイムスタンプの有効期限を 1 分ごとにクエリしSessionId
、これに再度アクセスしてSessionId
、キーの有効期限イベント、spring:session:sessions:expires:SessionId
つまり有効期限イベントRedis
を生成できるようにします。タイムリーに。Session