session共享问题

session共享问题:

在使用服务集群的时候。或者nginx做反向代理分发请求的时候,可能会遇到这个问题。比如说:用户过来了一个登录请求。请求到了服务a,然后登陆成功,服务a这时候保存了用户的登陆状态。但是在用户做其他操作的时候,很可能就把其他的操作的请求分发到了服务b,但是这时候服务b是没有保存用户的登陆信息的。这时候可能就会造成用户重新登陆。

解决方案:

修改nginx配置解决:

这种方案只针对于使用了nginx的项目。把nginx的负载均衡策略改为ip_hash(默认是轮询),这样每次请求就会根据用户的ip进行hash运算,保证了这个用户的每次请求都会指向同一台服务器。
缺点:但是这个有个弊端,就是如果是好多台pc机,共用了一个外网的ip。或者这个节点干脆挂了还是有问题。而且要是凑巧了。会造成服务器压力不均衡的问题。
优点:不需要编码,只需要改nginx.conf配置文件,相对来说很简单。

使用容器的session共享模块

比如搭建的tomcat集群,tomcat本身是有同步session的功能的。登陆tomcat官网,找到tomcat集群页面(https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html)。它实现session主要是基于广播的机制。每次session的变动都会广播通知所有的节点进行信息同步。
缺点:不适合大规模的集群,因为session有个存在时间,而且他的信息是会变动的,这样就需要不停的进行广播,进行所有的节点的同步,维护session的一致性。所以不会有很好性能。
优点:不需要进行编码,搭建容易。配置简单。
session共享问题
session共享问题
找到相关的官网配置(如下图):
session共享问题
把官网的这个配置复制到server.xml文件中Engine节点下。比如:
session共享问题
复制之后:

  1. 修改复制过来的相关配置,比如端口号还有一些ip地址之类的。
  2. 修改项目文件的web.xml相关的配置文件。如下添加一个标签:
    注意这里不是tomcat的web.xml是你项目的web.xml文件。
    session共享问题

tomcat+redis实现共享

集成一个第三方组件搭建。
举例:有两种中间件可以做session共享。

  1. 基于tomcat的:tomcat-redis-session-manager中间件。
  2. 基于Jetty的:jetty-session-redis中间件。
    去github上去搜索可以找到,需要下载一个jar包,然后放在tomcat的lib目录下,再修改下相关的配置即可。

缺点:tomcat-redis-session-manager现在这个插件只支持tomcat6和7。不支持tomcat7以上的版本。
这种基于第三方中间件的,耦合度较高依赖性较高。会有版本问题,不好维护。
优点:因为是基于redis的读写的,性能高,可以实现高并发。可以水平扩展,性能不会降低。

基于spring-session实现(推荐)

利用spring-data-session实现的。由spring-session接管session的数据管理。
优点:对于WEB容器没有入侵,支持多种session的存储,比如redis,DB,MongoDB等。
缺点:不明显。这三种推荐用这中来实现session共享。

springboot集成spring-session有两种方案:

传统模式中:当一个请求进入web容器中,根据请求获取session,如果有就返回,没有就创建一个,然后把sessionID放在response的head中返回。

traditional-session:

有局限性:单机session。他是把session从web容器中抽取出来,作为一个模块。以供分布式或者集群环境下共享。来解决的问题。

spring-session(推荐):

将session从web容器中剥离,存储于独立的存储服务器中。支持多种类型的存储。比如:redis,DB,MongoDB等。session的管理由spring-session进行管理。当请求进入web容器中,根据request获取session时,由spring-session负责从存储服务器中获取session。如果有则返回,没有则创建并持久化到存储服务器中。他是用spring的过滤器来实现的,他会拦截session信息,拦截后持久化。
引入来依赖
添加相关的yml配置
然后再控制层正常使用HttpSession的set属性方法就行。他自己就持久化了。如下图有个简单的例子:

session共享问题
session共享问题

session共享问题