新Spring Cloud(3)Ribbon负载均衡原理和策略、饥饿加载

在之前,我们使用Eureka实现负载均衡是通过注解@LoadBalanced,对于这个注解里面是怎样实现的拉取和负载均衡等,都一概不知。

该注解的负载均衡是通过Ribbon这个组件实现的

一:负载均衡流程(原理)

当消费者通过地址发起请求去访问服务时:

  1. 因为地址不是申请的域名或IP,所以是无法实现直接在浏览器去访问这个地址的
  2. cloud中,该请求会去访问Ribbon(负载均衡组件),通过其去找到真实的地址
  3. Ribbon获取到请求地址后,获取到服务名称,将会去访问eureka-server拉取该服务名称
  4. eureka-server有的话,就会将该服务列表返回给Ribbon
  5. Ribbon获取到服务列表后,会通过负载均衡挑选具体的服务
  6. 基本逻辑如下图所示:
    在这里插入图片描述
    在这里插入图片描述
    发出的请求从http://userservice/user/1,变成了http://localhost:8081?请看下一节源码分析

二:源码分析(代码执行流程)

在启动类中,我们通过给RestTemplatejia了一个注解,这个注解就是一个标记(标记当前这个RestTemplatejia发起的请求会被Ribbon去拦截和处理
在这里插入图片描述
LoadBalancerInterceptor(这个类会根据service名称,获取到了服务实例的ip和端口),这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

2.1 LoadBalancerIntercepor

请添加图片描述
其实现了ClientHttpRequestInterceptor:这个接口会将客户端发起的http请求拦截

  1. 实现了intercept方法,拦截了用户的HttpRequest请求
  2. intercept方法里面通过request.getURI():获取请求uri,本例中就是 http://user-service/user/8
  3. intercept方法里面通过 originalUri.getHost():获取uri路径的主机名,其实就是服务id,user-service
  4. intercept方法里面通过this.loadBalancer.execute():处理服务id,和用户请求。this.loadBalancerLoadBalancerClient类型

2.2 LoadBalancerClient

请添加图片描述
执行流程:

  1. getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会根据服务id去eureka中获取服务列表并保存起来,到loadBalancer。
  2. getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务
  3. 放行后,再次访问并跟踪,发现获取的是8081:实现了负载均衡。在这里已经实现了拉取服务列表这一步
    请添加图片描述

2.2 负载均衡策略IRule

在2.1中,获取服务使通过一个getServer方法来做负载均衡的
请添加图片描述
进入下一步:还是在当前类中

请添加图片描述
继续下一步,其会在其他类ZoneAwareLoadBalancer这个类中,执行return super.chooseServer(key)
在这里插入图片描述
继续下一步,会进入另一个类中,进入源码,查看chooseServer方法,发现这么一段代码:
请添加图片描述
查看rule,
在这里插入图片描述
这里的rule默认值是一个RoundRobinRule,看类的介绍;是轮询的意思。
请添加图片描述

三:流程总结

在这里插入图片描述

四:负载均衡策略

在该节里面,将详细的解释IRule这个接口的实现,及修改这些实现

4.1 负载均衡规则接口

默认的实现是ZoneAvoidanceRule,

Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则:
请添加图片描述

4.2 负载均衡有的规则含义

不同规则的含义如下:

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的< clientName>.< clientConfigNameSpace>.ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

4.3 调整负载均衡方案

注意,一般用默认的负载均衡规则,不做修改。

4.3.1 方法一:代码方式

在消费者的启动类Application类中,定义一个新的IRule:
如下所示:将会实现RandomRule(),配置过后,规则将会从轮询变为随机

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

作用于全局的,一旦这样配置过后,不管是调用哪一个服务,都是随机

4.3.2 方法二:配置文件方式

在消费者的application.yml配置文件文件中,添加新的配置也可以修改规则:

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

针对某个微服务配置的

五:饥饿加载

Ribbon 默认是采用懒加载

  • 懒加载:即第一次访问时才会去创建LoadBalanceClient,还要去拉取,所以请求时间会很长。

饥饿加载则会在项目启动时创建,降低第一次访问的耗时

通过下面配置开启饥饿加载:

  1. 只有一个的话:
    ribbon:
      eager-load:
        enabled: true #开启饥饿加载
        clients: userservice #指定对哪一个服务(userservice)饥饿加载
    
  2. 如果有多个的话
    ribbon:
      eager-load:
        enabled: true #开启饥饿加载
        clients:  #指定对哪一个服务(userservice)饥饿加载
        	- userservice
        	- 其他service
    

六:总结

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

?abc!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值