SpringCloud系列八:自定义Ribbon配置
1. 回顾
上文使用Ribbon实现了客户端侧的负载均衡。但是很多场景下,我们可能需要自定义Ribbon的配置,比如修改Ribbon的负载均衡规则。
Spring Cloud允许使用Java代码或属性自定义Ribbon的配置,这两种方式是等价的。
在Spring Cloud中,Ribbon的默认配置如下(格式是BeanType beanName:ClassName):
- IClientConfig ribbonClientConfig:DefaultClientConfigImpl
- IRule ribbonRule:ZoneAvoidanceRule
- IPing ribbonPing:NoOpPing
- ServerList ribbonServerList:ConfigurationBasedServerList
- ServerListFilter ribbonServerListFilter:ZonePreferenceServerListFilter
- ILoadBalance ribbonLoadBalancer:ZoneAwareLoadBalancer
@Bean
@ConditionalOnMissingBean
public IRule ribbonRule(IClientConfig config) {
if (this.propertiesFactory.isSet(IRule.class, this.name)) {
return (IRule)this.propertiesFactory.get(IRule.class, config, this.name);
} else {
ZoneAvoidanceRule rule = new ZoneAvoidanceRule();
rule.initWithNiwsConfig(config);
return rule;
}
}
// 来自 org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
BeanType是IRule,beanName是ribbonRule,ClassName是ZoneAvoidanceRule,这是一种根据服务提供者所在Zone的性能以及
服务提供者可用性综合计算,选择提供者节点的负载均衡规则。
在Spring Cloud中, Ribbon默认的配置类是RibbonClientConfiguration。也可使用一个POJO自定义Ribbon的配置(自定义配置会覆盖默认配置)。
这种配置是细粒度的,不同的Ribbon客户端可以使用不同的配置。
2. 使用Java代码自定义Ribbon配置
> 复制项目 microservice-consumer-movie-ribbon,将ArtifactId修改为 microservice-consumer-movie-ribbon-customizing
> 创建一个注解类
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing.annotation;
public @interface ExcludeComponent {
}
> 修改启动类,使@CompantScan不扫描被自定义注解注解的类
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
value = {com.itmuch.cloud.microserviceconsumermovieribboncustomizing.annotation.ExcludeComponent.class}))
public class MicroserviceConsumerMovieRibbonCustomizingApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonCustomizingApplication.class, args);
}
@Bean
@LoadBalanced // 实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
> 创建Ribbon的配置类
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing.config;
import com.itmuch.cloud.microserviceconsumermovieribboncustomizing.annotation.ExcludeComponent;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 该类为Ribbon的配置类
* 注意:该类不应该在主应用程序上下文的@ComponentScan中
*/
@Configuration
@ExcludeComponent
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
// 负载均衡规则改为随机
return new RandomRule();
}
}
> 创建一个空类,并在其上添加@Configuration注解和@RibbonClient注解
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing.config;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
/**
* 使用RibbonClient,为特定name的Ribbon Client自定义配置
* 使用@RibbonClient的configuration属性,指定Ribbon的配置类
*/
@Configuration
@RibbonClient(name = "microservice-provider-user", configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
> 启动microservice-discovery-eureka
> 启动两个以上的 microservice-provider-user 实例
> 多次访问 http://localhost:8010/log-instance,可获取类似如下的日志,表明负载均衡规则已改为随机
3. 使用属性自定义Ribbon配置
从Spring Cloud Netflix1.2.0开始,Ribbon支持使用属性自定义Ribbon客户端。这种方式比使用Java代码配置的方式更加方便。
支持的属性如下,配置的前缀是<clientName>.ribbon.
- NFLoadBalancerClassName:配置ILoadBalancer的实现类
- NFLoadBalancerRuleClassName:配置IRule的实现类
- NFLoadBalancerPingClassName:配置IPing的实现类
- NIWSServerListClassName:配置ServerList的实现类
- NIWSServerListFilterClassName:配置ServerListFilter的实现类
> 复制项目 microservice-consumer-movie-ribbon,将ArtifactId修改为 microservice-consumer-movie-ribbon-customizing-properties
> 在application.yml中添加一下内容
microservice-provider-user:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
> 测试过程同上
4. 总结
对于使用Java代码自定义Ribbon配置的过程中,可指定该配置只对某个Ribbon客户端生效,也可对所有的Ribbon客户端生效
若只对某个Ribbon客户端生效,则RibbonConfiguration类不能包含在主应用程序上下文的@CompantScan中,所以本文添加了自定义注解,
使用自定义注解和excludeFilters使RibbonConfiguration类不被@CompantScan扫描到
若想对所有的Ribbon客户端生效,只须将RibbonConfiguration类包含在主应用程序上下文的@CompantScan中即可。
下文将继续讲解脱离Eureka使用Ribbon,敬请期待~~~
5. 参考
周立 --- 《Spring Cloud与Docker微服务架构与实战》