背景
- 早上刷圈看到 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
- 以上源码 https://github.com/pigxcloud/big
- 欢迎关注 基于 Spring Boot 2.1.7、Spring Cloud Greenwich.SR2、OAuth2 的 RBAC 权限管理系统
- 欢迎关注我们获得更多的好玩 JavaEE 实践