客户端负载均衡:Ribbon
Ribbon是一个客户端的负载均衡器,可以提供很多HTTP和TCP的控制行为。Feign已经使用了Ribbon,所以如果你使用了@FeignClient,Riboon也同样被应用了。
Ribbon核心的概念是named client。每个负载均衡器都是共同体的一部分,可以一起运行去连接远程服务器,你会给你的应用设置一个名字(比如使用@FeignClient注解)。Spring Cloud creates a new ensemble as an ApplicationContext on demand for each named client using RibbonClientConfiguration. This contains (amongst other things) an ILoadBalancer, a RestClient, and a ServerListFilter.
如何引入Ribbon
org.springframework.cloud and artifact id spring-cloud-starter-ribbon. 查看详情 Spring Cloud Project page
定制Ribbon Clietn
你可以配置一些Ribbon client的属性在外部的属性文件里(application.properties/yml),如.ribbon.*,这个和Netflix APIS本身没有什么不同。本机选项可以被检查使用CommonClientConfigKey等静态字段。
Spring cloud还允许你完全控制客户端通过声明额外的配置,使用@RibbonClient(位于RibbonClientConfiguration的顶部)。
例如:
@Configuration @RibbonClient(name="foo",configuration=FooConfiguration.class) public class TestConfiguration{ }
In this case the client is composed from the components already in RibbonClientConfiguration together with any in FooConfiguration (where the latter generally will override the former).
警告:FooConfiguration已经设置为@Configuration,但是注意它不是@ComponentScan在主程序上下文,另外它会被所有的@RibbonClients共享。如果你使用了@ComponentScan(或者@SpringBootApplication)你需要采取措施去避免引入。(例如把他分割开来,不要重叠包,或者指定明确的包路径在@ComponentScan)。
Spring Cloud Netflix默认为Ribbon提供了如下beans(BeanType beanName:ClassName):
* IClientConfig ribbonClientConfig: DefaultClientConfigImpl * IRule ribbonRule: ZoneAvoidanceRule * IPing ribbonPing: NoOpPing * ServletList ribbonServerList: ConfigurationBasedServerlList * ServerListFilter ribbonServerListFilter: * ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
创建一个这些类型的一个Bean放置到@RibbonClient配置类中(就像上面的FooConfiguration一样),它允许你重写每一个bean的描述。例如:
@Configuration public class FooConfiguation { @Bean public IPing ribbonPing(IClientConfig config){ return new PingUrl(); } }
这里使用PingUrl替换了NoOpPing。
Customizing the ribbon client using properties
从1.2.0版本开始,sping cloud netflix支持使用配置文件的方式定制RibbOn clients并且与文档兼容 Ribbon documentation
这允许你在不同环境中,改变启动时的行为。
这些属性都列在下面,并且他们必须使用 .ribbon.作为前缀。
* NFLoadBalancerClassName: should implement ILoadBalancer * NFLoadBalanceerRuleClassName: should implement IRuld * NFLoadBalancePingClassName: should implement IPing * NIWSServerListClassName: should implement ServerList * NIWServerListFilterClassName: should implement ServerListFilter
注意: 类中定义了这些属性将会优先于@RibbonClient(configuration=MyRibbonConfig.class),默认的是Spring Cloud Netflix提供了。
给服务名为user设置IRule,你可以如下设置:
application.yml
user:
ribbon:
NFLoadBalancerRuleClassName:com.netflix.loadbalancer.WeightedResponseTimeRule
从 Ribbon documentation 查看Ribbon的实现。
Using Ribbon with Eureka
当Eureka跟Ribbon结合使用的时候(都在classpath),ribbonServerList会被一个外部的DiscoveryEnabledNIWServerList重写,它填充了服务懒得列表从Eureka中。它同样使用了NIWDiscoveryPing替换了IPing,它让Eureka去确定一个server是否启动。serverList默认使用的是DomainExtractingServerList,目的是让物理元数据用于负载均衡器而不是AWS AMI(这是Netflix依赖的)。默认srverlist会构造”zone”信息提供给实例使用(远程客户端设置eureka.instance.metadataMap.zone),如果没有设置它可以使用域名服务器的主机名作为区域代理(如果approximateZoneFromHostname被设置了)。一旦zone信息可用,它也会被用在ServerListFilter。默认它会用来定位一个客户端在同一个zone,因为默认的是ZonePrefeerenceServerListFilter。client的zone默认跟远程实例的一样。i.e. eureka.instance.metadataMap.zone。
注意:正统的“archaius”方式设置client zone是通过配置属性”@zone”,Sping Cloud将会优先使用这个设置(它会去引用YAML的配置)。
注意:If there is no other source of zone data then a guess is made based on the client configuration (as opposed to the instance configuration). We take eureka.client.availabilityZones, which is a map from region name to a list of zones, and pull out the first zone for the instance’s own region (i.e. the eureka.client.region, which defaults to “us-east-1” for comatibility with native Netflix).
Example:How to Use Ribbon Without Eureka
Eureka是一个方便的方式去抽象远程服务发现,所以你不需要在客户端硬编码他们的URLS。但是如果你不想用eureka,Ribbon和Feign仍然可用。假设你已经在“stores”定义了@RibbOnClient,而且没有使用Eureka(没有在classpath中)。Ribbon client默认要配置server list,你可以提供配置像这样:
application.yml
stores:
ribbon:
listOfServers: example.com.google.com
Example:Disable Eureka use in Ribbon
设置property ribbon.eureka.enable=false将会明确的让Eureka的ribbon失效。
application.yml ribbon: eureka: enabled: false
Using the Ribbon API Directly
你也可以直接使用 LoadBalancerClient。例如:
public class MyClass { @Autowired private LoadBalancerClient loadBalancer; public void dostuff(){ ServiceInstance instance = loadBalancer.choose("stors"); URI storeUri = URI.create(String.format("httP://%s:%s",instance.getHost(),instance.getPort())); //... do something with the URI } }
posted on 2017-03-20 23:13 ilinux_one 阅读(1170) 评论(0) 编辑 收藏 举报