集群部署的session共享问题

随着业务量的增加,系统开始由单一部署向集群部署演化。那么问题就来了,应用集群需要有一个组件来管理请求的分发,负载均衡就来了。

上面是几款负载均衡的组件,其中最受行业主流青睐的是Nginx。但是,问题又来了,Nginx虽然优点诸多,但是却有一个问题,那就是不能存储session,所以,要想对Nginx后面的应用集群做session共享,我们还要另辟蹊径。

首先从原理分析以下,为什么需要做session共享:首先HTTP是无状态的,不记录用户的行为,所以,对于应用和浏览器来说,每一次都是第一次见面,因对这种情况,提出了cookie和session机制,用来记住浏览器和应用上次见面的情况,但是,这也只是解决了浏览器访问单机部署,如果出现集群部署,就会出现以下情况:

上面提到了nginx支持多种分发策略,如下:

 

通过上面的流程我们可以看出

  1、cookie是以当前域名为cookie为名存储的,再次访问相同域名是会自动带上cookie信息,cookie里存储了JSESSIONID。

  2、session信息是缓存到web应用本地内存中的,同一个cookie名的请求过来,会通过cookie中存放的JSESSIONID来获取上下文中缓存的session信息

  3、出现session失效的原因是,应用1的sessionid给了应用2使用,肯定会失效,但是,如果我们把同一个浏览器的请求都发送到同一个应用上,就会解决失效问题,所以我们开始从nignx分发策略上下手,希望它能把ip是127.0.0.1的客户端上发出的请求都分发给web应用1,把ip是127.0.0.2的客户端上发出的请求都分发给web2,看下nignx的分发策略,好巧,正好ip哈希算法就满足我们的期望。

第一种解决session失效分方法就出现了 ———  配置nignx的分发策略为ip哈希算法

具体设置如下:

 那么我们来考虑,url散列可以吗?

  url散列,只是做相同的URL分发到相同的应用,但是,同一个浏览器可能会有不同请求,还是会有被分发到不同web节点上的可能。

  但是URL散列很适合做图片缓存,统一个图片的操作请求根据图片名做分类分发到同一个节点上做处理(很多秒杀时通过将静态资源放到CDN上面,用户请求时就近请求离用户最近的CDN,CDN时按流量收费的)

 第二种解决session失效的方式是  ——  通过tomcat集群功能做session复制

  session复制时tomcat容器为我们提供的session共享机制,时通过tomcat集群部署来实现的,具体可以参考tomcat官网。

  session复制的底层实现是通过网络通信的组播模式实现的,如下图:(网络中有三种通讯模式:单播、广播、组播)。

  通过配置,将集群中的各个节点服务器分到一个网络组中(图中标红点的),然后组内广播,实现容器中应用缓存信息的相互复制。 

   具体实现图下:

    1、修改tomcat配置文件server.xml中的Cluster节点配置。每个tomcat节点都要做配置。

      参考tomcat官网默认配置即可,路径:https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html

                

    2、修改web.xml配置信息,增加<distributable/>节点

    3、使用这种方式存在一个问题是tomcat间进行所有节点应用缓存的全备份,需要对session信息进行序列化且io读写和全备份都会耗费资源,当节点数逐步增多,例如超过7个以上,那么每个节点之间都要做同步,资源消耗就会很影响性能。

 第三种解决session失效的方式是  ——  通过redis内存数据存储组件做session共享

   通过内存缓存组件代替本地缓存,所以节点在获取session信息的时候都去redis服务器上获取,就做到了一份session,多节点使用,但是使用redis服务器做session共享要考虑redis服务单点故障问题。

   使用springboot实现redis组件做session共享具体操作如下:

  1、pom.xml引入相关starter包 —— spring-boot-starter-data-redis,spring-session-data-redis

   2、添加redis服务器配置

    spring.redis.database=0

    spring.redis.host=127.0.0.1

    spring.redis.port=6379

    spring.redis.password=12333

  3、启动类添加注解:@EnableRedisHttpSession

   4、通过源码可以看到底层实现是通过spring拦截器实现的。

 上面分析了三种解决session失效的方式,总结下:

 

原文地址:https://www.cnblogs.com/tianhaichao/p/12333320.html