会话保持(粘滞会话)

会话保持是负载均衡中最常见的问题之一,也是一个相对于比较复杂的问题。会话保持有时候又被叫做粘滞会话(Sticky Sessions)。会话保持是指在负载均衡器上的一种机制,可以识别客户端与服务器之间交互过程的关联性,在做负载均衡的同时还保证一系列相关联的访问请求会保持分配到一台服务器上。

会话保持的使用场景

在讨论这个话题之前,必须要先花一点时间弄清楚一些概念:什么是连接(Connection)、什么是会话(Session),以及这两者之间的区别。需要特别强调的是,如果我们仅仅是讨论负载均衡,会话和连接往往具有相同的含义。从简单的角度来看,如果用户需要登陆,那么就可以简单地理解为会话;如果不需要登陆,那么就理解为连接。

对于同一个连接中的数据包,负载均衡会将器进行NAT转换后,转发到后端固定的服务器进行处理。负载均衡系统内部会有专门的一张表来记录这些连接的情况,包括【源IP:端口】、【目标IP:端口】、【服务器IP:端口】和空闲超时时间(Idel Timeout)等。

由于负载均衡内部记录连接状态的这张表需要消耗系统的内存资源,因此这张表不可能无限大,所有传统厂商都会有一定的限制。这张表的大小一般称之为最大并发连接数,也就是系统能够同时容纳的连接数量。负载均衡的当前连接状态表项中,设计了一个空闲超时时间(Idle Timeout)的参数。当该连接在空闲超时时间内无流量通过时,负载均衡器就会自动删除该连接条目,释放系统资源。删除了连接后,客户端的请求将无法保持继续发往同一个后端服务器,需要遵循负载均衡器的流量分发策略。

在某些要求登陆状态的情境下,就会要求客户端和服务器之间保持一个会话(Session)以记录客户端的各种信息。比如在大多数电子商务的应用系统或者需要进行用户身份认证的在线系统中,一个客户与服务器经常进行好几次的交互过程才能完成一笔交易或者是一个请求的完成。由于这几次交互过程是密切相关的,服务器在进行这些交互过程的某一个交互步骤时往往需要了解上一次或上几次的交互过程处理结果,这就要求所有这些相关的交互过程都要由一台服务器完成,而不能被负载均衡器分散到不同的服务器上。否则可能会出现异常情况:

1.客户端输入了正确的用户名和口令,却反复跳到登陆页面。

2.用户输入了正确的验证码,可是总是提示验证码错误。

3.客户端放入购物车的物品丢失。

...

因此会话保持机制的意义就在于,确保在合适的场景下,将来自相同客户端的请求转发至后端相同的服务器进行处理。换句话说,就是将客户端与服务器之间建立的多个连接,都发送到相同的服务器进行处理。如果在客户端和服务器之间部署了负载均衡设备,很有可能这多个连接会被转发到不同的服务器进行处理。如果服务器之间没有会话信息的同步机制,就会导致其他服务器无法识别用户身份,造成用户在和应用系统发生交互时出现异常。

负载均衡希望将来自客户端的连接,请求均衡地转发至后端的多台服务器,以避免单台服务器负载过高;而会话保持则要求将某些请求转发到同一台服务器进行处理。因此,在实际的部署环境中,我们要根据应用环境的特点,选择适当的会话保持机制。

简单会话保持(四层会话保持)

简单会话保持也被称作基于源地址的会话保持、基于IP的会话保持,是指负载均衡器在做负载均衡的时候根据访问请求的源地址(IP地址)作为判断关联会话的依据。对来自同一IP地址的所有访问请求在做负载均衡的时候都会被转发到同一台服务器上去。在Nginx中,提供的一种ip_hash的负载均衡策略就是实现了这一需求。

简单会话保持中的一个很重要的参数就是连接超时值。负载均衡器会为每一个处于保持状态中的会话设定一个时间值。若一个会话从上一次完成到下次再来之间的间隔时间小于超时值时,负载均衡器就会将新的连接进行会话保持。但是如果这个间隔大于该超时值,负载均衡器就会认为该连接是新的会话并重新进行负载均衡。

简单会话保持实现简单,只需要根据数据包的三四层的信息就可以实现,效率比较高。但是这种方式存在的问题就在于,当多个客户端通过代理或地址转换的方式访问服务器时,由于来源地址一样,请求都被分配到同一台服务器上,就会导致服务器之间的负载严重失衡。

另外一种情况是,同一个客户端上产生大量并发,要求分配到多个服务器上处理的同时进行会话保持,这时基于客户端源地址的会话保持方法也会导致负载均衡失效。

当以上情况出现的时候,就必须要考虑使用其他的会话保持方式。

共享会话的会话保持

此种方式是通过多个后端服务器共享Session的方式,实现与负载均衡同时的会话保持。主要有数据库存放、文件系统存放和缓存(内存)存放的方式。

数据库存放

Session信息存储到数据库表,以此来实现不同应该服务器之间Session信息的共享。这种方法使用与数据库访问量不大的网站。这种方式的优点是实现简单,缺点高并发性能差。由于数据库服务器相对于应用服务器更难扩展且资源更为宝贵,在高并发的Web应用中,最大的性能瓶颈通常出现在数据库服务器。因此,如果将Session存储到数据库表,频繁的数据库操作会影响业务。

文件系统存放

通过文件系统(比如NFS)来实现各台服务器间的Session共享。此种方式适合并发量不大的网站。优点是各台服务器只需要mount存储Session的磁盘即可,实现较为简单。缺点则是NFS对高并发读写的性能并不高,在磁盘I/O性能和网络带宽上存在较大瓶颈,尤其是对于Session这样的小文件的频繁读写操作。

内存存放

利用Memcached来存放Session数据,直接通过内存的方式读取。优点是效率高,在读写速度上会比存放在文件系统或数据库时快甚多,而且多个服务器公用Session也更加方便,将这些服务器都配置成使用同一组Memcached服务器就可以,减少了额外的工作量。缺点是一旦宕机,内存中的数据就会丢失,但是对Session数据来说并不是特别严重的问题。如果网站的访问量太大,Session太多的时候Memcached就会将不常用的部分删除,但是如果用户隔离了一段时间之后继续使用,将会发生读取失败的问题。

当然也可以使用Redis做Sesion的共享。

基于Cookie的会话保持(七层会话保持)

在基于Cookie的模式下负载均衡器负责插入Cookie,后端服务器无需作出任何修改。当客户端进行第一次请求时,客户端的HTTP Request(不带Cookie)进入负载均衡器,CLB根据负载均衡算法策略选择后端一台服务器,并将请求发送至该服务器;后端服务器的HTTP Response(不带Cookie)被发回给负载均衡器。接下来负载均衡器将向该后端服务器插入Cookie并将HTTP Response返回到客户端。

当客户端请求再次发生的时候,客户HTTP Request(带有上次负载均衡器插入的Cookie)进入CLB,然后CLB读出Cookie里的会话保持数值,将HTTP Request(带有与上面同样的Cookie)发到指定的服务器,然后后端服务器进行请求回复;由于服务器并不写入Cookie,HTTP Response将不带Cookie,该HTTP Response再次经过进入CLB时,CLB将写入更新后的会话保持Cookie。

腾讯云CLB的7层会话保持能力,就是基于这样的Cookie插入的方式实现的。

转自:https://www.cnblogs.com/wajika/p/6645581.html

"你越努力,遇到的人就越优秀。"

原文地址:https://www.cnblogs.com/yanggb/p/10970702.html