分布式session一致性问题——5种解决方案!

目录

什么是Session

那么Session为什么会不一致呢?

Session一致性解决方案

方案一:客户端存储

方案二:session复制(Tomcat自带该功能)

方案三:session绑定:

方案四:后端统一集中存储

方案五:基于redis存储session方案(推荐)​

最靠谱的分布式Session解决方案(基于令牌(Token))

什么是Session

​ session 是一种服务端的会话机制。(被称为域对象)作为范围是一次会话的范围。

​ 服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。

​ Web开发中,web-server可以自动为同一个浏览器的访问用户自动创建session,提供数据存储功能。最常见的,会把用户的登录信息、用户信息存储在session中,以保持登录状态。

那么Session为什么会不一致呢?

​        在基于请求与响应的HTTP通讯中,当第一次请求来时,服务器端会接受到客户端请求,会创建一个session,使用响应头返回sessionid给客户端。浏览器获取到sessionid后会保存到本地cookie中。

当第二次请求来时,客户端会读取本地的sessionid,存放在请求头中,服务端在请求头中获取对象的sessionid在本地session内存中查询。

但是session属于会话机制,当当先会话结束时,session就会被销毁,并且web程序会为每一次不同的会话创建不同的session,所以在分布式场景下,即使是调用同一个方法执行同样的代码,但是他们的服务器不同,自然web程序不同,整个上下文对象也不同,理所当然session也是不同的。

Session一致性解决方案

方案一:客户端存储

直接将信息存储在cookie中
cookie是存储在客户端上的一小段数据,客户端通过http协议和服务器进行cookie交互,通常用来存储一些不敏感信息

优点

  • 不需要服务器存储session,节省服务端资源。

缺点

  • 都是缺点,这只是一种解决问题的思路。
  • 数据存储在客户端,存在安全隐患,容易泄露。
  • cookie存储大小为4K,不能存储大量信息、类型存在限制
  • 数据存储在cookie中,如果一次请求cookie过大,会给网络增加更大的开销

方案二:session复制(Tomcat自带该功能)

        

session复制是小型企业应用使用较多的一种服务器集群session管理机制,在真正的开发使用的并不是很多,通过对web服务器(例如Tomcat)进行搭建集群。

优点

  • 服务器之间的session信息都是同步的,任何一台服务器宕机的时候不会影响另外服务器中session的状态,配置相对简单
  • Tomcat内部已经支持分布式架构开发管理机制,可以对tomcat修改配置来支持session复制,在集群中的几台服务器之间同步session对象,使每台服务器上都保存了所有用户的session信息,这样任何一台本机宕机都不会导致session数据的丢失,而服务器使用session时,也只需要在本机获取即可

缺点

  • session同步的原理是在同一个局域网里面通过发送广播来异步同步session的,一旦服务器多了,并发上来了,session需要同步的数据量就大了,需要将其他服务器上的session全部同步到本服务器上,会带来一定的网路开销,在用户量特别大的时候,会出现内存不足的情况

步骤:

1.tomcat中server.xml直接配置

<!-- 第1步:修改server.xml,在Host节点下添加如下Cluster节点 -->
<!-- 用于Session复制 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
    <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true" />
    <Channel className="org.apache.catalina.tribes.group.GroupChannel">
        <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" 
                    port="45564" frequency="500" dropTime="3000" />
        <!-- 这里如果启动出现异常,则可以尝试把address中的"auto"改为"localhost" -->
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" 
                  autoBind="100" selectorTimeout="5000" maxThreads="6" />
        <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
            <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
        </Sender>
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
        <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor" />
    </Channel>
    <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter="" />
    <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />
    <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" 
              deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false" />
    <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>

2 修改web.xml

  web.xml中需加入<distributable/> 以支持集群。

方案三:session绑定:

Nginx介绍
Nginx是一款自由的、开源的、高性能的http服务器和反向代理服务器

Nginx能做什么
反向代理、负载均衡、http服务器(动静代理)、正向代理

如何使用nginx进行session绑定
我们利用nginx的反向代理和负载均衡,之前是客户端会被分配到其中一台服务器进行处理,具体分配到哪台服务器进行处理还得看服务器的负载均衡算法(轮询、随机、ip-hash、权重等),但是我们可以基于nginx的ip-hash策略,可以对客户端和服务器进行绑定,同一个客户端就只能访问该服务器,无论客户端发送多少次请求都被同一个服务器处理

在nginx安装目录下的conf目录中的nginx.conf文件

upstream aaa {
	Ip_hash;
	server 39.105.59.4:8080;
	Server 39.105.59.4:8081;
}
server {
	listen 80;
	server_name www.wanyingjing.cn;
	#root /usr/local/nginx/html;
	#index index.html index.htm;
	location / {
		proxy_pass http:39.105.59.4;
		index index.html index.htm;
	}
}

缺点

  • 容易造成单点故障,如果有一台服务器宕机,那么该台服务器上的session信息将会丢失
  • 前端不能有负载均衡,如果有,session绑定将会出问题
  • 失去了Nginx负载均衡的初心

优点

  • 配置简单

方案四:后端统一集中存储

思路:将session存储在web-server后端的存储层,数据库或者缓存

优点

  • 没有安全隐患
  • 可以水平扩展,数据库/缓存水平切分即可
  • web-server重启或者扩容都不会有session丢失

不足:增加了一次网络调用,并且需要修改应用代码

对于db存储还是cache,个人推荐后者:session读取的频率会很高,数据库压力会比较大。如果有session高可用需求,cache可以做高可用,但大部分情况下session可以丢失,一般也不需要考虑高可用。

方案五:基于redis存储session方案(推荐)

优点

  • 这是企业中使用的最多的一种方式
  • spring为我们封装好了spring-session,直接引入依赖即可
  • 数据保存在redis中,无缝接入,不存在任何安全隐患
  • redis自身可做集群,搭建主从,同时方便管理

缺点

  • 多了一次网络调用,web容器需要向redis访问

最靠谱的分布式Session解决方案(基于令牌(Token))

基于令牌(Token)方式实现Session解决方案,因为Session本身就是分布式共享连接。

将生成的Token 存入到Redis中。

猜你喜欢

转载自blog.csdn.net/zhangkaixuan456/article/details/109002134
今日推荐