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的一致性。所以不会有很好性能。
优点:不需要进行编码,搭建容易。配置简单。
找到相关的官网配置(如下图):
把官网的这个配置复制到server.xml文件中Engine节点下。比如:
复制之后:
- 修改复制过来的相关配置,比如端口号还有一些ip地址之类的。
- 修改项目文件的web.xml相关的配置文件。如下添加一个标签:
注意这里不是tomcat的web.xml是你项目的web.xml文件。![]()
tomcat+redis实现共享
集成一个第三方组件搭建。
举例:有两种中间件可以做session共享。
- 基于tomcat的:tomcat-redis-session-manager中间件。
- 基于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属性方法就行。他自己就持久化了。如下图有个简单的例子: