SpringBoot+Redis+Nginx实现负载均衡以及Session缓存共享
SpringBoot实现Session缓存共享
对于权限管理和安全认证,我们首先想到的是Spring Security和Apache Shiro,这两者均能实现用户身份认证和复杂的权限管理功能。但是如果我们只是想实现身份认证(如是否登录、会话是否超时),使用session管理即可满足。
spring-session
HttpSession的实现被Spring Session替换,操作HttpSession等同于操作redis中的数据。
目的:保证不同的web站点能够共享同一份Session数据。
在传统单机web应用中,对于一个浏览器发出的多次请求,WEB服务器则通过这个Sessionid来区分请求。一般使用tomcat等web容器时,用户的session是由单台服务器容器管理。浏览器使用cookie记录sessionId,容器根据sessionId判断用户是否存在会话session。
但是网站主键演变,分布式应用和集群是趋势(提高性能)。此时用户的请求可能被负载分发至不同的服务器,此时传统的web容器管理用户会话session的方式即行不通。除非集群或者分布式web应用能够共享session,尽管tomcat等支持这样做。但是这样存在以下两点问题:
1.需要侵入web容器,提高问题的复杂;
2.web容器之间共享session,集群机器之间势必要交互耦合。
基于这些,必须提供新的可靠的集群分布式/集群session的解决方案,突破traditional-session单机限制(即web容器session方式),spring-session应用而生。
spring-session与session是如何做到无缝切换的
1.自定义个Filter,实现doFilter方法
2.继承 HttpServletRequestWrapper 、HttpServletResponseWrapper 类,重写getSession等相关方法(在这些方法里调用相关的 session存储容器操作类)。
3.在 第一步的doFilter中,new 第二步 自定义的request和response的类。并把它们分别传递到过滤器链。
4.把该filter配置到过滤器链的第一个位置上。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
启动类添加注解配置
@EnableRedisHttpSession
@SpringBootApplication
public class App {
public static void main(String[] args)
{
SpringApplication.run(App.class, args);
}
}
Controller
@RestController
public class UserController {
@RequestMapping(value = "/getSesson")
public List<String> getSesson(HttpSession session, String name)
{
System.out.println(req.getRemoteAddr());
System.out.println(req.getRemoteHost()+":"+req.getRemotePort());
String sessionID = req.getSession().getId();
System.out.println("SessionID-----" + sessionID);
//
session.setAttribute("name", "lyndon-8088");
String testKey = (String)req.getSession().getAttribute("name");
System.out.println("testKey-----" + testKey);
//
List<String> list = new ArrayList<>();
list.add("testKey= " + testKey);
list.add("SessionID= " + sessionID);
list.add("RemoteAddr= " + req.getRemoteAddr());
list.add("RemoteHost+Port= " + req.getRemoteHost() + ":" + req.getRemotePort());
return list;
}
}
Redis查询
[root@localhost ~]# redis-cli -c -h 192.168.236.128 -p 6380 -a 123456
192.168.236.128:6380> keys *
1) "spring:session:sessions:d8eab967-5010-492c-88c8-c049c501909d"
2) "spring:session:expirations:1568471520000"
3) "spring:session:sessions:expires:d8eab967-5010-492c-88c8-c049c501909d"
部署到Nginx配置
start nginx
测试
在同一个浏览器下访问nginx下的服务 http://localhost:8001/getSession
多次请求后,结果返回了不同服务端下的相同Session数据
[“RemoteAddr= 127.0.0.1”,“RemoteHost+Port= 127.0.0.1:63518”,“SessionID= 8f6da055-6723-400e-b019-89a349d6b383”,“testKey= Server-8088”]
[“RemoteAddr= 127.0.0.1”,“RemoteHost+Port= 127.0.0.1:63499”,“SessionID= 8f6da055-6723-400e-b019-89a349d6b383”,“testKey= Server-8087”]
(完)
参考资料
nginx+springboot+redis 负载均衡Session共享的实现
https://www.jianshu.com/p/e2106832f76b
spring-session(一)揭秘
https://www.cnblogs.com/lxyit/p/9672097.html
spring-session负载均衡原理分析
https://www.jianshu.com/p/beaf18704c3c