Spring Cloud 參考文檔(客戶端負載均衡器:Ribbon)

客戶端負載均衡器:Ribbon

Ribbon是一個客戶端負載均衡器,可讓你對HTTP和TCP客戶端的行爲進行大量控制,Feign已經使用了Ribbon,所以,若是你使用@FeignClient,此部分也適用。java

Ribbon中的一個核心概念是命名客戶端,每一個負載均衡器都是一組組件的一部分,這些組件一塊兒工做以按需聯繫遠程服務器,而且該集合具備你做爲應用程序開發人員提供的名稱(例如,經過使用@FeignClient註解)。根據須要,Spring Cloud經過使用RibbonClientConfiguration爲每一個命名客戶端建立一個新的集合做爲ApplicationContext,這包含(除其餘外)ILoadBalancerRestClientServerListFiltergit

如何包含Ribbon

要在項目中包含Ribbon,使用組ID爲org.springframework.cloud和工件ID爲spring-cloud-starter-netflix-ribbongithub

自定義Ribbon客戶端

你可使用<client>.ribbon.*中的外部屬性配置Ribbon客戶端的某些,這相似於使用原生Netflix API,但你可使用Spring Boot配置文件,能夠在CommonClientConfigKey(ribbon-core的一部分)中將原生選項做爲靜態字段進行檢查。spring

Spring Cloud還容許你經過使用@RibbonClient聲明其餘配置(在RibbonClientConfiguration之上)來徹底控制客戶端,如如下示例所示:segmentfault

@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}

在這種狀況下,客戶端由RibbonClientConfiguration中已有的組件以及CustomConfiguration(後者一般覆蓋前者)中的任何組件組成。緩存

CustomConfiguration類必須是 @Configuration類,但要注意它不在 @ComponentScan中用於主應用程序上下文,不然,它由全部 @RibbonClients共享。若是使用 @ComponentScan(或 @SpringBootApplication),則須要採起措施以免包含它(例如,你能夠將其放在單獨的非重疊包中,或指定要在 @ComponentScan中顯式掃描的包)。

下表顯示了Spring Cloud Netflix默認爲Ribbon提供的bean:服務器

Bean類型 Bean名稱 類名稱
IClientConfig ribbonClientConfig DefaultClientConfigImpl
IRule ribbonRule ZoneAvoidanceRule
IPing ribbonPing DummyPing
ServerList<Server> ribbonServerList ConfigurationBasedServerList
ServerListFilter<Server> ribbonServerListFilter ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer ZoneAwareLoadBalancer
ServerListUpdater ribbonServerListUpdater PollingServerListUpdater

建立其中一種類型的bean並將其置於@RibbonClient配置(例以下面的FooConfiguration)中,能夠覆蓋所描述的每一個bean,如如下示例所示:app

@Configuration
protected static class FooConfiguration {
    @Bean
    public ZonePreferenceServerListFilter serverListFilter() {
        ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
        filter.setZone("myTestZone");
        return filter;
    }

    @Bean
    public IPing ribbonPing() {
        return new PingUrl();
    }
}

前面示例中的語句將NoOpPing替換爲PingUrl,並提供自定義serverListFilter負載均衡

自定義全部Ribbon客戶端的默認值

可使用@RibbonClients註解並註冊默認配置爲全部Ribbon客戶端提供默認配置,如如下示例所示:測試

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
public class RibbonClientDefaultConfigurationTestsConfig {

    public static class BazServiceList extends ConfigurationBasedServerList {
        public BazServiceList(IClientConfig config) {
            super.initWithNiwsConfig(config);
        }
    }
}

@Configuration
class DefaultRibbonConfig {

    @Bean
    public IRule ribbonRule() {
        return new BestAvailableRule();
    }

    @Bean
    public IPing ribbonPing() {
        return new PingUrl();
    }

    @Bean
    public ServerList<Server> ribbonServerList(IClientConfig config) {
        return new RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
    }

    @Bean
    public ServerListSubsetFilter serverListFilter() {
        ServerListSubsetFilter filter = new ServerListSubsetFilter();
        return filter;
    }

}

經過設置屬性自定義Ribbon客戶端

從版本1.2.0開始,Spring Cloud Netflix如今支持經過將屬性設置爲與Ribbon文檔兼容來自定義Ribbon客戶端。

這使你能夠在不一樣環境中啓動時更改行爲。

如下列表顯示了支持的屬性:

  • <clientName>.ribbon.NFLoadBalancerClassName:應該實現ILoadBalancer
  • <clientName>.ribbon.NFLoadBalancerRuleClassName:應該實現IRule
  • <clientName>.ribbon.NFLoadBalancerPingClassName:應該實現IPing
  • <clientName>.ribbon.NIWSServerListClassName:應該實現ServerList
  • <clientName>.ribbon.NIWSServerListFilterClassName:應該實現ServerListFilter
這些屬性中定義的類優先於使用 @RibbonClient(configuration=MyRibbonConfig.class)定義的bean以及Spring Cloud Netflix提供的默認值。

要爲名爲users的服務名稱設置IRule,你能夠設置如下屬性:

application.yml

users:
  ribbon:
    NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

有關Ribbon提供的實現,請參閱Ribbon文檔

使用Ribbon與Eureka

