背景
- 早上刷圈看到 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>複製代碼
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>複製代碼
@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整合高級屬性等
結論
