一、什么是Session ?
当用户访问时,服务器会为该用户创建一个会话,这个会话的id会放在Cookie存到用户的浏览器,此后用户访问服务器时都会带上这个id,服务器通过该id找到对应的会话,这个会话就是session,session常用于保存登录信息以及其他会话信息等。
二、什么是Session一致性
当只有一台服务器的时候,用户只要不要关掉浏览器或者长时间不操作(session过期),服务器基本能定位到session。
当有多台服务器的时候用户每次请求就不一定能定位到正确的session,
如上图中,如果第一次请求被分配到左边那台服务器,该服务器会为该请求创建一个session,但之后的每次请求都有可能被分配到右边那台服务器,所以之前的session就没法找到。
三、Session一致性解决方案
(一)使用 IP_HASH 配置
在用nginx实现负载均衡的情况下,用户请求时会被分发到任意一台服务器上,所以才导致session定位不到,如果能保证用户的每次请求都能落在同一台服务器上,那session一致性问题就可以解决;
在nginx的配置中就提供了 ip_hash 这个配置,如下图:
使用ip_hash配置后,每次请求都会根据ip的hash结果分配,这样保证每次请求都会落在同一台服务器上面。
缺点:使用ip_hash虽然能解决session一致性的问题,如果某一台服务器挂掉了,那将会丢失掉该台服务器上面的session。
(二)使用缓存存储Session
将session存放在缓存当中,所有服务器的都从这缓存中读取和存储session,这样的话不管请求落在哪台服务器上,都可以定位到session。
1. 安装Redis
(1)下载Redis :
官网下载 https://redis.io/download
或者在linux中执行以下命令
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
(2)解压Redis
tar xzf redis-3.2.9.tar.gz
(3)进入Redis目录下安装
cd redis-3.2.9
make
(4)运行Redis
src/redis-server
如果想让redis在后台运行,则在上面命令后面加上&符号 src/redis-server &
(5)运行客户端并测试
src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
2.Tomcat与Redis整合
依赖包: tomcat-redis-session-manager-master-2.0.0.jar commons-pool2-2.2.jar
jedis-2.5.2.jar
tomcat-redis-session-manager-master-2.0.0.jar 要在github上下载源码,地址是https://github.com/jcoleman/tomcat-redis-session-manager 然后用gradle编译
(1)将上面3个包放进Tomcat服务器的lib下面
(2)配置Tomcat 目录下的 conf/context.xml文件
(3)启动Redis,还有Tomcat
注意事项:要存放在redis中的对象所属的类必须实现 java.io.Serializable 接口,而且要存放的类中包含之其他类的引用,如果该引用也要存储在redis中也必须实现 java.io.Serializable 接口。例如:用户登录场景,我们需要把用户类存到session,然后把session放到redis中,此时的用户类就必须实现 java.io.Serializable ,否则无法跟着session存进缓存中。
除了以上这些方法外还有其他方法可以解决session一致性问题,有兴趣的朋友可以去了解下,例如:将session信息通过cookie存放到浏览器,但是这个会出现安全问题,还有就是用户可能在浏览器禁用cookie,另外一种方法就是将session存放到数据库,其实就跟上面存放在redis差不多,但存放数据库的话数据库操作开销很大。