什么是session?
在网络中,我们称之为会话控制,用于存储特定用户所需要的属性和配置信息。
为什么要使用session?
http属于无状态的协议,无法保存用户的一些相应状态。即在操作的前后,无法判断是否是同一个用户。部分业务需要有关联性,因此需要使用session技术。
什么是集群?什么是分布式?
集群:一堆机子集中在一起进行管理协助运行。
分布式:中心化带来的主要问题是可靠性,若中心节点宕机则整个系统不可用,分布式除了解决部分中心化问题,也倾向于分散负载,但分布式会带来很多的其他问题,最主要的就是一致性。
常用的分布式session解决方案:
1.基于nginx的ip_hash策略来进行负载均衡,那么相同ip的机子,每一次请求的时候,都会被请求到同一机子上。
优点:
配置简单,不用修改后端的程序代码。
缺点:
容易出现单点故障的情况,导致该服务器上边的session全部丢失。
当我们进行水平扩展的时候,增加服务器会发现session失效。因为hash的定位会丢失。
也容易出现单点负载过高的情况。
2.通过对于tomcat里面的cluster配置进行配置,搭建tomcat的集群配置。以及相应的项目开启distributable配置标签。
让tomcat集群进行自动的session一致。
优点:
不用修改后端代码,可以适合用于所有的负载均衡策略。
即使当某一单点出现了故障也能解决。
缺点:
session进行同步的时候,占用内存和内网的带宽。
而且session的复制会有一定的延迟。当用户量增加的时候,会有较为严重的影响。
3.通过使用Session的集中统一管理
借助一些mysql,redis,mongodb这些数据库来进行处理,将相应的session存入这些地方。
通常会采用这一方案来进行实施。
接下来这个案例主要是通过实操来演示如何进行分布式session处理的:
首先是依赖配置:
这里我使用的springboot版本是1.5.6.RELEASE
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> 复制代码
然后是application.properties配置部分信息:
spring.redis.database=0 spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= # 连接池最大连接数 spring.redis.jedis.pool.max-active=100 spring.redis.jedis.pool.max-wait=-1ms # 连接池中的最大空闲连接 spring.redis.jedis.pool.max-idle=8 # 连接池中的最小空闲连接 spring.redis.jedis.pool.min-idle=0 #session的存储方式 spring.session.store-type=redis 复制代码
最后加入一个配置类:
package com.sise.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.web.http.HeaderHttpSessionStrategy; import org.springframework.session.web.http.HttpSessionStrategy; @Configuration @EnableRedisHttpSession public class RedisSessionConfig { @Bean public HttpSessionStrategy httpSessionStrategy() { return new HeaderHttpSessionStrategy(); } } 复制代码
一段请求接口,用于测试使用:
@RequestMapping(value = "/saveSession") public void saveSession(HttpServletRequest request){ request.getSession().setAttribute("user"+System.currentTimeMillis(),new Date()); System.out.println("session存储成功!"); } 复制代码
通过测试请求该接口之后,再去查看redis里面的情况:
此时session已经被存储在了redis里面了。