1、LB负载均衡(Load Balance)是什么?
简单的说就是将用户的请求平摊的分配到多个服务商,从而达到系统的HA(高可用)。
2、Ribbon本地负载均衡客户端和Nginx服务端负载均衡区别
Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的 。 Ribbon本地负载均衡,在调用微服务接口的时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
补充:
1、使用ribbon实现负载均衡的时候,服务名称不能用下划线,换成中划线 2、RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版
开始搭建
引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
注意:在高版本spring cloud Eureka依赖中已经包含了spring cloud ribbon(我们现有版本已包含),因此无需再次引入。如过已经添加了的spring cloud Eureka依赖,不要添加该依赖,否则会遇到空指针错误。 我们首先创建3个服务,分别为client1,client2,client3。将client3和client2两个实例指向同一个微服务地址(如何配置,详情见Spring Cloud Eureka搭建及详解)
然后我们分别在三个服务使用#bean的方式注入自己定义的RestTemplateConfig类,并开启负载均衡功能
client1内容:
client2:
client3:
开始测试:
调用client1的getOther
测试结果:
第一次调用返回
From Port : 8703 , hello
第二次
From Port : 8704 , hello
第三次
From Port : 8703 , hello
看得出来默认为轮询方式
下面开始分析ribbon负载均衡方式 下图展示了ribbon的负载均衡类继承关系
各种负载均衡方式详解:
RandomRule:
随机策略
RoundRobinRule:
该策略实现了按照线性轮询的方式一次选择每个服务实例的功能。它的具体实现如下,其详细结构与RandomRule非常类似。除了循环条件不同外,就是从可用列表中获取所谓的逻辑不同。从循环条件中,我们可以看到增加了一个count计数变量,该变量会在每次循环后累加,也就是说,如果一直选择不到server超过10次,那么就会结束尝试。
RetryRule:
该策略实现了一个具备重试机制的实例选择功能。从下面的实现中我们可以看到,在其内部还定义了一个IRule对象,默认使用了RoundRobinRule实例。而在choose方法中则实现了对内部定义策略反复进行尝试的策略,若期间能够选择到实例就返回,若选择不到就根据设置的尝试时间为阈值,当超过该阈值后就返回null。
WeightedResponseTimeRule: 该策略是对RoundRobinRule的扩展,增加了根据实例的运行情况来计算权重,并根据权重来挑选实例,以达到更优的分配效果,它的实现主要有三个核心内容。 定时任务:
WeightedResponseTimeRule策略在初始化的时候会通过serverWeightTimer启动一个定时任务,用来为每个服务实例计算权重,该任务默认30秒执行一次。
权重计算:
根据LoadBalancerStats中记录的每个实例的统计信息,累加所有实例的平均响应时间,得到总平均响应时间
为负载均衡器中维护的实例清单逐个计算权重
实例选择:
获取权重区间的最后一个值,其实也就是总权重
如果总权重,低于0.01d,采用线性轮询的策略
如果总权重大于等于0.01,就产生一个权重区间内的随机数
遍历维护的权重清单,若权重大于等于随机得到的数值,就选择这个实例
ClientConfigEnabledRoundRobinRule:
该策略比较特殊,我们一般不直接使用它。因为它本身并没有实现什么特殊的处理逻辑,正如源码所示,他在内部直接引用了roundRobinRule。
虽然我们不会直接使用该策略,但是通过继承该策略,默认的choose就实现了线性轮询机制,在子类中做一些高级策略时通常有可能会存在一些无法实施的情况,那么就可以用父类的实现作为备选。
BestAvailableRule:
该策略继承自ClientConfigEnabledRoundRobinRule,在实现中它注入了负载均衡器的统计对象LoadBalancerStats,同时在具体的choose算法中利用LoadBalancerStats保存的实例统计信息来选择满足要求的实例。
它通过遍历负载据衡器中维护的所有服务shillings,会过滤掉故障的实例,并找出并发请求最小的一个,所以该策略的特性是可选出最空闲的实例。
PredicateBasedRule:
这是一个抽象策略,它也继承了ClientConfigEnabledRoundRobinRule,从命名中可以猜出这是一个基于Predicate实现的策略,Predicate是Google Guaua Collection工具对集合进行过滤的条件接口。
它定义了一个抽象函数getPredicate来获取AbstractServerPredicate对象的实现,而在choose函数中,通过AbstractServerPredicate的chooseRandomlyAfterFiltering函数来选出具体的服务实例。从该函数的命名我们也能大致猜到他的基础逻辑:先通过子类实现的Predicate逻辑来过滤一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个。
以上是各种默认负载均衡方式的功能说明,具体可以看一哈各种负载均衡类的源代码。 那么如何变更负载均衡方式呢? 方式一:使用@bean的方式注入相关配置
方式二:使用yml配置文件
ribbon:
//自定义服务列表,哪些使用此负载均衡方式
NIWSServerListClassName: com.hry.spring.cloud.consumer.ribbon.ribbonclient.self.MyDiscoveryEnabledNIWSServerList
//自定义负载均衡方式类
NFLoadBalancerRuleClassName: com.hry.spring.cloud.consumer.ribbon.ribbonclient.self.MyRule
测试: 使用@bean的方式注入,使用随机负载均衡方式 将client1设置为随机负载均衡,client2和client3不变(此时使用的是bean第二种方式进行注入,其他方式请自行尝试) 测试结果: 第一次 From Port : 8703 , hello 第二次 From Port : 8703 , hello 第三次 From Port : 8703 , hello 第四次 From Port : 8704 , hello 可以看出已经达到随机负载均衡相应效果 测试使用自定义负载均衡方式 首先继承RoundRobinRule 测试代码如下
变更自定义负载均衡
方式一:
方式二:同样可以使用yml配置文件的当时进行配置(详情见上面负载均衡yml配置方式)
注意:
自定义负载均衡的策略以及算法不能放在@ComponentScan所扫描的包下,不然会被所有Ribbon所共享(即所有的微服务都会使用该策略
测试
在client1主函数配置以上注释
调用client1的getOther方法
可以看出测试结果已经加上了自定义的打印字段,表面自定义负载均衡方式配置成功
ribbon其他配置参数
ribbon:
系统启动之后就初始化,防止在第一次调用超时
eager-load: enabled: true
连接超时时间
ConnectTimeout: 3000
读取超时时间
ReadTimeout: 3000