之前我们在使用RestTemplate进行服务交互的时候,在其注入的bean上添加了@LoadBalanced注解,这样它就默认是使用Ribbon进行负载均衡处理。
但是RestTemplate是Spring提供的,Bean跟Ribbon客户端负载均衡又有什么关系呢?
下面我们就来深入地研究Ribbon是如何结合RestTemplate实现客户端服务调用的负载均衡的。
既然RestTemplate是使用了@LoadBalanced注解才让其实现Ribbon的负载均衡的,那么我们就从这个注解开始着手研究。
按住“Ctrl”键并单击@LoadBalanced注解查看源码,我们发现这个注解里面没有什么特殊的内容,但是从源码的注释可以知道该注解是标记在RestTemplate或WebClient Bean上的,从而配置为LoadBalancerClient。
接着观察LoadBalancerClient的源码,可以发现它是一个定义了负载均衡方法的接口,如程序清单12-2所示。
除了上面源码中定义负载均衡的几种方法外,LoadBalancerClient还继承了ServiceInstance- Chooser接口中的chooser方法,如程序清单12-3所示。
通过查看这几个功能方法的注释可以得知,choose方法是通过serviceId(服务ID)从负载均衡器中挑选出对应的服务实例的;
execute方法是使用从负载均衡器中挑选出来的服务来处理请求的;
reconstructURI方法表示为服务实例创建一个host:port的URI实例。
从上图中可以看到,RibbonLoadBalancerClient是LoadBalancerClient的实现类,单击查看它的源码可知它是执行客户端负载均衡处理功能的子类。
RibbonLoadBalancerClient重写的choose功能方法中,内部通过getServer方法根据serviceId获取到服务,而从getServer方法中可以发现其是通过ILoadBalancer接口来实现的,如程序清单12-4所示。
ILoadBalancer是一个接口,所以它只定义了实现负载均衡的方法,如程序清单12-5所示。
ILoadBalancer接口的实现类是AbstractLoadBalancer,但是它是一个抽象类,所以服务的获取、选择以及添加等操作主要在其子类BaseLoadBalancer和DynamicServerListLoadBalancer中实现。
ILoadBalancer接口的实现类是AbstractLoadBalancer,但是它是一个抽象类,所以服务的获取、选择以及添加等操作主要在其子类BaseLoadBalancer和DynamicServerListLoadBalancer中实现。这两个子类中还定义了负载均衡的客户端配置IClientConfig、获取服务的负载均衡策略IRule、通过IPing接口进行ping测试来判断服务是否可用以及从Eureka服务列表中获取服务列表Server集合对象等,这里就不再列出其源码。
通过上面的描述,我们知道负载均衡进行服务的添加、服务的获取、服务的选择等操作主要是通过LoadBalancerClient的子类RibbonLoadBalancerClient实现的,那么为什么我们在RestTemplate注入的Bean上添加@LoadBalanced注解就可以加载RibbonLoadBalancerClient进行负载均衡呢?这是因为Ribbon有一个自动配置类RibbonAutoConfiguration,而RibbonAutoConfiguration加载前会加载LoadBalancerAutoConfiguration配置类,在LoadBalancer- AutoConfiguration中有一个被@LoadBalanced修饰的RestTemplate集合,在进行初始化的时候使用RestTemplateCustomizer给每一个RestTemplate都添加了LoadBalancerInterceptor拦截器。
LoadBalancerAutoConfiguration部分源码如程序清单12-6所示。
LoadBalancerInterceptor 拦截器(其源码如程序清单12-7所示)负责拦截请求,并把请求交给LoadBalancerClient负载均衡类处理,因此RestTemplate就实现了负载均衡的功能。
标签:负载,服务,RestTemplate,工作,源码,均衡,原理,Ribbon From: https://www.cnblogs.com/cnetsa/p/16982091.html