? ? ? ? 在實際項目中,前臺代碼部署在nginx中,后臺服務內嵌了tomcat運行在不同的節點中,常見的架構如下:
? ? ? ? 在上述架構中,nginx轉發前臺請求,第一次登錄后,將用戶登錄信息寫入到一臺服務session中(假設為A節點),再次請求后,假設nginx轉發到了B節點,B服務節點中沒有session用戶登錄信息,此時還需要登錄,session在服務集群內不可用,不符合預期,示例代碼如下:
package com.gingko.session.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;@RestController
@RequestMapping("/login")
public class LoginController {@GetMapping("/toLogin")public String toLogin(@RequestParam String userName, @RequestParam String password,HttpSession httpSession) {//校驗用戶名密碼...//用戶名加入sessionhttpSession.setAttribute("userName",userName);return "登錄成功";}@GetMapping("/getLoginUser")public String getLoginUser(HttpSession httpSession) {return "session獲取的值是:" + httpSession.getAttribute("userName") ;}
}
? ? ? ? 基于上述的代碼測試效果如下(后臺啟動了2個服務,端口分別是8081和8082),從下圖中可以看出8081登錄后,訪問8082時獲取不到登錄信息。
?
????????分布式session解決方案有很多,本文闡述【Session集中存儲】的解決方案,即將session集中存儲到某個地方,本文演示存儲到redis中,架構示意圖如下:
? ? ? ? 代碼架構引入redis和spring session,示例代碼如下:
? ? ? ? 1、引入?redis和spring session依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.gingko</groupId><artifactId>distributed-session</artifactId><version>0.0.1-SNAPSHOT</version><name>distributed-session</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version></properties><dependencies><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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.gingko.session.DistributedSessionApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
? ? ? ? 2、修改配置,增加對redis和session的支持
# 應用服務 WEB 訪問端口
server:port: 8081
spring:redis:host: 192.168.136.130 #redisport: 6379database: 0session:store-type: redis #session 存儲方式timeout: 1800 #session 過期時間 30分鐘
? ? ? ? 3、啟動2個應用測試(端口8081和8082),從下圖中可以看出8081登錄后,redis緩存中增加了session信息,8082也可以獲取到登錄信息,符合預期。