问题出在哪里?

当用户首次访问登录在服务器A上后,服务器A上保留了用户的登录信息。用户的下次请求可能被负载均衡代理器发送到服务器B,服务器B上没有用户的登录信息,如何将session同步到服务器B,使用户对该过程“无感知”?
在负载均衡中,针对session的处理,我们一般有以下几种方式:

  • session保持
  • session复制
  • session共享

session保持

session保持是在负载均衡层实现,在负载请求时将用户请求分发到同一台服务器实现。

nginx的session保持

nginx可以选择session保持的方法实现附着在均衡,nginx的upstream目前支持5种方式的分配方式,其中两种比较通用的session解决方法:ip_hash和url_hash。

ip_hash

每个请求按制造访问的ip和hash结果分配,每个固定访问一个后端服务器。

haproxy的session保持

haproxy作为一个优秀的反向代理和负载均衡软件,也提供了多种session保持的方法:

源地址Hash

haproxy将用户的ip经过hash计算后指定到固定队的真实服务器上(类似于nginx的ip_hash)

配置指令:balancesource
使用cookie进行识别

haproxy在用户第一次访问后在用户浏览器插入一个cookie,用户下次访问时就会带上这个cookie给haproxy,haproxy进行识别。

配置指令:cookies SESSION_COOKIE insert indirect nocache

session保持的缺点:
session保持看似解决了session同步的问题,但是却带来了其他方面的问题:

  • 负载不均衡: 由于使用了session,无法保持负载绝对均衡
  • 没有彻底解决问题:如果后台有服务器宕机,那么这台服务器的session丢失后,访问其他的服务器仍然需要重新登录

session复制

目标是所有服务器上都要保持用户的session,那么将每个服务器的session信息复制到其他服务器节点就可以解决问题。

session复制可以通过tomcat上的功能实现,基于IP组播(multicast)来完成session的复制。tomcat的会话复制分为两种:

  • 全局session复制:利用Delta Manager复制会话中的变更信息到集群中的所有其他节点
  • 非全局session复制:使用Backup Manager进行复制,把session复制给一个指定的备份节点

缺点:
一台服务器上的session状态或者信息发生改变的时候,会向整个网络里发送广播,其他服务器有接收广播的功能,在收到消息后会将session进行对应的改变,达到同步的目的。
但是由于发送的是网络广播,一台服务器改变其他都要改变,对网络造成的压力较大,尤其是在集群中服务器较多,session数据量较大的时候,大批量的网络罗复制会极大消耗后端性能,造成网络阻塞或者瘫痪。

在这里插入代码片

session共享

是否可以将session放在一个统一的地方进行保存?session保存到哪里?

对于session来说是需要频繁使用和访问的, 可以存放在数据库中,但是在真正生产环境中,更推荐放在性能更高的分布式KV数据中,例如Memcached和Redis

redis如何实现负载均衡?

首先明确session和cookie的区别。服务器端保存的cookie每次请求浏览器发送请求到http报文头会自动加上cookie信息,服务器使用用户的cookie(key)去寻找session(value)。
统一域名下网站的cookie都是一样的,所以无论几台服务器,无论请求分发到那台服务器上,同一用户的cookie是不变的,session也就是唯一的,只要保证多台服务器访问同一个redis服务器就可以。