负载均衡是指将请求/数据分发到多个运行单元去执行,关键在于均衡。但是,后端服务器的硬件条件可能不同:如果将负载“平均”分配给低配置的服务器,高配置服务器的利用率就会不足。能否根据异构服务器的处理能力,动态自适应地进行负载均衡和过载保护?负载均衡通常是如何完成的?服务层的负载均衡一般是通过服务连接池来实现的。连接池会与下游服务建立多个连接,并为每个请求“随机”获取连接,以保证访问的平衡。负载均衡、故障转移和超时处理等细节也是通过调用者连接池实现的。调用者的连接池能否根据服务的处理能力动态自适应调度负载?(1)方案一:服务的处理能力可以通过“静态权重”来识别。最容易想到的方法就是为每个下游服务设置一个“权重”,代表该服务的处理能力,来调整访问每个服务的概率,如上图所示:假设ip1的处理能力,ip2,ip3是一样的,可以设置weight1=1,weight2=1,weight3=1,这样三个服务连接被获取的概率分别是1/3,1/3,1/3,可以保证均衡访问;假设ip1的处理能力是ip2,是ip3处理能力的2倍,可以设置weight1=2,weight2=1,weight3=1,这样三个服务连接被获取到的概率是2/4,1/4、1/4,可以保证处理能力强的服务按比例分配流量,不造成资源浪费;Nginx具有类似的功能。方案优点:简单粗暴,可以快速实现异构服务器的负载均衡。方案缺点:权重是固定的,不能动态自适应调整,很多时候服务器的处理能力很难用固定值量化。(2)方案二:使用“动态权重”来识别服务的处理能力。如何识别服务的处理能力?服务能不能处理,由调用者决定:调用服务,处理快点,处理能力跟不上调用服务,如果处理超时,处理能力可能跟不上怎么样设计动态权重?你可以这样玩:用一个动态权重来标识每个服务的处理能力。默认初始处理能力相同,即分配给每个服务的概率是相等的;每当一个服务成功处理一个请求,就认为服务处理能力足够,权重动态+1;每当服务处理一个请求超时,就认为服务处理能力可能跟不上,权重动态-10;画外音:重量下降的速度快于重量上升的速度。为了方便权重的处理,可以将权重的范围限制在[0,100],权重的初始值设置为60分。例如:假设service-ip1、service-ip2、service-ip3的动态权重初值:weight1=60weight2=60weight3=60一开始,请求分配给这三个服务的概率为60/180、60分别为/180、60/180,即负载均衡。随着时间的推移:越来越多的请求被具有强大处理能力的服务成功处理。处理能力较弱的服务偶尔会超时。随着动态权重的增减,权重会发生变化:weight1=100weight2=60weight3=40那么此时,请求分配给这三个服务的概率分别为100/200、60/200、40/分别200,即处理能力强的服务会分配更多的流量。那么什么是过载保护呢?如上图所示,如果没有过载保护:随着外部负载的不断增加,系统的实际处理负载会增加。当外部负载上升到临界值时,系统将被压垮,实际处理能力将下降。掉到0画外音:这叫“掉底”。过载保护是指当外部负载超过系统的处理能力时,系统会进行自我保护,仍然能够对外提供受损稳定的服务。如上图所示,如果实施了过载保护:随着外部负载的不断增加,系统的实际处理负载会增加。即使外部负载超过临界值,系统也不会被压垮,还能保持一定的处理能力画外音:即使是最大的外部负载,系统也不会“触底”。如何实现过载保护?(1)方案一:服务的处理能力可以通过“静态权重”来识别。这是最简单的方法。服务器设置一个负载阈值,所有超过这个阈值的请求都会被淹没并丢弃。画外音:这种做法不是特别优雅。(2)方案二:借助“动重”实现过载保护。和异构服务器的负载均衡一样,后端的处理能力仍然由动态权重来标识:处理成功加分(+1),处理超时扣分(-10)。画外音:还是在连接池层面实现。当服务器反复超时,权重不断下降时,连接池只需要对“疑似超载”的服务器实施一些策略来减轻压力,而不是让服务器“放弃请求”来实现过载保护。应该实施什么样的策略来保护“疑似超载”的服务器?可以这样玩:(1)如果一个服务器连续3次请求超时,也就是连续3次-10分,可以认为,服务器处理不了,只好拿为这台服务器喘口气,所以我定下一个策略:在接下来的几个小时内,比如1秒,不再向这台服务器分配负载;它。(2)如果某个服务的动态权重降为0(3次断后超时),可以认为服务器完全无法处理,服务器不得不大口喘口气,所以设置策略:Next一定时间,比如1分钟,请求将不再分配给这个服务器;画外音:根据经验,此时服务器一般处于fullGC,恢复需要1分钟左右。这样一来,不仅可以借助“动态权重”实现动态自适应异构服务器负载均衡,还可以在客户端层面更优雅地实现过载保护,让下游服务器在快要过载时喘口气。未能响应机会。过载保护应注意什么?防止过载保护导致服务器雪崩,如果“整体负载”已经超过了“服务器集群”的处理能力,那么无论怎么处理传输请求,都无法处理。这时候你还是要通过放弃请求来进行自我保护。综上所述,负载均衡、故障转移、超时处理通常是在连接池层面实现的异构服务器的负载均衡。最简单的方法是静态权重法。缺点是动态权重法不能动态自适应调整,只能根据服务器的处理动态调整。分配负载的能力需要在连接池级别进行小的更改。过载保护是服务器在负载过高时进行自我保护,保证一定的处理能力的一种自救方式。动态加权法也可作为服务器过载保护【本文为专栏作者“58神剑”原创稿件,转载请联系原作者】点此查看该作者更多好文
