spring-boot+spring-session集成
在這個微服務,分布式的時代,很多傳統的實現方案變的不再那麼適用,比如傳統的web服務將session放在內存中的情況,當web服務做水平擴展部署的時候,session共享就成了需要處理的問題。目前有很多成熟的技術可供我們選擇,下麵簡單介紹最近用到的spring-boot+spring-session實現session共享的方案。
spring-boot集成spring-session非常簡單,因為spring-boot為我們完成了非常多的工作。具體集成步驟如下:
一、工程繼承spring-boot-starter-parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
這樣做的好處是我們接下來引入其他依賴包可以不需要考慮版本問題,推薦這樣做,避免自己引入不當導致的兼容性問題。
二、引入spring-session依賴包
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
引入之後,我們要確定我們要將session持久化到哪種介質中了。因為分布式session可以持久化到數據庫、redis、nosql等中,根據存儲方式不同,需要引入不同的jar包和做不同的操作。我們以redis存儲為例。
三、引入redis依賴包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
由於我們使用了spring-boot,所以我們隻需要引入spring-boot-starter-data-redis依賴即可,這樣我們可以很好的利用spring-boot開箱即用以及非常方便的配置優勢。
四、基礎配置
由於我們引入了redis,這樣我們需要在application.properties或者application.yml文件中配置redis連接,使用spring-boot我們可以很方便配置單點redis,哨兵模式,集群模式等,簡單起見我們配置一個單點模式的redis連接並采用連接池
spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=******
spring.redis.pool.max-active=100
spring.redis.pool.max-idle=5
spring.redis.pool.max-wait=60000
完成以上步驟之後,我們隻需要告訴spring開啟redis方式的session存儲即可,這裏有兩種方式可以實現
- 方式1、在配置文件中添加一行配置
spring.session.store-type=redis
- 方式2、在程序啟動類上添加注解
@EnableRedisHttpSession
兩種方式都可以完成開啟spring-session的redis存儲,是不是非常簡單。因為spring-boot的特性,以前很多需要在xml中配置的都可以輕鬆幫我們搞定。
擴展
雖然我們實現了redis方式存儲的分布式session,但是在實際場景中可能還有一些需要優化的地方。
一、修改cookies中sessionId的名字
二、修改session存放在redis中的命名空間
三、修改session超時時間
為什麼要這樣做呢,如果我們有兩套不同係統A和B,cookies中session名稱相同會導致同一個瀏覽器登錄兩個係統會造成相互的幹擾,例如兩個係統中我們存放在session中的用戶信息的鍵值為user。默認情況下cookies中的session名稱為JSESSIONID。當我們登錄A係統後,在同一個瀏覽器下打開B係統,B係統B係統拿到的user實際上並非自己係統的user對象,這樣會造成係統異常;而如果我們A、B係統存放用戶信息的鍵值設置為不相同,例如userA和userB,當我們登錄A係統後在登錄B係統,我們打開瀏覽器調試模式方向兩個係統隻有一個sessionId,因為我們沒有對二者的session名稱以及存儲的命名空間做區分,程序會認為就是自己可用的session。當我們推出B係統,注銷session後。發現B係統的session也失效了,因為在redis中JSESSIONID對應的數據已經被設置過期了。
同理,如果兩個係統想要不同的session過期時間,也存在相同的問題。所以,建議不同係統,session名稱以及存儲的命名空間設置為不同,*當然相同係統的水平擴展實例的情況除外*。
針對命名空間,我們可以在配置文件上添加配置解決
spring.session.redis.namespace=xxxx
如果是注解方式的也可以在注解上設置
@EnableRedisHttpSession(redisNamespace="xxxx")
這樣我們查看redis中就可以看到sping-session存儲的key就變成了我們設置的值。
針對超時時間,注解方式提供了響應的設置
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)
但是配置文件方式並沒有提供響應的直接設置。
我們可以采用javaconfig方式自定義策略來設置超時以及設置cookies名稱,如下我們設置超時時間是1800秒,cookies名為MYSESSIONID
@Bean
public CookieHttpSessionStrategy cookieHttpSessionStrategy(){
CookieHttpSessionStrategy strategy=new CookieHttpSessionStrategy();
DefaultCookieSerializer cookieSerializer=new DefaultCookieSerializer();
cookieSerializer.setCookieName("MYSESSIONID");//cookies名稱
cookieSerializer.setCookieMaxAge(1800);//過期時間(秒)
strategy.setCookieSerializer(cookieSerializer);
return strategy;
}
總結
通過以上步驟,我們就完成了分布式session的集成。相對於傳統的內存方式,分布式session實現能夠更方便水平擴展以及係統維護。對於不想立馬更改係統采用token方式來進行驗證的係統來說是一種簡便、快速、低成本的一種實現思路。
最後更新:2017-08-30 10:32:25