Spring Cloud Netflix之客户端负载均衡器:Ribbon

Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制。Feign已经在使用Ribbon了,所以如果你在使用@FeignClient,那么这个部分也适用。

Ribbon中的一个核心概念是命名客户端。每个负载均衡器都是组件集合的一部分,这些组件一起工作,根据需要联系远程服务器,集成有一个名称,作为应用程序开发人员使用(比如:使用@FeignClient注解)。Spring Cloud使用RibbonClientConfiguration根据需要为每个命名客户端创建一个新的集成作为ApplicationContext。其中包括一个ILoadBalancer、一个RestClient和一个ServerListFilter。

怎样引入Ribbon

项目中引入Ribbon,通过starter使用group org.springframework.cloud and artifact id spring-cloud-starter-netflix-ribbon

定制Ribbon客户端

您可以使用.ribbon.*中的外部属性配置Ribbon客户机的一些位。除了可以使用Spring Boot configuration files之外,这与本地使用Netflix api没有什么不同。可以在CommonClientConfigKey(ribbon-core的一部分)中将本机选项检查为静态字段。

Spring Cloud还允许您使用@RibbonClient声明额外的配置(在RibbonClientConfiguration之上),从而完全控制客户端。例子:

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

在这种情况下,客户端是由RibbonClientConfiguration中已经存在的组件以及FooConfiguration中的任何组件组成的(后者通常会覆盖前者)。

FooConfiguration必须是@Configuration,但是要注意它不是在用于主应用程序上下文的@ComponentScan中,否则它将被所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),您需要采取步骤来避免包含它(例如,将它放在一个单独的、不重叠的包中,或者指定在@ComponentScan中显式扫描的包)。Spring Cloud Netflix默认为ribbon提供了以下bean (BeanType beanName: ClassName):

  • IClientConfig ribbonClientConfig: DefaultClientConfigImpl
  • IRule ribbonRule: ZoneAvoidanceRule
  • IPing ribbonPing: DummyPing
  • ServerList ribbonServerList: ConfigurationBasedServerList
  • ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
  • ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
  • ServerListUpdater ribbonServerListUpdater: PollingServerListUpdater

创建其中一种类型的bean并将其放入@RibbonClient配置(如上面的FooConfiguration)中,您可以覆盖所描述的每个bean。例子:

@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();
	}
}

这将用PingUrl替换NoOpPing,并提供一个定制的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 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客户机.

这允许您在不同的环境中在启动时更改行为。

支持的属性列在下面,应该以.ribbon.  作为前缀:

  • NFLoadBalancerClassName: should implement ILoadBalancer
  • NFLoadBalancerRuleClassName: should implement IRule
  • NFLoadBalancerPingClassName: should implement IPing
  • NIWSServerListClassName: should implement ServerList
  • NIWSServerListFilterClassName should implement ServerListFilter

 这些属性中定义的类优先于使用@RibbonClient(配置=MyRibbonConfig.class)定义的bean,以及Spring Cloud Netflix提供的默认值。

要为user服务设置IRule,可以设置以下内容:

application.yml. 

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

Using Ribbon with Eureka

当Eureka与Ribbon一起使用时,使用DiscoveryEnabledNIWSServerList的扩展覆盖ribbonServerList,该扩展填充来自Eureka的服务器列表。它还将IPing接口替换为NIWSDiscoveryPing, NIWSDiscoveryPing委托给Eureka来确定服务器是否已启动。默认安装的ServerList是DomainExtractingServerList,其目的是使负载均衡器可以使用物理元数据,而不使用AWS AMI元数据。默认情况下,服务器列表将按照实例元数据中提供的“zone”信息构造(因此在远程客户机上设置eureka.instance.metadataMap.zone).如果缺少这一点,它可以使用服务器主机名中的域名作为专区的代理(if the flag approximateZoneFromHostname is set)。一旦zone信息可用,就可以在ServerListFilter中使用它。默认情况下,它将用于定位与客户机位于同一区域的服务器,因为默认情况下是一个zone preferenceserverlistfilter。默认情况下,客户机区域的确定方式与远程实例相同,即。通过eureka.instance.metadataMap.zone。

传统的设置客户端区域的“archaius”方法是通过名为“@zone”的配置属性,如果可用,Spring Cloud将优先使用该属性,而不是所有其他设置(请注意,该键必须在YAML配置中引用)。

如果没有其他区域数据源,则根据客户机配置(而不是实例配置)进行猜测。我们把eureka.client。可用性区域,它是从区域名称到区域列表的映射,并为实例自己的区域(即eureka.client)提取第一个区域。区域,默认为“us-east-1”与本地Netflix的兼容性)。

例子:如何在没有Eureka的情况下使用Ribbon

Eureka是一种方便的方法来抽象远程服务器的发现,这样您就不必在客户机中硬编码它们的url,但是如果您不喜欢使用它,Ribbon和Feign仍然非常适合。假设您为“存储”声明了@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

6.10 How to Configure Hystrix thread pools

If you change zuul.ribbonIsolationStrategy to THREAD, the thread isolation strategy for Hystrix will be used for all routes. In this case, the HystrixThreadPoolKey is set to "RibbonCommand" as default. It means that HystrixCommands for all routes will be executed in the same Hystrix thread pool. This behavior can be changed using the following configuration and it will result in HystrixCommands being executed in the Hystrix thread pool for each route.

application.yml. 

zuul:
  threadPool:
    useSeparateThreadPools: true

 

The default HystrixThreadPoolKey in this case is same with service ID for each route. To add a prefix to HystrixThreadPoolKey, set zuul.threadPool.threadPoolKeyPrefix to a value that you want to add. For example:

application.yml. 

zuul:
  threadPool:
    useSeparateThreadPools: true
    threadPoolKeyPrefix: zuulgw

 

6.11 How to Provide a Key to Ribbon’s IRule

If you need to provide your own IRule implementation to handle a special routing requirement like a canary test, you probably want to pass some information to the choose method of IRule.

com.netflix.loadbalancer.IRule.java. 

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

 

You can provide some information that will be used to choose a target server by your IRule implementation like the following:

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

If you put any object into the RequestContext with a key FilterConstants.LOAD_BALANCER_KEY, it will be passed to the choose method of IRule implementation. Above code must be executed before RibbonRoutingFilter is executed and Zuul’s pre filter is the best place to do that. You can easily access HTTP headers and query parameters via RequestContext in pre filter, so it can be used to determine LOAD_BALANCER_KEY that will be passed to Ribbon. If you don’t put any value with LOAD_BALANCER_KEY in RequestContext, null will be passed as a parameter of choose method.

 

你可能感兴趣的:(Spring,Cloud,Netflix)