![e3bb5664dfe153ca891a68ebd50b3724.png](https://i-blog.csdnimg.cn/blog_migrate/6ab1c434fb06a81e020c61cb4fd38217.jpeg)
首先聊聊session和cookie,session对象存储在服务器端节点内存中,cookie存储在客户端浏览器中。一般是客户端请求服务器,服务器端生成session对象,将session对象存储在jvm内存中,并且在响应头中放入sessionId响应给客户端,客户端收到响应后,将sessionid存储在本地。当浏览器第二次请求时会将本地cookie中存储的seesionId通过请求头的方式传递给服务器,这样服务器和客户端就能保持会话信息啦!如下图
![b81e2a9fc2843be6ecad8f6eb5392dc4.png](https://i-blog.csdnimg.cn/blog_migrate/5e675792feec9643b0bbf3637a4eb375.jpeg)
![6184ced838b0c89b405cb9513fbb2e00.png](https://i-blog.csdnimg.cn/blog_migrate/517ade38a4b31809e20f77b0e3fb21dc.jpeg)
那么为什么会出现分布式session问题呢,为了提高服务器端的负载能力,后台一般将服务器节点做集群,通过ngnix通过轮询的方式转发到目标服务器。打个比方,当浏览器首次访问A服务器生成session对象,然后在访问生成的session对象,如果正好被ngnix转发到了A服务器,那么没问题可以获取到session对象,如果不巧请求被转发到B服务器,由于之前生成的session对象在A服务器,B服务器根本没有生成session对象,很自然访问不到session对象。
知道了问题的存在,那么我们如何解决了,可以通过token令牌代替session解决,或者采用spring-session解决,这里我们选择后一种方式,其实解决思路都是一样的。分布式session不能共享是由于session对象存储在jvm内存中,那么如果共享,答案是将session放入redis中存在,这样不管有多少台应用服务器节点,都能共享redis中存储的session对象。思路很简单,下面给出实现。首先我们引人maven依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies><!--springboot web组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency><!--redis客户端连接工具-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency><!--springboot整合redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!--springboot整合session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
添加配置application.yml
server: port: 8080spring: redis: database: 0host: localhostport: 6379jedis: pool: max-active: 20max-wait: -1max-idle: 10min-idle: 0timeout: 10000
redis连接配置
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)public class SessionConfig {
@Value("${redis.hostname:localhost}")private String hostName;
@Value("${redis.port:6379}")private int port;
@Beanpublic JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(port);
connection.setHostName(hostName);return connection;
}
}
生成session和获取session
![68f6bef690cccd1429a1667939da552e.png](https://i-blog.csdnimg.cn/blog_migrate/298036e3f08919d0de1dfb2b6498cddb.jpeg)
ngnix轮询配置
![524edff90c63eb08738955f7b945d099.png](https://i-blog.csdnimg.cn/blog_migrate/c76d40b2d95e0f88d6dddbe3bf35b7f8.jpeg)
启动ngnix和redis,然后启动2台服务器通过端口区分
8080启动成功
![aeef8dfea02c827709b34cc9d4e22f5b.png](https://i-blog.csdnimg.cn/blog_migrate/fb890351dfd1dc166ebb494d783dd7be.jpeg)
8081启动成功
![81cd7cee392030917369e63063c295bf.png](https://i-blog.csdnimg.cn/blog_migrate/ab702f91a3fe4bdcd8472927cacc30d6.jpeg)
首先生成session对象
![61961af765a342ab260685fcfee0f7e7.png](https://i-blog.csdnimg.cn/blog_migrate/a7e55383590c4b7eb23e20588f1bdba7.png)
然后在二台服务器都能获取到session对象中存储的内容
![dd0d6fd53e3d6c2f2a8f8efd0ce67200.png](https://i-blog.csdnimg.cn/blog_migrate/17824ec659006a1150fa56fa95a9ff43.png)
![fe15d94875d8cd32be3df3087a09ef44.png](https://i-blog.csdnimg.cn/blog_migrate/0bc2d4c7a776c46be48385640226ea26.png)
完结!错误之处,望大佬批评指正!