《Spring Cloud Netflix官方文档》6. 客户端负载均衡: Ribbon
6. 客户端负载均衡: Ribbon
Ribbon是一个客户端负载均衡,它提供了很多控制来管理HTTP和TCP客户端的行为。Feign已经包含了Ribbon,所以如果你使用了@FeignClient
,这篇文章对你仍然适用。
Ribbon中最核心的概念就是命名客户端。每个负载均衡器都是组件的一部分,这些组件是一起工作的,它们按需向远程服务发起请求。每个组件都有一个应用程序开发人员提供的名称(通过@FeignClient
指定的名称)。Spring Cloud使用RibbonClientConfiguration
按需要为每个命名客户端创建一个ApplicationContext
。这包含(除其他外)ILoadBalancer
,RestClient
和ServerListFilter
。
6.1 怎样使用Ribbon
引入Ribbon到你的项目,需要添加groupId
:org.springframework.cloud
、artifactId
:spring-cloud-starter-ribbon
到你的项目依赖中。详情请参考Spring Cloud配置你的依赖。
6.2 定制你的Ribbon客户端
你可以在Spring Boot配置文件中配置Ribbon相关的外部属性(如<client>.ribbon.*
),这和使用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(Bean的名称为ClassName):
IClientConfig
ribbon客户端配置:DefaultClientConfigImpl
IRule
ribbon规则 : ZoneAvoidanceRuleIPing
ribbonPing:NoOpPing
ServerList<Server>
ribbon服务列表:ConfigurationBasedServerList
ServerListFilter<Server>
ribbon服务过滤列表:ZonePreferenceServerListFilter
ILoadBalancer
ribbon负载均衡器:ZoneAwareLoadBalancer
ServerListUpdater
ribbon服务列表更新器:PollingServerListUpdater
创建这些类型的bean并将其放置在@RibbonClient配置(例如上面的FooConfiguration)中,可以覆盖所描述的每个bean。例如:
@Configuration public class FooConfiguration { @Bean public IPing ribbonPing(IClientConfig config) { return new PingUrl(); } }
这将用PingUrl替代NoOpPing。
6.3 使用属性定制你的Ribbon客户端
从1.2.0版开始,Spring Cloud Netflix现在支持使用属性自定义Ribbon客户端,以便与Ribbon文档兼容。这使您可以在不同的环境启动时更改行为。
支持的属性如下,并以<clientName>.ribbon
为前缀::
NFLoadBalancerClassName
: 需要实现ILoadBalancer
NFLoadBalancerRuleClassName
: 需要实现IRule
NFLoadBalancerPingClassName
: 需要实现IPing
NIWSServerListClassName
: 需要实现ServerList
NIWSServerListFilterClassName
: 需要实现ServerListFilter
在这些属性中定义的类优先于使用
@RibbonClient(configuration = MyRibbonConfig.class)
定义的bean和Spring Cloud Netflix提供的默认类。
要为服务名称用户设置IRule,您可以设置以下内容:
application.yml
users:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
有关Ribbon提供的实现,请参阅Ribbon文档](https://github.com/Netflix/ribbon/wiki/Working-with-load-balancers)。
6.4 使用Ribbon和Eureka
当Eureka与Ribbon一起使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList
覆盖从Eureka服务器获取服务列表。IPing
会被NIWSDiscoveryPing
覆盖以委托给Eureka检测服务是否启动。ServerList
的默认实现是DomainExtractingServerList
,它是确保物理元数据对负载均衡器可用,而不是使用AWS AMI元数据。默认情况下,服务器列表将使用实例元数据中提供的“Zone”信息构建(所以在远程客户端上设置eureka.instance.metadataMap.zone
),如果缺少这个信息,可以使用服务器主机中的域名作为区域(如果标志approximateZoneFromHostname
被设置)。一旦有区域信息可用,就可以在ServerListFilter
中使用。默认情况下,客户端将使用与客户端在同一区域的服务器,因为ZonePreferenceServerListFilter
是ServerListFilter
的默认实现。客户端的区域设置方式与远程实例相同,即通过eureka.instance.metadataMap.zone
。
6.5 示例: 如何在没有Eureka时使用Ribbon
通过Eureka可以方便的发现远程服务,而不用硬编码URL到代码中,但如果你不想使用它Ribbon和Feign仍然可以使用。假设你已经声明了一个@RibbonClient作为“stores”,并且没有使用Eureka(甚至不在类路径中)。 Ribbon客户端默认有一个服务器列表,而你也可以像这样指定:
application.yml
stores:
ribbon:
listOfServers: example.com,google.com
6.6 示例: 禁止Ribbon使用Eureka
在属性中添加ribbon.eureka.enabled = false
禁止Ribbon使用Eureka
application.yml
ribbon:
eureka:
enabled: false
6.7 直接使用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 } }
6.8 缓存Ribbon的配置
每个Ribbon的命名客户端都有一个Spring Cloud维护的子应用程序上下文,这个应用程序上下文在第一个请求到客户端的时候才会被加载。 你可以通过指定Ribbon客户端的名称让应用启动时立即加载这个上下文。
application.yml
ribbon:
eager-load:
enabled: true
clients: client1, client2, client3