在大多数的企业级应用中,客户端与服务器经常需要通过多次的交互才能完成一次事务处理或一笔交易。由于这些交互与用户的身份是紧密相关的,因此,与这个客户端相关的应用请求,往往需要转发至一台服务器完成,而不能被负载均衡器转发至不同的服务器上进行处理。为了实现这一机制,我们需要在负载均衡上配置会话保持(Session Persistence)机制,以确保客户端与应用系统之间的交互不会因为部署了负载均衡而发生问题。

实际上,会话保持机制与负载均衡的基本功能是完全矛盾的。负载均衡希望将来自客户端的连接、请求均衡的转发至后端的多台服务器,以避免单台服务器负载过高;而会话保持机制却要求将某些请求转发至同一台服务器进行处理。因此,在实际的部署环境中,我们要根据应用环境的特点,选择适当的会话保持机制。
 
连接和会话的区别
在介绍会话保持技术之前,我们必须先花点时间弄清楚一些概念:什么是连接(Connection)、什么是会话(Session),以及这二者之间的区别。
需要特别强调的是,如果我们仅仅是谈论负载均衡,会话和连接往往具有相同的含义。但是,如果我们和开发人员沟通这些术语时,这两个术语却具有截然不同的含义。希望广大读者能够注意这其中的区别。在本文中,我想着重说明的是开发人员眼中的连接及会话的含义。
通常,在普通的客户端或服务器上,我们把具有相同[源地址:端口],和相同[目的地址:端口]的数据包定义为一个连接。下表是Windows系统中用命令 netstat –an输出的部分系统连接状态。
 
 
  
  1. C:\>netstat -an 
  2.   
  3. 活动连接 
  4.   
  5.  协议 本地地址          外部地址        状态 
  6.  
  7. ...<省略部分输出内容>... 
  8.   TCP    172.31.20.53:47669     122.225.67.240:80      ESTABLISHED 
  9.   TCP    172.31.20.53:47670     122.225.67.240:80      ESTABLISHED 
  10.   TCP    172.31.20.53:47671     122.228.243.240:80     ESTABLISHED 
  11.   TCP    172.31.20.53:47672     110.75.34.138:80       TIME_WAIT 
  12.   TCP    172.31.20.53:47673     110.75.34.138:80       TIME_WAIT 
  13.   TCP    172.31.20.53:47674     110.75.34.138:80       TIME_WAIT 
  14.   TCP    172.31.20.53:47675     122.225.67.240:80      ESTABLISHED 
  15.   TCP    172.31.20.53:47676     122.225.67.240:80      ESTABLISHED 
  16.   TCP    172.31.20.53:47677     122.228.243.240:80     ESTABLISHED 
  17.   TCP    172.31.20.53:47679     110.75.24.105:80       ESTABLISHED 
  18.   TCP    172.31.20.53:47681     122.225.67.240:80      ESTABLISHED 
  19.   TCP    172.31.20.53:47682     122.225.67.240:80      ESTABLISHED 
  20.   TCP    172.31.20.53:47683     60.191.143.240:80      ESTABLISHED 
  21.   TCP    172.31.20.53:47684     60.191.143.240:80      ESTABLISHED 
  22.   TCP    192.168.1.4:18231      203.208.46.29:443      CLOSE_WAIT 
  23. ...<省略部分输出内容>... 
对于负载均衡来说,情况则稍微发生了一些变化。负载均衡会将来自相同[源IP:端口],发送到相同[目的IP:端口]的数据包,通过NAT技术做一些转换后,转发至后端的某台固定的服务器。如下表所示,虽然两个TCP连接具有相同的源地址,但源端口不同,AX负载均衡仍然将其识别为两个不同的连接,并且转发至两台不同的服务器进行处理。
 
 
  
  1. AX#show session 
  2. ...<省略部分输出内容>... 
  3.   
  4. Prot Forward Source         Forward Dest           Reverse Source         Reverse Dest           Age Hash 
  5. ----------------------------------------------------------------------------------------------------------- 
  6. Tcp  103.104.157.122:1619   61.22.215.151:80       172.30.2.83:80         103.104.157.122:1619   60     1     
  7.  
  8. Tcp  103.104.157.122:1621   61.22.215.151:80       172.30.2.84:80         103.104.157.122:1621   120     3     
  9.  
  10. ...<省略部分输出内容>... 
