文章目录
实战
环境
Nacos
Nacos Version
:2.0.3
Demo Application:
System
: macOS 10.14.6
JDK
: 1.8.0_251
Spring Boot
:2.2.13.RELEASE
Spring Cloud
:Hoxton.SR12
Spring Cloud Alibaba
: 2.2.5.RELEASE
Ribbon简介
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。Ribbon就是简化了上面代码的组件,其中提供了更多的负载均衡算法。 它是Spring Cloud的一个组件,它可以让我们使用一个注解就能轻松的搞定负载均衡。
负载均衡分类
- 服务器端负载均衡
- 客户端负载均衡
手写客户端负载均衡
服务层HandWtriteLoadBalance::getGoodById
public Result getGoodById(String id) {
// 从nacos中获取服务
List<ServiceInstance> instances = discoveryClient.getInstances("good-service");
// 定义一个随机数
int i = new Random().nextInt(instances.size());
// 随机获取一个服务
ServiceInstance instance = instances.get(i);
String url = instance.getHost() + ":" + instance.getPort();
Result result = restTemplate
.getForObject("http://"+url+"/good/" + id, Result.class);
return result;
}
控制器层RibbonController::handWriteLoadbalance
@RequestMapping("/hand")
public Result handWriteLoadbalance(@RequestParam("id") String id) {
return handWtriteLoadBalance.getGoodById(id);
}
Ribbon实现负载均衡
服务层RibbionLoadBalance::getGoodById
public Result getGoodById(String id) {
// 自动负载均衡并解析服务名为ip:port
Result result = ribbonRestTemplate
.getForObject("http://good-service/good/" + id, Result.class);
return result;
}
控制器层RibbonController::ribbionLoadBalance
@RequestMapping("/auto")
public Result ribbionLoadBalance(@RequestParam("id") String id) {
return ribbionLoadBalance.getGoodById(id);
}
负载均衡策略
策略名 | 策略描述 | 实现说明 |
---|---|---|
BestAvailableRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | 先过滤掉故障实例,再选择并发较小的实例; | 过滤掉一直连接失败的被标记为circuit tripped(电路跳闸)的后端Service,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤Server的逻辑,其实就是检查status的记录的各个Server的运行状态 |
WeightedResponseTimeRule | 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取平均响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权 |
RetryRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | 轮询方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule(默认) | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
配置项
接口 | 作用 | 默认值 |
---|---|---|
IclientConfig | 读取配置 | DefaultClientConfigImpl |
IRule | 负载均衡规则,选择实例 | ZoneAvoidanceRule |
IPing | 筛选掉ping不通的实例 | DumyPing(该类什么不干,认为每个实例都可用,都能ping通) |
ServerList | 交给Ribbon的实例列表 | Ribbon:ConfigurationBasedServerList Spring Cloud Alibaba:NacosServerList |
ServerListFilter | 过滤掉不符合条件的实例 | ZonePreferenceServerListFilter |
ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
ServerListUpdater | 更新交给Ribbon的List的策略 | PollingServerListUpdater |
支持配置方式
代码配置和属性配置(优先选择)。
代码配置负载均衡策略
策略配置类::RibbonConfiguration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
在类上面加了@Configuration注解的话,就必须将该类放到@ComponentScan能扫描的包以外,否则这个类的配置将会被所有的RibbonClient共享,就无法实现针对服务的细粒度配置了,详见JAVA父子上下文。所以这里建议不加。
服务选择策略配置类GoodServiceRibbonConfiguration
@RibbonClient(name = "good-service", configuration = RibbonConfiguration.class)
public class GoodServiceRibbonConfiguration {
}
全局选择策略配置类
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class GloableRibbonConfiguration {
}
属性配置负载均衡策略
# ribbon loadbalance strategy
good-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
常用配置
饥饿加载
在使用RestTemplate的时候,用Rabbon时会进行懒加载,头一次的访问会比较慢。可改变加载模式,将懒加载改为饥饿加载,增加如下配置:
ribbon.eager-load.enabled=true
# 多个服务,以 英文逗号分割
ribbon.eager-load.clients=good-service
禁用Eureka
# 禁用 Eureka
ribbon.eureka.enabled=false
禁用了 Eureka 之后,就不能使用服务名称去调用接口了,必须指定服务地址。
# 手动配置服务地址
good-service.ribbon.listOfServers=localhost:8080,localhost:8081
配置并发、超时、重试参数
配置并发参数
# 最大连接数
ribbon.MaxTotalConnections=200
# 每个host最大连接数
ribbon.MaxConnectionsPerHost=200
配置超时参数
# 请求连接的超时时间,默认1s
ribbon.ConnectTimeout=1000
# 请求处理的超时时间,默认1s
ribbon.ReadTimeout=2000
# 可以为每个Ribbon客户端设置不同的超时时间, 通过服务名称进行指定:
good-service.ribbon.ConnectTimeout=1000
good-service.ribbon.ReadTimeout=2000
配置重试参数
# 对所有http方法进行重试
good-service.ribbon.OkToRetryOnAllOperations=true
# 每个host最大重试次数
good-service.ribbon.MaxAutoRetries=2
# 最大重试几个host
good-service.ribbon.MaxAutoRetriesNextServer=3