9.與springcloud結合

一、簡介

使用ribbon,一般都是和springcloud結合使用,springcloud提供了膠水代碼來整合ribbon。

二、接口

ServiceInstanceChooser該接口只有一個方法:

public interface ServiceInstanceChooser {
    /**
     * Choose a ServiceInstance from the LoadBalancer for the specified service
     * @param serviceId the service id to look up the LoadBalancer
     * @return a ServiceInstance that matches the serviceId
     */
    ServiceInstance choose(String serviceId);
}

其實現類如下:
在這裏插入圖片描述
我們可以看到好多Retry開頭的,這些類的實例會被自動注入,如果class路徑發現org.springframework.retry.support.RetryTemplate的話。

也就是說,默認情況下,並沒有開啓retry功能。如果需要開啓retry機制,需要引入以下配置:

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

這裏對於retry相關的不再多寫,詳細請參考重試

那麼,默認的就只有一個類了,就是RibbonLoadBalancerClient。

三、實現

這裏看一下如何實現choose的:

  1. 首先對於每個serviceId,spring會創建一個單獨的ILoadBalancer。
  2. 之後調用ILoadBalancer.chooseServer(“default”),這裏就對應到了負載均衡器的ZoneAwareLoadBalancer.choose流程。

四、與RestTemplate整合

參照[結合ribbonLoadBalanced]的部分,整個調用過程如下:
在這裏插入圖片描述
可以看到,調用鏈還是比較長的,最終會調用到ILoadBalancer,實現負載均衡。

五、與Feign整合

從spring-cloud-netflix-core/META-INF/sping.factories可以看到這個自動注入類:FeignRibbonClientAutoConfiguration,它的condition如下:

@ConditionalOnClass({ ILoadBalancer.class, Feign.class })

也就是說,如果classpath存在ribbon的依賴和Feign的依賴,將啓用該配置。

那麼注入的feign使用的http客戶端是哪個?

1.HttpURLConnection的
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
        SpringClientFactory clientFactory) {
    return new LoadBalancerFeignClient(new Client.Default(null, null),
            cachingFactory, clientFactory);
}
2.httpclient的
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
protected static class HttpClientFeignLoadBalancedConfiguration {
    @Autowired(required = false)
    private HttpClient httpClient;
    @Bean
    @ConditionalOnMissingBean(Client.class)
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
            SpringClientFactory clientFactory) {
        ApacheHttpClient delegate;
        if (this.httpClient != null) {
            delegate = new ApacheHttpClient(this.httpClient);
        }
        else {
            delegate = new ApacheHttpClient();
        }
        return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
    }
}
3.okhttp的
@Configuration
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty(value = "feign.okhttp.enabled", matchIfMissing = true)
protected static class OkHttpFeignLoadBalancedConfiguration {
    @Autowired(required = false)
    private okhttp3.OkHttpClient okHttpClient;
    @Bean
    @ConditionalOnMissingBean(Client.class)
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
            SpringClientFactory clientFactory) {
        OkHttpClient delegate;
        if (this.okHttpClient != null) {
            delegate = new OkHttpClient(this.okHttpClient);
        }
        else {
            delegate = new OkHttpClient();
        }
        return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
    }
}

httpclient和okhttp都有static修飾,那麼就會比HttpURLConnection先加載。

而httpclient和okhttp取決於pom裏依賴了那個jar,例如依賴feign-okhttp則爲okhttp:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

依賴feign-httpclient則爲httpclient:


<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

無論用哪個http客戶端,可以看到,最終都傳給了LoadBalancerFeignClient,該類最終會調用到ILoadBalancer的choose方法,流程如下圖:
在這裏插入圖片描述
到這裏看到ILoadBalancer就清楚了,跟之前的負載均衡器結合起來了

發佈了62 篇原創文章 · 獲贊 23 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章