对于同一个连接中的数据包,负载均衡会将其进行NAT转换后,转发至后端固定的服务器进行处理,这是负载均衡最基本、最原始的功能。负载均衡系统内部会专门有一张表来记录这些连接的状况,包括:[源IP:端口]、[目的IP:端口]、[服务器IP:端口]、空闲超时时间(Idle Timeout)等等。这里需要特别说明一下超时时间的意义和定义。
由于负载均衡内部记录连接状态的这张表需要消耗系统的内存资源,因此,这张表不可能无限大,所有厂家都会有一定的限制。这张表的大小一般称之为最大并发连接数,也就是系统同时能够容纳的连接数量。考虑到建立这些连接的客户端或服务器会发生一些异常状况,导致这些连接不能被正常终结掉,因此,负载均衡的当前连接状态表项中,设计了一个空闲超时时间的参数。这个参数定义为,当该连接在一定时间内无流量通过时,负载均衡会自动删除该连接条目,释放系统资源。在AX中,这个空闲超时时间一般设置为120秒。也就是说,如果在120秒内,对于某个连接,AX没有收到任何来自客户端或服务器端的数据包,AX会主动删除该连接,以释放系统资源。
之所以在这里强调这个参数,是为了和后面介绍会话保持机制时提到的会话保持时间有所区别。
理解了连接的概念,那么对于会话的概念就会比较容易理解一些。在开发人员眼中,会话一般是指从用户登录应用系统,进行事务处理,直至退出应用系统的整个过程。因此,对于相同的会话,客户端可能会建立多个连接进行处理。如果在客户端和服务器之间部署了负载均衡设备,很有可能,这多个连接会被转发至不同的服务器进行处理。如果服务器之间没有会话信息的同步机制,会导致其他服务器无法识别用户身份,造成用户在和应用系统发生交互时出现异常。常见的异常场景包括:
客户端输入了正确的用户名和口令,但却反复跳到登录页面,要求用户进行登录,
客户端放入购物篮的物品丢失。
因此,会话保持机制的意义就在于,确保将来自相同客户端的请求,转发至后端相同的服务器进行处理。换句话说,就是将客户端与服务器之间建立的多个连接,都发送到相同的服务器进行处理。
 
常见的会话保持机制介绍
源地址会话保持
源地址会话保持利用客户端的源地址信息,负载均衡会将所有来源于相同源IP的连接认为是相同的客户端,并将这些连接转发至相同的服务器进行处理。当我们启用了源地址会话保持机制后,AX负载均衡在收到新的连接请求时,会首先查询系统的源地址会话保持表,如果查询到该IP地址对应的服务器表项,则根据当前表项对应的服务器建立连接,如果没有查询到该源IP对应的服务器,则根据当前配置的算法选择服务器。同时,会将当前连接对应的服务器记入源地址会话保持表。这样,当该源IP有新的连接请求时,就会根据该表项选择后端的服务器资源。
源地址会话保持机制是一种非常简单但又十分高效的会话保持机制。但是,正是这种简单,又造成负载均衡无法很准确的识别客户端,造成后端服务器负载分配不均匀。尤其是当大量的客户端共享同一个NAT地址访问服务器资源时,会造成某台服务器的负载分配过高。同时,由于负载均衡系统内部保存会话保持表也会占用一定的资源,因此,当客户端数量巨大的时候,可能会造成会话保持表被耗尽的问题。
 
Cookie会话保持
Cookie会话保持是利用HTTP协议中的cookie功能来实现会话保持功能。当客户端的请求中带有负载均衡设置的cookie信息,则负载均衡根据cookie中的信息来选择服务器;当客户端的请求中没有cookie信息,则负载均衡按照算法选择服务器,同时,在服务器响应的response头部中,插入cookie信息。这样,当该客户端再次访问服务器时,可以确保该客户端的请求会被转发到相同的服务器进行处理。
相较于源地址会话保持机制来说,cookie会话保持能够更加精准的识别客户端,避免了大量客户端共享同一个NAT地址访问服务器资源时,源地址会话保持造成的单台服务器负载过高的问题。此外,负载均衡通过分析客户端请求中的cookie信息来决定服务器选择,因此,负载均衡无需在系统中维护会话表项,因此,没有会话表项数量的限制。但是,cookie会话保持机制却比源地址会话保持存在更多的限制。
首先,cookie会话保持只能够在B/S架构的应用中使用,也就是说,cookie会话保持只能够工作在HTTP协议下。道理很简单——非HTTP协议并不支持cookie插入。
其次,如果浏览器不支持cookie,即便配置了cookie会话保持机制,cookie会话保持机制也不会起到应有的效果。
第三,由于cookie会话保持机制中,需要根据负载均衡当前的系统时间来计算一个过期时间,并把该时间设置为cookie失效的时间,因此,负载均衡的系统时间不能有太大误差,否则,会话保持机制有可能会失效。
对于第三个问题,我们考虑一种场景,当负载均衡的系统时间比正常的时钟慢20分钟,而会话保持的超时时间设置为15分钟,则客户端在收到负载均衡插入的cookie后,会认为该cookie已经失效,则在后续的http请求中,不会带有负载均衡插入的用于会话保持的cookie。
 
简单总结一下这两种常见的会话保持机制的优缺点:
方法
优点
缺点
适用场景
源地址会话保持
适用范围广泛
无需负载均衡保持精准时钟
不需要修改客户端请求或响应
需要维护会话表
客户端识别仅依靠源地址信息,不够精准
各种B/S、C/S应用
需要会话保持时间较短的应用
需要高性能的场景
cookie会话保持
客户端识别精准
仅支持B/S架构应用
需要客户端支持cookie
需要负载均衡维持精准的系统时钟
B/S架构应用
需要会话保持时间较长的应用
 
在下一篇文章中,我们仍然以A10的AX负载均衡为例,向大家介绍在具体的场景中,如何配置会话保持机制,在实现会话保持的基础上,又能更加均衡的负载客户端请求。
E.S.