spring-session实现分布式会话
文章目录
通过spring session实现分布式会话
集群下不会丢失会话 集中管理session
目标
通过spring session实现分布式会话
集群下不会丢失会话 集中管理session
场景
一个Nginx(反向代理,负载均衡) -> 用户服务被部署了3份(tomcat)
默认情况下,使用的session由tomcat的sessionManager提供
在负载均衡下, 用户A的登录会失效 因为其登录的session只存在于其中一个tomcat上
当连接到另一个tomcat时, tomcat发现没找到A的session(sessionId) 会给A新建一个session(同时重写cookie的sessionId)
请求每换了一个tomcat就会发送session新建的操作, 上次的session虽然还在之前的tomcat中, 但凭据(sessionId)已经丢失
解决方案:
- 方案1: nginx的负载策略 ip-hash 可以保证某用户的请求会转发到相同的tomcat
- 方案2: tomcat-cluster可以保证节点间的session共享
- 方案3: 通过第三方session插件替换tomcat自带的sessionManager 如memcached-session-filter,memcached-session-manager
- 方案4: spring-session将session进行集中管理 直接顶替
构建服务
启动redis
|
|
测试redis
|
|
spring boot添加spring session
|
|
spring boot
MyApp.java
|
|
spring session
pom.xml
|
|
RedisSessionConfig.java
|
|
application.properties
|
|
测试
添加测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @RestController public class HelloController { @RequestMapping(value = "hello") public String add(HttpServletRequest req) throws Exception { String k = "count"; int v = 0; HttpSession session = req.getSession(); Object obj = session.getAttribute(k); if(null != obj){ v = (int) obj; } v ++; session.setAttribute(k, v); StringBuilder sb = new StringBuilder("hello-"); sb.append("\n sid-"+session.getId()); sb.append("\n num-"+v); return sb.toString(); } }
程序以8811端口启动 浏览器每次访问 http://127.0.0.1:8822/hello 数字会加1 同时打印了sessionId
修改下application.properties端口为8822 启动第2个程序 同时不关闭上1个程序 访问 http://127.0.0.1:8822/hello 数字是接着上次的数字增加了
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#查看redis的数据 root@cfc7fffb424a:/data# redis-cli -a pwd123 Warning: Using a password with '-a' option on the command line interface may not be safe. 127.0.0.1:6379> keys spring:session* 1) "spring:session:expirations:1554631680000" 2) "spring:session:sessions:90546a74-7d5a-49cb-acba-40a79a078eb1" 3) "spring:session:sessions:expires:90546a74-7d5a-49cb-acba-40a79a078eb1" 127.0.0.1:6379> exit #清空数据 root@cfc7fffb424a:/data# redis-cli -a pwd123 keys "spring:session:*" | xargs redis-cli -a pwd123 del Warning: Using a password with '-a' option on the command line interface may not be safe. Warning: Using a password with '-a' option on the command line interface may not be safe. (integer) 3
此时在浏览器中继续访问
可以发现之前的计数被清空了
另外登录时通常是将UserInfo对象放入session
而session是放在redis中 应注意序列化问题
文章作者 duansheli
上次更新 2019-12-25 (325c7b3)