HttpSession是通過Servlet容器創建和管理的,像Tomcat/Jetty都是保存在內存中的。而如果我們把web伺服器搭建成分布式的集群,然後利用LVS或Nginx做負載均衡,那麼來自同一用戶的Http請求將有可能被分發到兩個不同的web站點中去。那麼問題就來了,如何保證不同的web站點能夠共享同一份session數據呢?
最簡單的想法就是把session數據保存到內存以外的一個統一的地方,例如Memcached/Redis等資料庫中。那麼問題又來了,如何替換掉Servlet容器創建和管理HttpSession的實現呢?
(1)設計一個Filter,利用HttpServletRequestWrapper,實現自己的 getSession()方法,接管創建和管理Session數據的工作。spring-session就是通過這樣的思路實現的。
(2)利用Servlet容器提供的插件功能,自定義HttpSession的創建和管理策略,並通過配置的方式替換掉默認的策略。不過這種方式有個缺點,就是需要耦合Tomcat/Jetty等Servlet容器的代碼。這方面其實早就有開源項目了,例如memcached-session-manager,以及tomcat-redis-session-manager。暫時都只支持Tomcat6/Tomcat7。
Spring Session是Spring的項目之一,GitHub地址:https://github.com/spring-projects/spring-session。
Spring Session提供了一套創建和管理Servlet HttpSession的方案。Spring Session提供了集群Session(Clustered Sessions)功能,默認採用外置的Redis來存儲Session數據,以此來解決Session共享的問題。
Springboot集成步驟:
(1)Maven依賴
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
(2)添加@EnableRedisHttpSession來開啟spring session支持,配置如下:
@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
}
(3)Redis配置
spring.redis.host=localhostspring.redis.port=6379測試:
首先我們開啟兩個tomcat服務,埠分別為8080和9090
啟動之後進行訪問測試,首先訪問8080埠的tomcat
{"request Url":"http://localhost:8080/admin/v1/first"}
我們訪問8080埠的sessions,返回:
{"sessionId":"efcc85c0-9ad2-49a6-a38f-9004403776b5","message":"http://localhost:8080/admin/v1/first"}
再訪問9090埠的sessions,返回:
{"sessionId":"efcc85c0-9ad2-49a6-a38f-9004403776b5","message":"http://localhost:8080/admin/v1/first"}
8080與9090兩個伺服器返回結果一樣,實現了session的共享