redis 集群 +spring-session 实现 session 共享

1. 问题背景

1.1. 问题描述

大连大众 MES 项目采用 ngnix 负载均衡,并搭配 redis 集群来管理两台应用服务器,并采用 sticky 模块在一定程度上实现了会话保持。
但是当其中一台服务器宕机,请求自动切换到另一台服务器时,被强制重新登录,对现场使用很大影响(包括电视无纸化展示,web 端操作等等)。

1.2. 问题分析

Sticky 是 nginx 的一个模块,它是基于 cookie 的一种 nginx 的负载均衡解决方案,通过分发和识别 cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为 route。但是当服务器宕机后,这种方式便行不通了。
经百度及咨询同事,决定通过 spring-session 将 session 存储到 redis,实现 session 共享,来解决此问题。

2. 问题处理

2.1. 改造项目(这里只贴出 spring-session 配置项)

2.1.1. 导入依赖

image.png

2.1.2. 增加 spring-session.xml 配置

image.png

2.1.3. 配置 web.xml

image.png
此处需要注意,若项目上同时使用了 spring-session 和 spring-security,这里的 filter 一定要放在 SpringSecurity filter 的前面,否则不会生效。

2.2. 测试

1、访问服务器,使用RedisDesktopManager查看 redis 中存储的 session
image.png
2、观察后台日志,看请求落在哪台服务器上,并停掉该服务器,再进行访问,不需要重新登录,可以继续使用系统。

3. 问题总结和分析

现在很多的服务器都采用分布式集群的方式进行部署,一个 Web 应用,可能部署在几台不同的服务器上,通过 LVS 或者 Nginx 等进行负载均衡,此时来自同一用户的 Http 请求将有可能被分发到不同的 web 站点中去(如:第一次分配到 A 站点,第二次可能分配到 B 站点)。这种情况都可以使用 spring-session 来实现 session 共享。