Springboot Session共享實現(xiàn)原理及代碼實例
在傳統(tǒng)的單服務架構中,一般來說,只有一個服務器,那么不存在 Session
共享問題,但是在分布式/集群項目中,Session 共享則是一個必須面對的問題,先看一個簡單的架構圖:

在這樣的架構中,會出現(xiàn)一些單服務中不存在的問題,例如客戶端發(fā)起一個請求,這個請求到達 Nginx 上之后,被
Nginx 轉發(fā)到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份數(shù)據(jù),下次又來一個請求,這個請求被轉發(fā)到 Tomcat
B 上,此時再去 Session中獲取數(shù)據(jù),發(fā)現(xiàn)沒有之前的數(shù)據(jù)。對于這一類問題的解決,思路很簡單,就是將各個服務之間需要共享的數(shù)據(jù),保存到一個公共的地方(主流方案就是 Redis):

1 實戰(zhàn)
1.1 創(chuàng)建工程
首先 創(chuàng)建一個 Spring Boot 工程,引入 Web、Spring Session 以及 Redis:

創(chuàng)建成功之后,pom.xml 文件如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
注意:
這里我使用的 Spring Boot 版本是 2.1.4 ,如果使用當前最新版 Spring Boot2.1.5的話,除了上面這些依賴之外,需要額外添加 Spring Security 依賴(其他操作不受影響,僅僅只是多了一個依賴,當然也多了 Spring Security 的一些默認認證流程)。
1.2 配置 Redis
spring.redis.host=192.168.66.128
spring.redis.port=6379
spring.redis.password=123
spring.redis.database=0
1.3 使用
配置完成后 ,就可以使用 Spring Session 了,其實就是使用普通的 HttpSession ,其他的 Session 同步到 Redis 等操作,框架已經自動幫你完成了:
@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/set")
public String set(HttpSession session) {
session.setAttribute("user", "javaboy");
return String.valueOf(port);
}
@GetMapping("/get")
public String get(HttpSession session) {
return session.getAttribute("user") + ":" + port;
}
}
考慮到一會 Spring Boot 將以集群的方式啟動 ,為了獲取每一個請求到底是哪一個 Spring Boot 提供的服務,需要在每次請求時返回當前服務的端口號,因此這里我注入了 server.port 。
接下來 ,項目打包:

打包之后,啟動項目的兩個實例:
java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080
java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081
然后先訪問 localhost:8080/set 向 8080 這個服務的 Session 中保存一個變量,訪問完成后,數(shù)據(jù)就已經自動同步到 Redis 中 了 :

然后,再調用 localhost:8081/get 接口,就可以獲取到 8080 服務的 session 中的數(shù)據(jù):

此時關于 session 共享的配置就已經全部完成了,session 共享的效果我們已經看到了,但是每次訪問都是我自己手動切換服務實例,因此,接下來我們來引入 Nginx ,實現(xiàn)服務實例自動切換。
1.4 引入 Nginx
很簡單,進入 Nginx 的安裝目錄的 conf 目錄下(默認是在 /usr/local/nginx/conf),編輯 nginx.conf 文件:

在這段配置中:
- upstream 表示配置上游服務器
- javaboy.org 表示服務器集群的名字,這個可以隨意取名字
- upstream 里邊配置的是一個個的單獨服務
- weight 表示服務的權重,意味者將有多少比例的請求從 Nginx 上轉發(fā)到該服務上
- location 中的 proxy_pass 表示請求轉發(fā)的地址,/ 表示攔截到所有的請求,轉發(fā)轉發(fā)到剛剛配置好的服務集群中
- proxy_redirect 表示設置當發(fā)生重定向請求時,nginx 自動修正響應頭數(shù)據(jù)(默認是 Tomcat 返回重定向,此時重定向的地址是 Tomcat 的地址,我們需要將之修改使之成為 Nginx 的地址)。
配置完成后,將本地的 Spring Boot 打包好的 jar 上傳到 Linux ,然后在 Linux 上分別啟動兩個 Spring Boot 實例:
nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080 & nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081 &
其中
- nohup 表示當終端關閉時,Spring Boot 不要停止運行
- & 表示讓 Spring Boot 在后臺啟動
配置完成后,重啟 Nginx:
/usr/local/nginx/sbin/nginx -s reload
Nginx 啟動成功后,我們首先手動清除 Redis 上的數(shù)據(jù),然后訪問 192.168.66.128/set 表示向 session 中保存數(shù)據(jù),這個請求首先會到達 Nginx 上,再由 Nginx 轉發(fā)給某一個 Spring Boot 實例:

如上,表示端口為 8081 的 Spring Boot 處理了這個 /set 請求,再訪問 /get 請求:

可以看到,/get 請求是被端口為 8080 的服務所處理的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- 淺談Spring Session工作原理
- SpringBoot+SpringSession+Redis實現(xiàn)session共享及唯一登錄示例
- SpringCloud Feign轉發(fā)請求頭(防止session失效)的解決方案
- springboot中的springSession的存儲和獲取實現(xiàn)
- 多個SpringBoot項目采用redis實現(xiàn)Session共享功能
- SpringBoot 如何實現(xiàn)Session共享
- Springboot中登錄后關于cookie和session攔截問題的案例分析
- SpringBoot中實現(xiàn)分布式的Session共享的詳細教程
- spring-redis-session 自定義 key 和過期時間
- SpringBoot2.x 整合Spring-Session實現(xiàn)Session共享功能
- Spring Session的使用示例
相關文章
java中實現(xiàn)map與對象相互轉換的幾種實現(xiàn)
這篇文章主要介紹了java中實現(xiàn)map與對象相互轉換的幾種實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
RabbitMQ高級應用之消費端限流策略basicQos詳解
這篇文章主要介紹了RabbitMQ高級應用之消費端限流策略basicQos詳解,高并發(fā)情況下,隊列里面一瞬間就就積累了上萬條數(shù)據(jù),但是消費者無法同時處理這么多請求,這種場景下我們就需要對消費端進行限流,需要的朋友可以參考下2023-08-08
SpringBoot中的@ConditionalOnMissingBean注解使用詳解
這篇文章主要介紹了SpringBoot中的@ConditionalOnMissingBean注解使用詳解,@ConditionalOnMissingBean作用在@Bean定義上,也就是說在容器加載它作用的Bean時,檢查容器中是否存在目標類型,需要的朋友可以參考下2024-01-01
詳談Java中instanceof和isInstance的區(qū)別
下面小編就為大家?guī)硪黄斦凧ava中instanceof和isInstance的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01
基于Spring Boot應用ApplicationEvent案例場景
這篇文章主要介紹了基于Spring Boot應用ApplicationEvent,利用Spring的機制發(fā)布ApplicationEvent和監(jiān)聽ApplicationEvent,需要的朋友可以參考下2023-03-03
Java利用openoffice將doc、docx轉為pdf實例代碼
這篇文章主要介紹了Java利用openoffice將doc、docx轉為pdf實例代碼,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-01-01

