一、什么是Session ?

        当用户访问时,服务器会为该用户创建一个会话,这个会话的id会放在Cookie存到用户的浏览器,此后用户访问服务器时都会带上这个id,服务器通过该id找到对应的会话,这个会话就是session,session常用于保存登录信息以及其他会话信息等。


二、什么是Session一致性

        当只有一台服务器的时候,用户只要不要关掉浏览器或者长时间不操作(session过期),服务器基本能定位到session。

                                          

nginx如何会话保持_数据库

        当有多台服务器的时候用户每次请求就不一定能定位到正确的session,

           

nginx如何会话保持_运维_02

           如上图中,如果第一次请求被分配到左边那台服务器,该服务器会为该请求创建一个session,但之后的每次请求都有可能被分配到右边那台服务器,所以之前的session就没法找到。

 



三、Session一致性解决方案

        (一)使用 IP_HASH 配置

            在用nginx实现负载均衡的情况下,用户请求时会被分发到任意一台服务器上,所以才导致session定位不到,如果能保证用户的每次请求都能落在同一台服务器上,那session一致性问题就可以解决;

            在nginx的配置中就提供了 ip_hash 这个配置,如下图:

                    

nginx如何会话保持_nginx如何会话保持_03

            使用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文件

          

nginx如何会话保持_java_04

                   (3)启动Redis,还有Tomcat

            注意事项:要存放在redis中的对象所属的类必须实现 java.io.Serializable 接口,而且要存放的类中包含之其他类的引用,如果该引用也要存储在redis中也必须实现 java.io.Serializable 接口。例如:用户登录场景,我们需要把用户类存到session,然后把session放到redis中,此时的用户类就必须实现 java.io.Serializable ,否则无法跟着session存进缓存中。

       除了以上这些方法外还有其他方法可以解决session一致性问题,有兴趣的朋友可以去了解下,例如:将session信息通过cookie存放到浏览器,但是这个会出现安全问题,还有就是用户可能在浏览器禁用cookie,另外一种方法就是将session存放到数据库,其实就跟上面存放在redis差不多,但存放数据库的话数据库操作开销很大。