Spring Boot 2 + Redis 處理 Session 共享

Spring Boot 2 + Redis 處理 Session 共享

 

〇、背景

Web 開發中,通過 Session 在服務端記錄用戶狀態是很常見的操作。對於 Web 開發中 Session、Cookie 等概念請參考《Session 機制詳解》。但是 Session 的機制對於單機應用是沒問題的,但是對於集羣環境,由於在將請求分配到另一臺服務器時,新的服務器無法通過瀏覽器傳入的 Cookie 值取到 Session,所以導致所有基於 Session 的操作都會失敗,如:登錄狀態。

本文通過搭建一個非常簡易的集羣環境,來演示 Session 機制在集羣環境中存在的問題,並通過 Redis 進行 Session 共享來解決該問題。

一、問題再現

1、測試環境

(1)App Server

使用 Spring Boot 2 寫一個簡單的 Web 應用,提供兩個鏈接:

Spring Boot 2 + Redis 處理 Session 共享

 

Controller 部分代碼如下:

@RestController
public class TestController {
 @GetMapping("/set-session")
 public Object writeSession(String sessionVal, HttpSession httpSession) {
 System.out.println("Param 'sessionVal' = " + sessionVal);
 httpSession.setAttribute("sessionVal", sessionVal);
 return sessionVal;
 }
 @GetMapping("/get-session")
 public Object readSession(HttpSession httpSession) {
 Object obj = httpSession.getAttribute("sessionVal");
 System.out.println("'sessionVal' in Session = " + obj);
 return obj;
 }
}

單機測試通過。

(2)通過 Nginx 做負載均衡

分別在 9001 和 9002 兩個端口啓動 App Server,然後通過 Nginx 配置負載均衡,配置如下:

http {
 upstream app_server {
 server 127.0.0.1:9001;
 server 127.0.0.1:9002;
 }
 server {
 listen 9000;
 location / {
 proxy_pass http://app_server;
 }
 }
}

測試失敗。

二、原因分析

主要是因爲原來 A 服務器將其 Session 的標識 Cookie_for_Session_A 放入瀏覽器 Cookie,當下一次請求被分配到 B 服務器,B 服務器無法通過 Cookie_for_Session_A 獲取到對應的 Session,導致失敗。

解決的思路,主要是引入三方服務器,將 Session 保存到三方服務器,A、B 服務器共享三方服務器中的 Session 數據。

三、解決方案

引入 Redis 作爲三方服務器存儲 Session 數據。

1、引入 Redis 相關庫

dependencies {
 implementation('org.springframework.boot:spring-boot-starter-web')
 implementation('org.springframework.boot:spring-boot-starter-data-redis')
 // https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis
 compile group: 'org.springframework.session', name: 'spring-session-data-redis', version: '2.1.2.RELEASE'
}

2、配置 Redis 連接

application.yml,這裏爲了演示清晰,只做了最簡配置,正式使用請調整相關參數

spring:
 redis:
 host: 127.0.0.1
 port: 6379

3、開啓配置

創建一個配置類 SessionConfig,類名隨意。

關鍵是兩個註解:

@Configuration

@EnableRedisHttpSession

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

4、打包、運行測試

執行 Gradle 的 bootJar 任務,然後按照前面的方式,分別在 9001 和 9002 端口運行 jar 包:

java -jar redis-session.jar --server.port=9001
java -jar redis-session.jar --server.port=9002

測試通過。

如果你想學好JAVA這門技術,也想在IT行業拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,7個月後,進入名企拿高薪。我們的課程內容有:Java工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點。如果你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優勢的,想進阿里面試但擔心面試不過的,你都可以來,羣內分享很多資料  自己進去拿就可以的  羣號爲:728821520

複製鏈接直接加也可以的:點擊鏈接加入羣聊【JAVA架構交流羣】:https://jq.qq.com/?_wv=1027&k=5AY1Nct

注:加羣要求

1、具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶着大家全面、科學地建立自己的技術體系和技術認知!
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章