當Eureka與Ribbon一塊兒使用時(即二者都在類路徑上),ribbonServerListDiscoveryEnabledNIWSServerList的擴展覆蓋,該擴展填充Eureka的服務器列表,它還用NIWSDiscoveryPing替換IPing接口,它委託Eureka肯定服務器是否啓動,默認狀況下安裝的ServerListDomainExtractingServerList,其目的是在不使用AWS AMI元數據的狀況下使負載均衡器可使用元數據(這是Netflix所依賴的)。默認狀況下,服務器列表使用「zone」信息構建,如實例元數據中所提供的(所以,在遠程客戶端上,設置eureka.instance.metadataMap.zone)。若是缺乏該標誌而且設置了approximateZoneFromHostname標誌,則可使用服務器主機名中的域名做爲區域的代理,區域信息可用後,能夠在ServerListFilter中使用。默認狀況下,它用於在與客戶端相同的區域中查找服務器,由於默認值爲ZonePreferenceServerListFilter,默認狀況下,客戶端區域的肯定方式與遠程實例相同(即經過eureka.instance.metadataMap.zone)。

設置客戶端區域的傳統「archaius」方法是經過名爲「@zone」的配置屬性,若是可用,Spring Cloud優先於全部其餘設置使用它(請注意,必須在YAML配置中引用該鍵)。
若是沒有其餘區域數據源,則根據客戶端配置進行猜想(與實例配置相反),獲取 eureka.client.availabilityZones,它是從region名稱到zone列表的映射,併爲實例本身的region 拉出第一個zone(即 eureka.client.region,默認爲「us-east-1」,以便與原生Netflix兼容)。

示例:如何在沒有Eureka的狀況下使用Ribbon

Eureka是一種抽象遠程服務器發現的便捷方式,所以你無需在客戶端中對其URL進行硬編碼,可是,若是你不想使用Eureka,Ribbon和Feign也可使用。假設你已爲「stores」聲明瞭@RibbonClient,而且未使用Eureka(甚至在類路徑中也沒有),Ribbon客戶端默認爲已配置的服務器列表,你能夠按以下方式提供配置:

application.yml

stores:
  ribbon:
    listOfServers: example.com,google.com

示例:禁用在Ribbon中使用Eureka

ribbon.eureka.enabled屬性設置爲false會顯式禁用在Ribbon中使用Eureka,如如下示例所示:

application.yml

ribbon:
  eureka:
   enabled: false

直接使用Ribbon API

你也能夠直接使用LoadBalancerClient,如如下示例所示:

public class MyClass {
    @Autowired
    private LoadBalancerClient loadBalancer;

    public void doStuff() {
        ServiceInstance instance = loadBalancer.choose("stores");
        URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
        // ... do something with the URI
    }
}

Ribbon配置的緩存

每一個Ribbon命名客戶端都有一個Spring Cloud維護的相應子應用程序上下文,在對命名客戶端的第一次請求上延遲加載此應用程序上下文,經過指定Ribbon客戶端的名稱,能夠將此延遲加載行爲更改成在啓動時急切地加載這些子應用程序上下文,如如下示例所示:

application.yml

ribbon:
  eager-load:
    enabled: true
    clients: client1, client2, client3

如何配置Hystrix線程池

若是將zuul.ribbonIsolationStrategy更改成THREAD,則Hystrix的線程隔離策略將用於全部路由,在這種狀況下,HystrixThreadPoolKey設置爲RibbonCommand做爲默認值,這意味着全部路由的HystrixCommands都在同一個Hystrix線程池中執行,可使用如下配置更改此行爲:

application.yml

zuul:
  threadPool:
    useSeparateThreadPools: true

前面的示例致使每一個路由都在Hystrix線程池中執行HystrixCommands。

在這種狀況下,默認HystrixThreadPoolKey與每一個路由的服務ID相同,要向HystrixThreadPoolKey添加前綴,請將zuul.threadPool.threadPoolKeyPrefix設置爲要添加的值,如如下示例所示:

application.yml

zuul:
  threadPool:
    useSeparateThreadPools: true
    threadPoolKeyPrefix: zuulgw

如何爲Ribbon的IRule提供一個鍵

若是你須要提供本身的IRule實現來處理特殊的路由要求,如「canary」測試,請將一些信息傳遞給IRulechoose方法。

com.netflix.loadbalancer.IRule.java

public interface IRule{
    public Server choose(Object key);
         :

你能夠提供IRule實現用於選擇目標服務器的一些信息,如如下示例所示:

RequestContext.getCurrentContext()
              .set(FilterConstants.LOAD_BALANCER_KEY, "canary-test");

若是使用FilterConstants.LOAD_BALANCER_KEY的鍵將任何對象放入RequestContext,則會將其傳遞給IRule實現的choose方法,必須在執行RibbonRoutingFilter以前執行前面示例中顯示的代碼,Zuul的預過濾器是最好的選擇。你能夠經過預過濾器中的RequestContext訪問HTTP headers和查詢參數,所以能夠用它來肯定傳遞給Ribbon的LOAD_BALANCER_KEY,若是未在RequestContext中爲LOAD_BALANCER_KEY設置任何值,則將null做爲choose方法的參數傳遞。


上一篇:Hystrix超時和Ribbon客戶端

下一篇:外部配置:Archaius

相關文章
相關標籤/搜索