SpringCloud(三) Ribbon负载均衡

SpringCloud(二) Eureka注册中心的使用-CSDN博客

在SpringCloud(二)中学习了如何通过Eureka实现服务的注册和发送,从而通过RestTemplate实现不同微服务之间的调用,加上@LoadBalance注解之后实现负载均衡,那负载均衡的原理是什么呢?

目录

[一, 负载均衡](#一, 负载均衡)

[1.1 负载均衡原理](#1.1 负载均衡原理)

[1.2 源码追踪](#1.2 源码追踪)

[1, LoadBalanceInterceptor](#1, LoadBalanceInterceptor)

[2, LoadBalanceClient](#2, LoadBalanceClient)

[3, 负载均衡策略](#3, 负载均衡策略)

[1.3 总结负载均衡](#1.3 总结负载均衡)

[二, 代码示例](#二, 代码示例)

[三, 负载均衡策略](#三, 负载均衡策略)

[3.1 负载均衡策略](#3.1 负载均衡策略)

[3.2 自定义负载均衡策略](#3.2 自定义负载均衡策略)

[四, 负载均衡](#四, 负载均衡)


一, 负载均衡

1.1 负载均衡原理

SpringCloud底层其实是利用了一个名为Ribbon的组件来实现负载均衡功能的.

此时就可以将我们发出的http://userservice/user/1请求变成http://localhost:8081

1.2 源码追踪

为什么我们只输入了user-service的服务名称就可以访问了呢?

显然有人帮我们根据service名称,获取到了实例的ip和端口号,它就是LoadBalanceInterceptor,这个类会对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真是的服务地址信息,替换服务id.

1, LoadBalanceInterceptor

可以看到这里的intercept方法,拦截了用户大的HttpRequest请求,然后做了以下几件事:

  • request.getURI():获取请求uri,本例中就是http://userservice/user/1
  • originalUri.getHost() :获取uri路径的主机名,其实就是服务id,user-service
  • this.loadBalancer.execute():处理服务id,和用户请求

2, LoadBalanceClient

继续跟入execute方法:

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来
  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个

放行后,再次访问并跟踪,发现获取的是8081:

3, 负载均衡策略

在刚才的代码中,可以看到获取服务是通过一个getServer方法来做负载均衡:

继续跟入:

继续跟踪源码chooseServer方法,发现这么一段代码:

看看这个rule是谁:

这里的rule默认值是一个RoundRobinRule,看类的介绍(意思是轮询):

1.3 总结负载均衡

SpringCloudRibbon的底层采用了一个拦截器,拦截了RestTemplate发出的请求,对地址进行了修改,用一幅图总结一下:

基本流程如下:

  • 拦截我们的RestTemplate请求http://userservice/user/1;
  • RibbonLoadBalancerClient会从请求url中获取服务名称,也就是userservice;
  • DynamicServerListBalance根据userservice到eureka拉取服务列表;
  • eureka返回列表,localhots:8081和localhost:8082;
  • IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081;
  • RibbonLoadBalanceClient修改请求地址,用localhost:8081代替userservice,得到http://localhost:8081/user/1.

二, 代码示例

现在我们有两个user-service微服务,使用order-service多次调用user-service查看服务落在两个user-service的频率

启动服务并清空两个user-service服务的日志:

在浏览器多次调用order-service中的queryOrderByUserId接口:

分别查看两个user-service的日志打印结果:

user-service1:

user-service2:

从日志结果可以看出,在不改变负载均衡策略的情况下,默认的策略是轮询的方式.

三, 负载均衡策略

3.1 负载均衡策略

负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:

不同规则的含义如下:

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

默认的实现就是ZoneAvoidanceRule,是一种轮询方案.

3.2 自定义负载均衡策略

通过定义IRule实现可以修改负载均衡规则,有两种方式:

  1. 代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:

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

  2. 配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:

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

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

四, 负载均衡

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长.

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

复制代码
ribbon:
  eager-load:
    enabled: true
    clients: userservice

未开启饥饿加载时:

第一次访问的时候耗时是579ms

开启饥饿加载时:

先在配置文件里进行配置

重启order-service进行访问

可以看出开启饥饿加载后第一次访问的时间变少了很多,未232ms.

相关推荐
这儿有个昵称1 小时前
Java面试场景:从音视频到微服务的技术深挖
java·spring boot·spring cloud·微服务·面试·kafka·音视频
Remember_9931 小时前
深入理解 Java String 类:从基础原理到高级应用
java·开发语言·spring·spring cloud·eclipse·tomcat
鸽鸽程序猿16 小时前
【JavaEE】【SpringCloud】注册中心_nacos
java·spring cloud·java-ee
递归尽头是星辰19 小时前
Spring Cloud Alibaba 核心理论体系:Nacos、Sentinel、Seata深度解析
spring cloud·nacos·sentinel·seata·微服务治理
lpfasd12319 小时前
springcloud docker 部署问题排查与解决方案
spring·spring cloud·docker
蓝眸少年CY20 小时前
(第七篇)spring cloud之Hystrix断路器
spring·spring cloud·hystrix
蓝眸少年CY1 天前
(第八篇)spring cloud之zuul路由网关
后端·spring·spring cloud
We....1 天前
SpringBoot 微服务拦截器与负载均衡实践
java·spring boot·微服务·负载均衡
码出财富1 天前
SpringBoot 内置的 20 个高效工具类
java·spring boot·spring cloud·java-ee
daladongba2 天前
Spring Cloud Gateway
java·spring cloud·gateway