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

相关文章
相关标签/搜索