背景
-
早上刷圈看到 Spring Cloud Hoxton.M2 Released 的消息,随手发布到了我的知识星球,过了会有个朋友过来如下问题。抽取半天时间学习spring-cloud-loadbalancer 的源码,整理出此文总结
-
Spring Cloud Hoxton.M2 是第一个整合新的loadbalancer实现来替代Ribbon的版本
Spring Cloud Hoxton.M2 is the first release containing both blocking and non-blocking load balancer client implementations as an alternative to Netflix Ribbon which has entered maintenance mode.
-
spring-cloud-loadbalancer 的渊源
-
2017年spring 开始尝试开发新的项目
spring-cloud-loadbalancer
替代ribbon,项目托管在 spring-cloud-incubator 孵化器 (多提一嘴,spring cloud alibaba 等顶级的项目大多从此孵化出来的,代表着 spring cloud 的发展方向)
-
经过N个月的不维护,还以为spring 放弃此项目时,突然把此项目标记成归档迁移到spring-cloud-commons
-
发布2.2.0.M2 版本
如何使用
-
这里基于 最新的hoxton.m2 版本才可以使用,所以要配置spring的代理maven库
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.M2</version> <type>pom</type> <scope>import</scope> </dependency></dependencyManagement>
-
加入nacos-client 使用 2.1.0版本,特别注意排除 ribbon依赖,不然loadbalancer 无效
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </exclusion> </exclusions></dependency>
-
加入 loadbalancer pom坐标
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId></dependency>
-
配置使用还是和 ribbon 一样配置
-
@Configuration
-
public class LbConfiguration {
-
@Bean
-
@LoadBalanced
-
RestTemplate restTemplate() {
-
return new RestTemplate();
-
}
-
}
-
@GetMapping(\"/demo\")
-
public String doOtherStuff() {
-
return restTemplate.getForObject(\"http://big-provider-server/demo\", String.class);
-
}
源码解析
LoadBalancerClient 实现
-
目前版本只提供了 BlockingLoadBalancerClient 的实现, 注意看中文注释
-
// 删除只保留了核心代码注意
-
public class BlockingLoadBalancerClient implements LoadBalancerClient {
-
@Override
-
public <T> T execute(String serviceId, LoadBalancerRequest<T> request)
-
throws IOException {
-
// 根据 服务名称去查询可用实例
-
ServiceInstance serviceInstance = choose(serviceId);
-
return execute(serviceId, serviceInstance, request);
-
}
-
@Override
-
public ServiceInstance choose(String serviceId) {
-
// 获取负载均衡策略
-
ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory
-
.getInstance(serviceId);
-
// 执行负载均衡策略获取可以实例
-
Response<ServiceInstance> loadBalancerResponse = Mono.from(loadBalancer.choose())
-
.block();
-
return loadBalancerResponse.getServer();
-
}
-
}
loadBalancer 负载均衡策略实现
-
目前只有一个RoundRobinLoadBalancer 轮询选择server的方式
-
public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
-
public Mono<Response<ServiceInstance>> choose(Request request) {
-
ServiceInstanceSupplier supplier = this.serviceInstanceSupplier.getIfAvailable();
-
return supplier.get().collectList().map(instances -> {
-
if (instances.isEmpty()) {
-
log.warn(\"No servers available for service: \" + this.serviceId);
-
return new EmptyResponse();
-
}
-
// TODO: enforce order?
-
int pos = Math.abs(this.position.incrementAndGet());
-
ServiceInstance instance = instances.get(pos % instances.size());
-
return new DefaultResponse(instance);
-
});
-
}
-
}
和ribbon 比较
默认负载均衡比较
-
ribbon 提供7中默认的负载均衡策略,常见的常见都有覆盖,一般我们都是使用
ZoneAvoidanceRule
复合判断server所在区域的性能和server的可用性选择server
配置方面丰富性
-
目前
spring-cloud-loadbalancer
仅支持 重试操作的配置
-
ribbon 支持超时、懒加载处理、重试及其和 hystrix整合高级属性等
结论
-
老老实实用 ribbon