负载均衡集群中的session解决方案

Posted java全栈技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了负载均衡集群中的session解决方案相关的知识,希望对你有一定的参考价值。

1.什么是Session

1.1 什么是Session

用户使用网站的服务,基本上需要浏览器与Web服务器的多次交互。HTTP协议本身是无状态的,需要基于HTTP协议支持会话状态(Session State)的机制。而这样的机制应该可以使Web服务器从多次单独的HTTP请求中看到"会话",也就是知道哪些请求来自哪个会话的。
具体实现方式为:在会话开始时,分配一个唯一的会话标识(SessionId),通过Cookie把这个标识告诉浏览器,以后每次请求的时候,浏览器都会带上这个会话标识来告诉Web服务器请求是属于哪个会话的。在Web服务器上,各个会话有独立的存储,保存不同的 会话的信息。如果遇到禁用Cookie的 情况,一般的做法就是把这个会话放到URL的参数中,

这里写图片描述

如下图所示 的网站中,如果我第一次访问网站时 请求落到了左边的服务器,那么我的Session就创建在左边的服务器上,如果我们不做处理 ,就不能保证 接下来的请求每次都落在同一边的服务器上,这就是Session问题。

负载均衡集群中的session解决方案
这里写图片描述

我们看看以下的集中解决方案:

2.Session的解决方案

2.1 Session Sticky

在单机的情况下,会话保存在单机上,请求也都是由这个机器处理,所以不会有问题。Web服务器编程多台以后,如何保证同一个会话的请求都在同一个Web服务器上处理,那么对这个会话的个体来说,与之前单机的情况是一样的。
如果要这样,就需要负载均衡器能够根据每次请求的会话标识来进行请求转化,如下图,称为Session Sticky。

负载均衡集群中的session解决方案
这里写图片描述

这个方案本身非常简单,对于Web服务器来说,该方案和单机的情况是一样的,只是我们在负载均衡上做了"手脚"。这个方案可以让通过同样Session的请求每次 都发送到同一个服务器端处理,非常利于针对Session进行服务端本地的缓存。不过也带来了如下几个问题:
  • 如果有一台Web服务器宕机或者重启,那么这台机器上的会话数据会丢失。如果会话中有登录状态数据,那么用户就要重新登录了。

  • 会话标识是应用层的信息,那么负载均衡器要将同一个会话的请求都保存到同一个Web服务器上的话,就要进行应用层的解析,这个开销比第4层的交换要大。

  • 负载均衡器变为了一个有状态的节点,要将会话保存到具体Web服务器的映射。和无状态的节点相比,内存消耗会更大,容灾方面会更麻烦。

nginx为例实现方法:

 1   upstream nginx.example.com
2       {
3                server 192.168.74.235:80;
4                server 192.168.74.236:80;
5                ip_hash;
6       }
7       server
8       {
9                listen 80;
10                location /
11                {
12                        proxy_pass
13                       http://nginx.example.com;
14                }
15    }

ip_hash 不能在以下情况下使用:

  • nginx不是最前端的服务器
    ip_hash 要求nginx一定是最前端的服务器,否则nginx得不到正确的ip,就不能根据ip作hash.

  • nginx 的后端还有其他 方式的负载均衡
    假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用 location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。

2.2 Session Replication

如下图:

负载均衡集群中的session解决方案
这里写图片描述

可以看到,在Session Replication方式中,不再要求负载均衡器来保证同一个会话的多次请求必须到同一个Web服务器上。而我们的Web服务器之间则增加了会话的同步。通过同步就保证了不同Web服务器之间的Session数据的一致。
一般的应用容器都支持Session Replication方式,与Session Sticky 方案相比,Session Replication 方式对负载均衡器没有那么多的要求。不过本身也会存在一些问题,我们来看一下下面的问题:
  • 同步Session 数据造成了网络带宽的开销。只要Session 数据有变化,就需要将数据同步到所有其他机器上,机器数 越多,同步带来的网络带宽开销就越大。

  • 每台Web服务器都要保存所有的Session 数据,如果整个集群的Session数据很多的话,每台机器用于保存的Session数据内容占用会很严重。
    这就是Session Replicaiton方案。这个方案是靠应用容器来完成Session 的复制,从而使得应用解决Session 问题的,应用本身并不关心这个事情。不过,这个方案不适合集群机器数多的场景。如果只有几台机器,用这个方案是可以的。


tomcat配置参考:

https://blog.csdn.net/shiyong1949/article/details/78197848

2.3 Session数据集中存储

同样是希望同一个会话的请求发到不同Web服务器上,刚才的Session Replication是一种方案,还有另一种方案就是把Session 集中存储起来,然后不同Web服务器从同样的地方来获取Session,大概的结构如下图:

这里写图片描述

该方案存在的问题:
  • 读写Session 数据引入了网络操作,这相对于本机的数据读取来说,问题就在于存在时延和不稳定性,不过我们的通信基本都是发生在内网,问题不大。

  • 如果集中存储 Session 的机器 或者集群有问题,就会永祥我们应用

相对于Session Replication ,当Web服务器数量比较大、Sessison数比较大 的时候,这个集中存储防范的优势是非常明显的。

实现的技术方案:

  • Tomcat使用redis实现session共享

          https://blog.csdn.net/fd2025/article/details/80014228

  • Spring session + redis:

           https://www.cnblogs.com/westward/articles/6978906.html

  • shiro session + redis

           https://www.cnblogs.com/shihaiming/p/6406640.html

  • SSO+redis

        https://blog.csdn.net/WuCourage/article/details/77802812

2.4 Cookie Based

Cookie Based 方案是要介绍的最后一个解决Session问题的方案。这个方案对于同一个会话的不同请求也是不限制具体处理机器的。和Session Replication 以及Session数据集中管理的方案不同,这个方案是通过Cookie来传递Session的数据的。

这里写图片描述

从上图可以看到,我们的Session数据放在Cookie中,然后在Web服务器从Cookie中生成对应的Session数据。不过,这种方案依然存在不足:
  • Cookie长度的限制。我们知道Cookie是有长度的,而这也 会限制Session 数据的长度。

  • 安全性: Session 数据本来都是服务器端数据,而这个方案是让这些服务端数据到了外部网络及客户端,因此存在安全上的问题。我们可以对写入的Cookie的Session数据做加密。

  • 带宽消耗:这里指的不是内部 Web服务器之间的带宽消耗,而是我们数据 中心的整体外部带宽的 消耗。

  • 性能影响:每次HTTP请求和响应都带有Session数据,对Web服务器来说,在 同样的处理情况下,响应的结构输出越少,支持的并发请求就会越多。


以上是关于负载均衡集群中的session解决方案的主要内容,如果未能解决你的问题,请参考以下文章

针对负载均衡集群中的session解决方案的总结

针对负载均衡集群中的session解决方案的总结

负载均衡集群中的session解决方案

nginx负载均衡集群中的session共享说明

nginx的负载均衡后session共享(ip_hashredis集群解决)将maven项目向springboot项目改造

使用Redis存储Nginx+Tomcat负载均衡集群的Session