今天跟大伙儿聊的是负载均衡相关的一些算法。老王在百度的时候(估计是5-6年前),写过一个通用的基础库(不知道现在还有没有部门在用),用来做不同系统间负载均衡。太细节的东东估计想不起来了,不过基本的算法可以跟大家做做分享。
那第一个问题:what's load-balance?
假设我有两个模块(或者两个系统):module-A和module-B,A依赖B提供服务。当用户请求过来的时候,A就会去请求B,让B根据请求进行某些处理(比如:根据单词id查对应的单词),完成后把结果返回给A,A再对这个结果进行处理。然而,为了保证服务稳定,有可能B服务有很多台机器,A遇到这个时候就犯难了:我该去找B的哪台机器取数据呢?
最常见的一个case就是nginx:比如我们的web逻辑服务器是jetty或者tomcat,一般会有多台,nginx就需要配置这多台机器:
upstream simplemain.com {
server 192.168.1.100:8080;
server 192.168.1.101:8080;
}
那这些机器是怎么样选择的呢?实际就是负载均衡算法。
老王对负载均衡的理解,他应该包含两个层面:
1、负载:就是后端系统的承载能力。比如同等条件下,一个1核cpu-1G内存的机器的承载能力一般会比8核cpu-8G内存的机器要差;相同配置下,一个cpu利用率为80%的机器比30%的承载能力一般要差等等。
2、均衡:保证后端请求的平衡。比如:在同等情况下,分配到多台机器的请求要相当;有些情况下,同一用户尽可能分配到同一台机器等等。
所以,负载均衡的算法实际上就是解决跨系统调用的时候,在考虑后端机器承载情况的前提下,保证请求分配的平衡和合理。
那第二个问题随之而来:why?
为什么要有负载均衡呢?
1、很明显,如果我们不去考虑后端的承载情况,有可能直接就把某台机器压垮了(比如cpu利用率已经80%了,再给大量的请求直接就干死了),更严重的会直接造成雪崩(一台压死了,对应的请求又压倒其他某台机器上,又干死一台……),从而致使服务瘫痪。
2、如果我们均衡算法选的不好,就会导致后端资源浪费。比如:如果选择一致Hash算法,可以很好利用cache的容量。而如果用随机,有可能就会让cache效果大打折扣(每台机器上都要缓存几乎相同的内容)。
所以,用负载均衡应该是一个比较好的选择。
那就解决第三个问题吧:how?
按照之前的思路,我们还是分成两个部分来讲:负载& 均衡。
1、先来看负载算法:
既然要解决后端系统的承载能力,那我们就有很多方式,常见的有以下几种:
A、简单粗暴有效的:手工配置!
大家是不是觉得这个听起来很山寨呢?其实不是。这种方式对于中小系统来讲是最有效最稳定的。因为后端机器的性能配置、上面部署了哪些服务、还能有多大的承载能力等等,我们是最清楚的。那我们在配置的时候,就可以明确的告诉调用者,你只能分配多大的压力到某台服务器上,多了不行!
比如,我们经常看到nginx的配置:
upstream simplemain.com {
server 192.168.1.100:8080 weight=30;
server 192.168.1.101:8080 weight=70;
}
就是说,虽然有两台后端的服务器,但是他们承载能力是不一样的,有一个能力更强,我们就给他70%的压力;有一个更弱,我们就给他30%的压力。这样,nginx就会把更多的压力分配给第二台。