负载均衡
负载均衡(Load Balance)是互联网架构中的必备技术,多层级的负载均衡服务器是大公司构建分布式系统的必备组件,它可以将请求分摊到后端多个服务器实例上,从而可以达到更大的吞吐量,减少系统响应时间,避免单点过载问题。
常用的负载均衡服务器一般有基于七层的应用层负载均衡、四层的IP层负载均衡、二三层的硬件负载均衡,以及基于DNS的负载均衡。作为软件工程师一般接触多的就是基于软件层面实现的四层和七层的负载均衡了。
四层的负载均衡是不能理解应用层协议的,它不知道请求的是HTTP还是FTP,是MySQL还是Redis,这样的细节它是不知道的。而七层的负载均衡是基于虚拟的URL或主机IP的来负载,它是在高级的应用层上执行的,它可以处理每一个请求消息的内容,比如它可以识别请求的是图片还是文本,如果识别到是图片类的请求就可以转发到静态资源的服务器上,还可以增加一些压缩等其它操作。
七层的负载均衡相对来说性能要差一些,因为它要用算法去识别URL、Cookie和HTTP Header这样的信息,但是它的安全性确是更高的,它可以识别出DDOS或其它的一些恶意攻击,同时还可以处理一些额外功能,像会话保持、图片压缩、文字加密等等。
在大型互联网公司,一般多个层级的负载均衡都是需要的,越往上层功能越丰富,越底层的负载均衡功能越简单。
了解了负载均衡的这么多好处,那一定很好奇负载均衡的算法是怎么实现的吧。
顺序轮询
顺序轮询是一种简单轮询算法,实现它很简单,只需要记录一个值,每次调用这个值就递增1,然后用实例总数量对这个值进行取模运算,就可以得到这个实例的索引。
1
2
3
index = num % instances.total
instance = instances[index]
num += 1
假如一个服务有三个实例分别为A、B、C:
次数 | num值 | 命中索引 | 命中实例 |
---|---|---|---|
1 | 0 | 0%3=0 | A |
2 | 1 | 1%3=1 | B |
3 | 2 | 2%3=2 | C |
4 | 3 | 3%3=0 | A |
5 | 4 | 4%3=1 | B |
6 | 5 | 5%3=2 | C |
随机轮询
随机轮询和顺序轮询类似,它是随机的将流量分配到各个节点,随着调用次数的增多,实际效果会越来越接近于平均分配,优缺点也和顺序轮询有些相似。
顺序轮询和随机轮询算法简单高效,不过它并没有考虑机器的性能问题,也就是说无论服务器性能强还是弱,都会收到相同的请求流量。
权重交叉轮询
如果一台服务器 serverC 的性能更强,它就能干的事情就越多,那么用顺序轮询或随机轮询就不太合适,需要加入权重的概念:能力越强的权重越高,命中的概率也就越高,这就是权重交叉轮询。
那么应该怎么实现呢?原理也很简单。
每个服务都记录一个当前的权重值,每请求一次所有服务的当前权重值增加上自己的权重,作为新的权重值,然后命中最大值的那个,如果等权则命中第一个。每次命中后的服务权重值再减去总权重值。
假设现在有三个服务:A、B、C 权重值分别为10、20、30,最初的时候它们的权重都是零。看下它们每次请求时的权重变化,括号内为减去总权重后的值:
次数 | A权重 | B权重 | C权重 | 当前总权重 | 命中实例 |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | |
1 | 10 | 20 | 30 (30-60=-30) | 60 | C |
2 | 20 | 40 (40-60=-20) | 0 | 60 | B |
3 | 30 (30-60=-30) | 0 | 30 | 60 | A |
4 | -20 | 20 | 60 (60-60=0) | 60 | C |
5 | -10 | 40 (40-60=-20) | 30 | 60 | B |
6 | 0 | 0 | 60 (60-60=0) | 60 | C |
经过了两轮轮询,看下命中次数是不是和上面的权重是不是相同呢?权重交叉轮询算法是不是也很简单呢?
服务 | 命中次数 |
---|---|
A | 1 |
B | 2 |
C | 3 |