Ribbon是一种客户端负载平衡器,可让您对HTTP和TCP客户端的行为进行大量控制。Feign已使用Ribbon,因此,如果使用@FeignClient,则本节也适用。
Ribbon中的中心概念是指定客户的概念。每个负载均衡器都是组件的一部分,这些组件可以一起工作以按需联系远程服务器,并且该组件具有您作为应用程序开发人员提供的名称(例如,使用@FeignClient批注)。根据需要,Spring Cloud通过使用RibbonClientConfiguration为每个命名的客户端创建一个新的集合作为ApplicationContext。其中包含ILoadBalancer,RestClient和ServerListFilter。
要将Ribbon包含在您的项目中,请使用起始者,其组ID为org.springframework.cloud,工件ID为spring-cloud-starter-netflix-ribbon。
您可以使用
Spring Cloud还允许您通过使用@RibbonClient声明其他配置(在RibbonClientConfiguration之上)来完全控制客户端,如以下示例所示:
@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}
在这种情况下,客户端由RibbonClientConfiguration中已有的组件以及CustomConfiguration中的任何组件组成(其中后者通常会覆盖前者)。
[警告]
CustomConfiguration类必须是@Configuration类,但请注意,对于主应用程序上下文,它不在@ComponentScan中。否则,它由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免将其包括在内(例如,可以将其放在单独的,不重叠的程序包中,或指定要在@ComponentScan)。
下表显示了Spring Cloud Netflix默认为Ribbon提供的beans:
Bean类型Bean名称班级名称
IClientConfig
ribbonClientConfig
DefaultClientConfigImpl
IRule
ribbonRule
ZoneAvoidanceRule
IPing
ribbonPing
DummyPing
ServerList
ribbonServerList
ConfigurationBasedServerList
ServerListFilter
ribbonServerListFilter
ZonePreferenceServerListFilter
ILoadBalancer
ribbonLoadBalancer
ZoneAwareLoadBalancer
ServerListUpdater
ribbonServerListUpdater
PollingServerListUpdater
创建其中一种类型的bean并将其放置在@RibbonClient配置中(例如上述FooConfiguration),您可以覆盖所描述的每个beans,如以下示例所示:
@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();
}
}
上一示例中的include语句将NoOpPing替换为PingUrl,并提供了自定义serverListFilter。
通过使用@RibbonClients批注并注册默认配置,可以为所有Ribbon客户端提供默认配置,如以下示例所示:
@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;
}
}
从版本1.2.0开始,Spring Cloud Netflix现在支持通过将属性设置为与Ribbon文档兼容来自定义Ribbon客户端。
这使您可以在启动时在不同环境中更改行为。
以下列表显示了受支持的属性>:
.ribbon.NFLoadBalancerClassName:应实施ILoadBalancer
.ribbon.NFLoadBalancerRuleClassName:应实施IRule
.ribbon.NFLoadBalancerPingClassName:应实施IPing
.ribbon.NIWSServerListClassName:应实施ServerList
.ribbon.NIWSServerListFilterClassName:应实施ServerListFilter
[注意]
这些属性中定义的类优先于使用@RibbonClient(configuration=MyRibbonConfig.class)定义的beans和Spring Cloud Netflix提供的默认值。
要为名为users的服务名称设置IRule,可以设置以下属性:
application.yml。
users:
ribbon:
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
当Eureka与Ribbon结合使用时(也就是说,两者都在类路径上),ribbonServerList被扩展名DiscoveryEnabledNIWSServerList覆盖,这将填充{71中的服务器列表/}。它还用NIWSDiscoveryPing替换了IPing接口,该接口委托给Eureka确定服务器是否启动。默认安装的ServerList是DomainExtractingServerList。其目的是不使用AWS AMI元数据(这就是Netflix所依赖的)使元数据可用于负载均衡器。默认情况下,服务器列表是使用实例元数据中提供的“ zone ”信息构建的(因此,在远程客户端上,设置为eureka.instance.metadataMap.zone)。如果缺少该字段,并且设置了approximateZoneFromHostname标志,则它可以使用服务器主机名中的域名作为该区域的代理。一旦区域信息可用,就可以在ServerListFilter中使用它。默认情况下,它用于在与客户端相同的区域中定位服务器,因为默认值为ZonePreferenceServerListFilter。默认情况下,以与远程实例相同的方式(即通过eureka.instance.metadataMap.zone)确定客户端的区域。
[注意]
设置客户端区域的传统“ archaius ”方法是通过名为“ @zone”的配置属性。如果可用,Spring Cloud优先于所有其他设置使用该设置(请注意,该键必须在YAML配置中用引号引起来)。
[注意]
如果没有其他区域数据源,则根据客户端配置(而不是实例配置)进行猜测。我们取eureka.client.availabilityZones(这是从区域名称到区域列表的映射),然后为实例自己的区域拉出第一个区域(即eureka.client.region,其默认值为“ us-east-1” ”,以与本机Netflix兼容)。
Eureka是一种抽象发现远程服务器的便捷方法,因此您不必在客户端中对它们的URL进行硬编码。但是,如果您不想使用Eureka,则Ribbon和Feign也可以使用。假设您为“商店”声明了@RibbonClient,并且Eureka未被使用(甚至不在类路径上)。Ribbon客户端默认为配置的服务器列表。您可以提供以下配置:
application.yml。
stores:
ribbon:
listOfServers: example.com,google.com
将ribbon.eureka.enabled属性设置为false会显式禁用Ribbon中的Eureka,如以下示例所示:
application.yml。
ribbon:
eureka:
enabled: false
您也可以直接使用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命名的客户端都有一个相应的子应用程序上下文,Spring Cloud维护该上下文。该应用程序上下文在对命名客户端的第一个请求上延迟加载。通过指定Ribbon客户端的名称,可以更改此延迟加载行为,以代替在启动时急于加载这些子应用程序上下文,如以下示例所示:
application.yml:
ribbon:
eager-load:
enabled: true
clients: client1, client2, client3
如果将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
如果您需要提供自己的IRule实现来处理诸如“ canary ”测试之类的特殊路由要求,请将一些信息传递给IRule的choose方法。
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标头和查询参数,因此可以用来确定传递到Ribbon的LOAD_BALANCER_KEY。如果没有在RequestContext中用LOAD_BALANCER_KEY放置任何值,则将空值作为choose方法的参数传递。