【spring cloud hoxton】Ribbon 真的能被 spring-cloud-loadbalancer 替代嗎

背景

  • 早上刷圈看到 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 的淵源
  1. 2017年spring 開始嘗試開發新的項目 spring-cloud-loadbalancer 替代ribbon,項目託管在

spring-cloud-incubator 孵化器
(多提一嘴,spring cloud alibaba 等頂級的項目大多從此孵化出來的,代表着 spring cloud 的發展方向)

  1. 經過N個月的不維護,還以爲spring 放棄此項目時,突然把此項目標記成歸檔遷移到spring-cloud-commons
  2. 發佈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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章