一伸蚯、Spring Session
在使用Nginx負(fù)載均衡功能的時候妹沙,總會碰到session同步問題处铛。一般Nginx配置的時候會將用戶的請求IP進(jìn)行綁定,對于同一個IP的請求都會轉(zhuǎn)發(fā)到同一臺服務(wù)器幽邓,這樣就會避免session丟失。如果請求來自于同一個局域網(wǎng)火脉,那么他們的出口IP可能是一樣的牵舵,這樣會導(dǎo)致某一臺服務(wù)器處于繁忙狀態(tài)柒啤,而其它服務(wù)器卻處于空閑狀態(tài),這就導(dǎo)致負(fù)載均衡的實際效率不高畸颅。
Spring Session是一個集群會話解決方案担巩,它通過redis、mysql等數(shù)據(jù)庫來實現(xiàn)集群間Session的共享没炒。另外Spring Session并不需要你修改任何業(yè)務(wù)代碼就能無縫集成到Spring框架中涛癌。
二、需要準(zhǔn)備的內(nèi)容
-
一臺Nginx服務(wù)器
我這邊直接使用工作電腦作為Nginx服務(wù)器送火,設(shè)置IP地址為192.168.0.102
拳话。 -
兩臺linux服務(wù)器
設(shè)置IP地址,我這邊分別設(shè)置為192.168.0.107
和192.168.0.109
种吸。 -
Redis服務(wù)
我這邊安裝在192.168.0.107
這臺服務(wù)器中弃衍。由于之前沒有使用過Redis,所以在安裝坚俗、使用的時候遇到了不少問題镜盯。
1、啟動配置文件路徑問題
根據(jù)官方文檔猖败,Redis啟動時最好設(shè)置自己的配置文件速缆,所以我使用了
./redis-server ../../path/to/redis.conf
這條命令,結(jié)果設(shè)置的配置莫名丟失恩闻。最后發(fā)現(xiàn)是路徑問題激涤,因為我使用了相對路徑結(jié)果導(dǎo)致配置文件沒有找到,所以啟動服務(wù)的時候最好使用全路徑判呕。
2倦踢、Redis連接問題
Redis默認(rèn)只綁定了127.0.0.1
,所以只有本機(jī)可以訪問Redis侠草。我們需要在redis.conf
文件中或者通過redis-cli
命令config set bind 192.168.0.107
進(jìn)行配置辱挥。然后還需要設(shè)置連接密碼,同樣可以通過redis.conf
文件或者通過redis-cli
命令config set requirepass 123456
進(jìn)行配置边涕。完成以上配置后晤碘,我們就可以在局域網(wǎng)內(nèi)連接到192.168.0.107
這臺服務(wù)器上的Redis服務(wù)了。
需要注意的是redis.conf
文件配置的內(nèi)容重啟服務(wù)后依然有效功蜓,而redis-cli
配置的內(nèi)容重啟服務(wù)后失效园爷。另外,以上方式只適合開發(fā)環(huán)境式撼。
三童社、Spring Boot配置
根據(jù)Spring的官方教程,我直接在pom.xml
導(dǎo)入以下依賴:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
結(jié)果啟動時發(fā)生了以下異常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.session.SessionAutoConfiguration$ServletSessionRepositoryValidator': Invocation of init method failed; nested exception is org.springframework.boot.autoconfigure.session.SessionRepositoryUnavailableException: No session repository could be auto-configured, check your configuration (session store type is 'redis')
...
...
Caused by: org.springframework.boot.autoconfigure.session.SessionRepositoryUnavailableException: No session repository could be auto-configured, check your configuration (session store type is 'redis')
大概意思是Bean創(chuàng)建失敗著隆,主要是因為session repository
不存在扰楼,如果使用過Spring Data
的人都會知道repository
代表的就是數(shù)據(jù)庫呀癣。經(jīng)過查詢最終發(fā)現(xiàn)少導(dǎo)入了包,完整的包依賴應(yīng)該是如下:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
lettuce-core
用來連接Redis服務(wù)弦赖,如果沒有它就無法創(chuàng)建相應(yīng)的repository
项栏。雖然Spring的官方案例中導(dǎo)入了該包,但是它的教程中并沒有任何提示蹬竖,這對于新手來說有點不太友好沼沈。
除了導(dǎo)入依賴包外還需要在application.properties
進(jìn)行一些配置:
spring.session.store-type=redis
server.servlet.session.timeout=600
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=spring:session
spring.redis.host=192.168.0.107
spring.redis.password=123456
spring.redis.port=6379
四、Nginx負(fù)載均衡設(shè)置
Nginx服務(wù)部署在工作電腦上币厕。
# spring session測試
upstream springsession {
server 192.168.0.107:8080 weight=1;
server 192.168.0.109:8080 weight=1;
}
server {
listen 8001;
server_name springsession;
location /session/ {
proxy_pass http://springsession;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
我這邊將兩臺服務(wù)器的權(quán)重設(shè)置一樣列另,這樣方便測試。
五劈榨、測試結(jié)果
將Spring Session項目分別放到在192.168.0.107
和192.168.0.109
這兩臺服務(wù)器上運(yùn)行访递,然后在工作電腦上通過瀏覽器訪問localhost:8001/session/
:
從上可以看出,雖然兩次請求分配到了兩臺服務(wù)器同辣,但是它們通過Spring Session共享了一個session拷姿。
六、參考資源
https://redis.io/
https://docs.spring.io/spring-session/docs/2.4.3/reference/html5/guides/boot-redis.html