聊一聊负载均衡

前言

负载均衡是实现服务高可用的一个关键性技术,在集群环境中,常常会将一个应用部署在多台服务器上同时提供服务,负载均衡将任务均衡的分配给不同的服务器,减少单一服务器的负载,达到水平扩容的目的,再者如果集群中某个节点的服务宕机了,负载均衡器会及时发现不可用的节点,并将其从集群服务节点中逻辑移除,此后的流量不会再转发到这台服务器上。

单点服务

没有使用负载均衡的服务架构一般如图:

image-20200420122319035

如果Server出现故障导致服务不可用,则整个系统都会无法使用,这种故障的危害对于一个产品而言是非常巨大的。在微服务流行之前,一些中小型公司和传统IT公司大多采用单点部署方案。

既然单点服务无法保证故障的自动切换,所以为了避免单节点故障而导致的服务不可用,就需要将服务多节点部署,服务之间以主备的方式提供服务,这就延伸到了另外一个方案:多节点主备服务。

多节点主备

多节点主备不算是负载均衡的一种实现,这种方案只是为服务提供了一个备份,虽然服务部署在多台服务器上,但同时只有一台服务器提供服务,当正在提供服务不可用时,自动将请求切换到备份的服务器上。

image-20200420144949473

多节点主备方案保证了服务的高可用,但并没有保证负载的均衡分配,由于同一时间只有一台机器提供服务,所有的流量全部都会透传到这一台服务器上,当流量激增的时候可能会很快的压垮这台服务器,然后不断的在主备机器之间来回切换,每隔一段时间压垮一台服务器。

我们通常解决这种情况的办法就是增加每台服务器的配置,也可以理解为F5负载均衡(压缩数据、连接聚合、页面缓存、浏览器缓存),但是这种方案的成本非常高,一般的中小企业都难以承担这个费用。所以智者又提出能否让多台服务器同时对外提供服务,然后根据一定的规则将流量分配到每一台机器上,这样既能保证服务的高可用,也能缓解每台服务器的压力,因此Nginx这类负载均衡组件应运而生。

负载均衡策略

既然多台服务器可以同时提供相同的服务,那么就需要指定响应的规则进行流量分配,并且要确保服务是可用的,不然请求过来之后不知道该往哪转发,所以在做负载均衡服务配置之前需要先确定均衡策略。

image-20200420151415778
  • 轮询策略:轮询也就意味着服务器会被按顺序的选择,从1到N然后重新开始,比如由两台服务器,请求1分配给Server1,请求2分配给Server2,请求3分配给Server1…,所有的服务器都会被分配数量相同的流量。这种策略适合用于各服务器处理能力相同并且每个业务处理量差不多的情况。
  • 随机策略:请求随机发送到各个节点,每台服务器处理的请求数量可能会有很大的差异。一般不使用随机策略。
  • 最少连接策略:客户端的每次请求所消耗的时长可能会有很大差异,每台服务器上的连接线程可能会因此产生较大的不同,长此以往并不能达到真正的负载均衡。最少连接策略是让负载均衡器记录每台服务器正在处理的请求数,新的请求打过来之后会分配给当前正在处理请求数最少的那台机器,使每台服务器处理的请求数更加均衡。这种策略适合长时处理的请求服务。
  • 权重策略:事先为每台服务器分配不同的权重,比如Server1和Server2分别设置为3和7,也就意味着Server2将承担70%的请求,Server1则承担30%的请求,保证性能更优的服务器能够承担更多的请求处理任务。权重策略适用于服务器性能不同的情况。
  • IP-Hash策略:负载均衡器根据请求来源的IP计算Hash值,然后决定分配给哪一台服务器,当用户IP和Hash计算方式不发生变化的情况下,他发出的所有请求最终都会落在一台机器上。该策略适用于想简单解决session问题的情况。

健康检查

使用负载均衡的目的既然是提升服务的高可用,那么前提自然是要确保集群中的每个服务都是健康可用的,负载均衡器会通过健康检查的方式来识别服务是否可用。

常用的负载均衡器基本属Nginx莫属了,使用Nginx的好处是它自带健康检查模块ngx_http_upstream_module,可用做到最基本的健康检查。但是Nginx是被动的进行健康检查,也就是健康检查是依赖于请求的,如果服务1出现异常,则需要再将请求转发给服务2,直到遇到能够成功返回的接口,每一次的失败请求都会被记录下来,若失败节点达到了预设的最大次数,则将其从健康服务列表中移除,效率不高。

1
2
3
4
5
6
7
8
9
10
11
12
13
upstream backend{
# max_fails表示失败次数,整体的意思是在fail_timeout时间内若失败次数达到了max_fails,则认为该节点的服务异常,移除健康服务列表
server 127.0.0.1:8080 max_fails=1 fail_timeout=40s;
server 127.0.0.1:8090 max_fails=1 fail_timeout=40s;
}

server {
listen 80;
server_name d.kv.cc;
location / {
proxy_pass http://backend;
}
}

负载均衡session共享问题

在使用IP-Hash做负载均衡策略时,因为同一个用户的请求都会转发到固定的一台机器上,所以在服务稳定的情况下,不用考虑session共享的问题,但是为了防止服务器突然宕机而引起的请求被转发到其他机器造成的session丢失的情况出现,所以不管哪一种策略,最好都做好session共享的解决方案。

  1. Redis:可以使用spring-session+Redis来实现session共享,很简单,请看Spring-Session和Redis实现Session共享
  2. 基于token认证:JWT认证