Ribbon负载均衡策略

Ribbon策略描述

@LoadBalance注解详解

要想了解ribbon负载均衡,首先要了解LoadBalance的注入方式。了解@LoadBalance怎么把RestTemplate注入容器的。

/**
 * Annotation to mark a RestTemplate or WebClient bean to be configured to use a
 * LoadBalancerClient.
 * @author Spencer Gibb
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {

}

@Target 注解:表示注解的作用范围,取值如下:

public enum ElementType {
    TYPE, # 类、接口(包括注释类型)或枚举声明
    FIELD, # 字段声明(包括enum常量)
    METHOD, # 方法声明
    PARAMETER, # 正式的参数声明
    CONSTRUCTOR, # 构造函数声明
    LOCAL_VARIABLE, # 局部变量说明
    ANNOTATION_TYPE, # 注解类型声明
    PACKAGE, # 程序包说明 /包说明
    TYPE_PARAMETER, # 类型参数声明
    TYPE_USE # 一种类型的使用
}

@Retention 注解,用来表示注解的生命周期,取值如下:

public enum RetentionPolicy {
    SOURCE, # 只在源文件中起作用,编译的时候就没有了,一般用于检查类的,例如:@Override
    CLASS, # 默认值,作用于class文件,用于在一些预编译处理,不常用。
    RUNTIME # 作用于运行时期,能在运行时动态调用注解。
}

@Documented 注解:

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {

}

当有@Documented生成的api文档时会显示上面的注解,如下:

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Qualifier
public @interface LoadBalanced 

当没有有@Documented生成的api文档时会显示上面的注解,如下:

public @interface LoadBalanced 

@Inherited 注解:

  1. @Inherited只能用于注解类上,修饰在其他地方不起作用。
  2. 被@Inherited表示的注解,自动继承。
    说明:@Inherited标识的注解@Test,修饰在一个类上,那么这个类的子类将自动继承注解@Test。但是@Test修饰在一个接口类上,那么这个接口的子类,或者实现类并不会继承注解@Test。

@Qualifier 注解:

在类注入的时候给类取一个标识,比如一个接口有多个实现类的时候,如果我们用@Autowrite(根据类型注入),就找不到具体的实现类,这时候可以添加@Qualifier(value=“**”)来标识你具体注入的实现类。
上面是一种使用情况,还有一个对要自动装配的类做标识,例如:

 @Bean
    public Date date1(){
        return new Date();
    }

    @Bean
    public Date date2(){
        return new Date();
    }
    
    @Autowired(required = false)
    public List<Date> list = Collections.emptyList();

这时候date1和date2都会被注入到list中,如果添加@Qualifier注解,就只会注入有@Qualifier标识的Bean。

@Bean
    public Date date1(){
        return new Date();
    }
    
    @Qualifier
    @Bean
    public Date date2(){
        return new Date();
    }

    @Qualifier
    @Autowired(required = false)
    public List<Date> list = Collections.emptyList();

在使用Ribbon做负载均衡时注入RestTemplate

在ribbon做负载均衡时,需要在配置类注入RestTemplate:

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

在配置类:org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration中维护了一个RestTemplate的集合

	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

因为@Loadbalanced用了@Qualifier注解,所有所有被@Loadbalanced修饰的RestTemplate都会被注入到restTemplates 之中。

ribbon负载均衡策略

ribbon负载均衡内置的实现方式。
在这里插入图片描述

RoundRobinRule: 轮询策略

WeightedResponseTimeRule: 权重策略

根据每个服务提供者的响应时间分配一个权重,响应时间越长权重越小,被选中的可能性也就越低。 它的实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率也越大。

RandomRule: 随机策略

BestAvailableRule: 最小连接数策略

也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取

RandomRule: 重试策略

按照轮询策略来获取服务,如果获取的服务实例为null或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回null

AvailabilityFilteringRule: 可用性敏感策略

先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例

ZoneAvoidanceRule: 区域敏感策略

根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。

@Bean注入的方式,全局配置

在配置类中注入负载均衡策略,这样是全局的所有的服务都会用这个策略。

    @Bean
    public IRule iRule(){
        return new RandomRule();
    }

通过配置文件配置负载均衡策略

可以指定服务使用负载策略

user-service: # 服务名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

如何通过@Loadbalanced实现负载均衡

1、将RestTemplate注入LoadBalancerAutoConfiguration配置类维护的List< RestTemplate>
2、为RestTemplate的添加LoadBalancerInterceptor拦截器。

@Bean
	public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
			final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
		return () -> restTemplateCustomizers.ifAvailable(customizers -> {
			for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
				for (RestTemplateCustomizer customizer : customizers) {
					customizer.customize(restTemplate);
				}
			}
		});
	}

3、LoadBalancerInterceptor会拦截RestTemplate发出的请求,因为LoadBalancerInterceptor实现了ClientHttpRequestInterceptor接口。

@Override
	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
			final ClientHttpRequestExecution execution) throws IOException {
		final URI originalUri = request.getURI();
		String serviceName = originalUri.getHost();
		Assert.state(serviceName != null,
				"Request URI does not contain a valid hostname: " + originalUri);
		return this.loadBalancer.execute(serviceName,
				this.requestFactory.createRequest(request, body, execution));
	}

这里this.loadBalancer.execute的实现类,RibbonLoadBalancerClient的execute方法,里面的getServer方法实现的负载均衡。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值