您的位置 首页 > 数码极客

分布式session 分布式数据库…

平常做的项目都是在一台应用系统,并且所有的操作都在一台Tomcat服务器上,并不会引发Session共享的问题,所以并不会对我们的系统产生影响,但是当我们部署多个微服务的时候,再搭配Nginx进行负载均衡时,如果不处理分布式Session问题,我们在系统中访问不同功能时就会频繁出现用户登录的操作。

图解分析原因:

前提:用户登录功能和图中的商品订单模块、秒杀抢购模块属于单独的微服务模块

用户登录成功后想要访问图中其他两个模块的功能时,由于Nginx使用默认负载均衡策略(轮询),这时请求会按照时间顺序逐一分发到后端应用上,也就是说用户在Tomcat1上登录成功之后,用户的信息放在Tomcat1的Session里,过了一会,用户想要进行秒杀活动的功能操作,请求又被Nginx分发到了Tomcat2,而这时的Tomcat2上的Session里还没有用户信息,于是就是出现让用户重新登录的情况,在微服务分布式项目中,不同的功能模块必然会被分列成各自的微服务,假设访问一个功能都需要重新登录一次,用户的体验必然会大幅度下降!

那如何来解决分布式Session问题呢?

一、解决方案列举

1. Session复制

优点:

  • 无需修改代码,只需要修改Tomcat配置

缺点:

  • Session同步传输占用内网宽带
  • 多台Tomcat同步性能指数级下降
  • Session占用内存,无法有效水平扩展

2. 前端存储

优点:

  • 不占用服务器内存

缺点:

  • 存在安全风险
  • 数据大小受cookie限制
  • 占用外网宽带

3. Session粘滞

优点:

  • 无需修改代码
  • 服务端可以水平扩展

缺点:

  • 增加新机器,会重新Hash,导致重新登录
  • 应用重新启动后,需要重新登录

4. 后端集中存储

优点:

  • 安全
  • 容易水平扩展

优点:

  • 增加复杂度
  • 需要修改代码

二、Java代码实现解决分布式Session

1. SpringSession - Redis解决分布式Session

添加依赖

<!--Redis--> <dependency> <groupId>org.S;/groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--commons-pools2 对象池依赖--> <dependency> <groupId>org.a;/groupId> <artifactId>commons-pool2</artifactId> </dependency> <!--spring session 依赖--> <dependency> <groupId>org.;/groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>

添加Redis配置

## Redis配置 spring: redis: # 服务器地址 host: localhost # 端口 port: 6379 # 数据库 database: 0 # 超时时间 connect-timeout: 10000ms lettuce: pool: # 最大连接数 max-active: 8 # 最大连接阻塞等待时间 默认 -1 max-wait: 10000ms # 最大空闲时间 默认8 max-idle: 200 # 最小空闲连接 默认8 min-idle: 5

业务逻辑实现

/** * 登录功能 * @param loginVo * @return */ @Override public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) { String username = loginVo.getUserName(); String password = loginVo.getPassword(); User user = u(username); if (user == null){ throw new GlobalException); } //判断密码是否正确 if (!MDU(password,u()).equal())){ throw new GlobalException); } //使用UUID生成字符串代替Cookie String ticket = UUIDU(); reque().setAttribute(ticket,user); CookieU(request,response,"userTicket",ticket); return Re(); }

视图控制层

/** * 跳转商品列表 * @param session * @param model * @return */ @RequestMapping("/toList") public String toList(HttpSession session, Model model,@CookieValue("userTicket")String ticket){ if (ticket)){ return "login"; } User user = (User) (ticket); if (user == null){ return "login"; } model.addAttribute("user",user); return "goodsList"; }

登录测试

打开Redis管理软件发现Session信息已经添加到Redis中了

2. Redis解决分布式Session

导入依赖

<!--Redis--> <dependency> <groupId>org.s;/groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--commons-pools2 对象池依赖--> <dependency> <groupId>org.a;/groupId> <artifactId>commons-pool2</artifactId> </dependency>

Redis配置参考 【SpringSession - Redis解决分布式Session】

业务逻辑层

@Override public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) { String username = loginVo.getUserName(); String password = loginVo.getPassword(); User user = u(username); if (user == null){ throw new GlobalException); } //判断密码是否正确 if (!MDU(password,u()).equal())){ throw new GlobalException); } //成功Cookie String ticket = UUIDU(); //将用户信息存入到redis中 redi().set("userTicket",ticket); redi().set("user:"+ticket,user); //reque().setAttribute(ticket,user); CookieU(request,response,"userTicket",ticket); return Re(); } /** * 根据cookie获取cookie * @param ticket * @return */ @Override public User getUserByByCookie(String ticket,HttpServletRequest request,HttpServletResponse response) { if (ticket)){ return null; } User user = (User) redi().get("user:" + ticket); if (user == null){ CookieU(request,response,"userTicket",ticket); } return user; }

视图控制层

/** * 跳转商品列表 * @param session * @param model * @return */ @RequestMapping("/toList") public String toList(HttpSession session, Model model,HttpServletRequest request,HttpServletResponse response){ String ticket = (String) redi().get("userTicket"); if (ticket)){ return "login"; } //User user = (User) (ticket); User user = u(ticket, request, response); if (user == null){ return "login"; } model.addAttribute("user",user); return "goodsList"; }

测试成功

查看Redis管理工具

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“分布式session,分布式数据库,分布式session解决方案,spring,分布式session,分布式session的几种实现方式”边界阅读