Ribbon负载均衡源码分析
Ribbon负载均衡
在springcloud中,我们通常注册一台或多台服务器(Eureka),之后将服务‘消费者(consumer)’和服务‘提供者(provider)’注册到Eureka服务器上,消费者可以在服务器上找到服务提供者端口,之后对服务提供者进行调用。如下图所示:
但是如果服务提供者只有一个时,当这个提供者模块宕机时,系统就挂掉了。
为了解决这一问题,我们将提供者模块设置不同端口,然后多次启动,也就是将提供者模块做个集群。里边的代码保持不变,为的就是防止一个提供者宕机以后,整个系统瘫痪。
在配置时,将服务名(spring.application.name)设置成一样的,但是端口号(eureka.instance.instance-id)不同:
######### 1
# 服务的名字,注册到注册中心的名字,后期消费者来根据名字调用服务 可以重复
spring.application.name=springcloud-producer
########## 2
# 执行当前服务的应用ID 不可以重复 标识的是每一个具体的的服务
eureka.instance.instance-id=springcloud-producer-8181
######### 1
# 服务的名字,注册到注册中心的名字,后期消费者来根据名字调用服务 可以重复
spring.application.name=springcloud-producer
########## 2
# 执行当前服务的应用ID 不可以重复 标识的是每一个具体的的服务
eureka.instance.instance-id=springcloud-producer-8383
之后将同一个项目启动两次,就完成了提供者的集群如下图:
集群后的图示如下:
说了这么多,还是没有提到负载均衡。别急,来了。
进行提供者集群之后,消费者调用的是哪个端口的提供者呢?不使用ribbon负载均衡时,消费者随机调用不同端口的提供者。开启ribbon负载均衡后,可以使用内置算法进行花式负载均衡。默认的是轮询(就是在一个周期内每个端口调用一次,雨露均沾)。
加入下图注解,开启负载均衡。
源码分析一 为何只传服务名,不传端口号,就可以帮你访问到目标提供者
在LoadBalancerInterceptor拦截器类中,重写了intercept方法,其中第31行代码就是获得该服务名中的“host”信息。这里我们就解决了第一个疑惑:是谁帮我们将服务名转化成IP地址和端口名的。
源码分析二 获取host的算法
之前有提到,负载均衡默认地为消费者选择服务者端口的方式是轮询(雨露均沾)。那么我们就从源码里揪出这个算法藏在哪儿。
点击excute,深入了解一下彼此。
点进来发现,是个接口(interface),看接口没啥用,看看他的实现类。
选择RibbonLoadBalancerClient方法,点进去,直接找execute的重写方法,核心代码在第64行,后边都是对server的if else判断,那我们看看这个“this.getServer”到底对server做了什么手脚。
ctrl+1 点击“getServer”之后,跳到同一个类的getService方法,如下图所示:
使用了一个三目运算表达式,但是具体每个属性是干啥的我也不知道,但一眼就能看到,里边只调了一个方法“chooseServer”,那还不ctrl+1点开看看!
【激动时刻,不配表情包了,来个符号表情。 ( ̄︶ ̄)↗ 】
点开以后,进入BaseLoadBalancer类中:
这个key对象,就是通过ribbon内置算法得到的host名吧。那么到底是通过什么算法得到的呢?赶紧把623行的rule点开看看!
再点击Irule。Ohoo,又回来了。又要找它的实现类了…这个类在上头我们就遇到过,这次转了一圈又点回来了,唉。我们这时候还是不知道他默认实现什么算法,不是吗?
不是呗。我们回到上上步操作,这个623行的代码,rule明明是个接口,怎么直接链式实现其中的choose方法了呢?如下图:
dangdangdangdang~请看第40行,这个Irule其实已经被重新定义了。 new RoundRobinRule()
这个方法翻译成中文就是:轮询算法。
点开看看。
这就是最终我们想找到的算法,也应证了ribbon默认算法是轮询算法的推论。
实战检验
我一共请求了6次‘/test’,两个提供者的端口相继为我服务,谁也不争,谁也不抢。
我这里的测试方式是在提供者的controller方法里sout他所在的模块的端口号,还可以在源码打断点或者编写测试类进行测试。
大家快去试试吧
推荐阅读
-
PHP开发负载均衡分析与方案
-
SpringCloud客户端的负载均衡Ribbon的实现
-
spring cloud 之 客户端负载均衡Ribbon深入理解
-
SpringCloud客户端的负载均衡Ribbon的实现
-
spring cloud 之 客户端负载均衡Ribbon深入理解
-
详解spring cloud中使用Ribbon实现客户端的软负载均衡
-
Spring Cloud Ribbon实现客户端负载均衡的方法
-
详解spring cloud中使用Ribbon实现客户端的软负载均衡
-
Spring Cloud Ribbon实现客户端负载均衡的方法
-
Spring Cloud Ribbon实现客户端负载均衡的示例