深入理解Java SpringCloud Ribbon 负载均衡

 更新时间:2021年09月06日 11:41:13   作者:Coder Xu  
Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制。这篇文章主要介绍了SpringCloud Ribbon 负载均衡的实现,感兴趣的小伙伴们可以参考一下

前言

该技术博客是关于黑马视频教程的笔记总结!

服务消费者需要通过RestTemplate调用注册中心(Eureka)的服务提供者,但当同一服务名称的服务有多个的时候,我们的服务消费者应该调用哪一个服务呢?这时候就需要我们学习理解Ribbon负载均衡的实现原理。

当我们在RestTemplate组件上加上@LoadBalanced注解,就会去注册中心中拉取服务的实例列表,并且实现负载均衡,SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。

1、抛出问题

比如我们的服务消费者 order-service发出请求:http://userservice/user/1
该请求并不能与注册中心中的服务列表信息相符,那么是如何找到 http://localhost:8081呢?

在这里插入图片描述

2、源码解析

2.1、LoadBalancerIntercepor

上述信息已经表明,我们没有输出IP和端口号,只是通过了服务名称(userservice) 就能找到我们想要调用的服务!

这是因为Ribbon组件中的LoadBalancerInterceptor(负载均衡拦截器)会将调用请求拦截,根据服务名称获取到服务实例的ip和端口。

LoadBalancerInterceptor 会在将RestTemplate的请求进行拦截,然后在Eureka注册中心根据服务名称获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务名称。

在这里插入图片描述

可以看到这里的intercept方法,拦截了调用请求HttpRequest,然后做了一下操作:

1.request.getURI():获取请求uri,本例中就是 http://user-service/user/8

2.originalUri.getHost():获取uri路径的主机名,其实就是服名称:userservice

3.this.loadBalancer.execute():处理服务名称,和用户请求

这里的this.loadBalancer是LoadBalancerClient类型,我们继续跟入execute方法!

2.2、LoadBalancerClient

代码是这样的:

getLoadBalancer(serviceId):根据服务名称获取ILoadBalancer接口,而ILoadBalancer会拿着服务名称去eureka中获取服务列表并保存起来。

getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务

在这里插入图片描述

放行后,再次访问并跟踪,发现变成获取8081端口服务,实现了负载均衡:

在这里插入图片描述

2.3、负载均衡策略IRule

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

在这里插入图片描述

继续跟入getServer方法:

在这里插入图片描述

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

在这里插入图片描述

我们看看这个rule是谁:

在这里插入图片描述

这里的rule默认值是一个RoundRobinRule,看看介绍:

在这里插入图片描述

翻译过来就是轮询的意思,这样,整个负载均衡的流程我们就清楚了。

2.4、总结

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

在这里插入图片描述

基本流程如下:

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

3、负载均衡策略

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

在这里插入图片描述

不同规则的含义如下:

在这里插入图片描述

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

那么如何自定义负载均衡策略?

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

1.代码方式:在配置类或启动类(可以看作配置类)中,定义一个新的IRule:

@Bean
public IRule randomRule(){
	//随机策略
    return new RandomRule();
}

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

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

注意:我们一般用默认的负载均衡规则,不做修改!

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • SpringBoot Controller接收参数的几种常用方式

    SpringBoot Controller接收参数的几种常用方式

    这篇文章主要介绍了SpringBoot Controller接收参数的几种常用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Docker和 Containerd 的区别解析

    Docker和 Containerd 的区别解析

    containerd 是一个来自 Docker 的高级容器运行时,并实现了 CRI 规范,它是从 Docker 项目中分离出来,之后 containerd 被捐赠给云原生计算基金会(CNCF)为容器社区提供创建新容器解决方案的基础,这篇文章主要介绍了Docker和 Containerd 的区别,需要的朋友可以参考下
    2024-03-03
  • SpringBoot实现分布式任务调度的详细步骤

    SpringBoot实现分布式任务调度的详细步骤

    随着互联网应用的规模和复杂度不断增加,单节点任务调度系统已经难以满足高并发、大数据量的处理需求,分布式任务调度成为了解决这一问题的重要手段,本文将介绍如何在Spring Boot中实现分布式任务调度,需要的朋友可以参考下
    2024-08-08
  • 深入理解Java三大特性中的多态

    深入理解Java三大特性中的多态

    多态性是对象多种表现形式的体现。在面向对象中,最常见的多态发生在使用父类的引用来引用子类的对象。下面这篇文章主要给大家深入的介绍了Java三大特性中多态的相关资料,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • 把Java程序转换成exe,可直接运行的实现

    把Java程序转换成exe,可直接运行的实现

    这篇文章主要介绍了把Java程序转换成exe,可直接运行的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • IntelliJ IDEA 中使用jRebel进行 Java 热部署教程图解

    IntelliJ IDEA 中使用jRebel进行 Java 热部署教程图解

    Rebel是一款JAVA虚拟机插件,它使得JAVA程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。本文通过图文并茂的形式给大家介绍了IntelliJ IDEA 中使用jRebel进行 Java 热部署教程图解,需要的朋友参考下吧
    2018-04-04
  • java中的接口能够被实例化吗

    java中的接口能够被实例化吗

    这篇文章主要介绍了java中的接口能够被实例化吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 使用Spring Boot+gRPC构建微服务并部署的案例详解

    使用Spring Boot+gRPC构建微服务并部署的案例详解

    这篇文章主要介绍了使用Spring Boot+gRPC构建微服务并部署,Spring Cloud仅仅是一个开发框架,没有实现微服务所必须的服务调度、资源分配等功能,这些需求要借助Kubernetes等平台来完成,本文给大家介绍的非常详细,需要的朋友参考下吧
    2022-06-06
  • 新建springboot项目时,entityManagerFactory报错的解决

    新建springboot项目时,entityManagerFactory报错的解决

    这篇文章主要介绍了新建springboot项目时,entityManagerFactory报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Spring与bean有关的生命周期示例详解

    Spring与bean有关的生命周期示例详解

    这篇文章主要给大家介绍了关于Spring与bean有关的生命周期的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07

最新评论