RestTemplate实现负载均衡及Ribbon原理

一、客户端负载均衡

Ribbon让服务调用端具备负载均衡能力,即客户端会有一个服务器地址列表(在SpringCloud中,服务注册列表的信息来自 EurekaClient等注册中心),在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,即在客户端就进行负载均衡算法分配。

即将负载均衡的逻辑集成到消费方,消费方从注册认证中心获取有哪些服务地址可用,然后自己再从这些地址中选出一个合适的服务器。

客户端(即服务调用方)负载均衡,大抵可以分为两个过程:

  1. 获取服务注册列表的信息
  2. 根据均衡策略进行负载均衡

二、负载均衡代码实例

首先搭建演示需要的服务,一个消费者服务consumer,三个服务提供者,一个eureka注册中心服务

( 代码位置,可自行下载: https://github.com/ImOk520/myspringcloud ):

启动所有服务,查看注册中心:

消费者consumer中我们调用的接口如下:

扫描二维码关注公众号,回复: 13147280 查看本文章

三个服务提供者都是以procider这个名字启动的,此时通过provider这个服务名就能映射三个服务提供者。但是这还不能实现负载均衡,还需要在RestTemplate中加上@LoadBalanced注解:

此时调用consumer的接口如下:

这里每个服务提供者对应不同的数据库,分别对应db01,db02,db03,每次调用会负载均衡到不同的服务提供者,因此数据库的名称会不断变化:

三、负载均衡原理 

Ribbon的负载均衡,主要通过LoadBalancerClient来实现的,而LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等信息,并向EurekaClient获取注册列表的信息,并默认10秒一次向EurekaClient发送“ping”,进而检查是否更新服务列表,最后,得到注册列表后,ILoadBalancer根据IRule的策略进行负载均衡。

而RestTemplate 被@LoadBalance注解后,能实现负载均衡,主要是维护了一个被@LoadBalance注解的RestTemplate列表,并给列表中的RestTemplate添加拦截器,进而交给负载均衡器去处理。

多个RestTemplate从哪来?主要是@LoadBalance注解是包含@Qualifier注解的:

@Qualifier注解注解有两个使用场景:

  •  一、当Spring上下文中含有某个Bean的多个实例,可以指定获取某个实例
  • 二、获取Spring上下文中,某个Bean的创建,有使用Qualifier注解标记的对象集合

 SpringCloud-ribbon组件中,@Qualifie的作用是获取所有使用LoadBalanced注解标记的  RestTemplate 的对象。

完成以上的过程需要依赖多个配置:

1.RibbonAutoConfiguration配置生成 RibbonLoadBalancerClient 实例。

2.LoadBalancerInterceptorConfig 配置生成:1).负载均衡拦截器 LoadBalancerInterceptor 实例。2).RestTemplate自定义的RestTemplateCustomizer 实例。

3.RibbonClientConfiguration配置生成 ZoneAwareLoadBalancer 实例

下面来介绍上面这些配置类产生的 实例 到底有啥用。

RibbonLoadBalancerClient 

负载均衡的一个客户端,是负责整个过程的执行者。

ServiceInstance choose(String serviceId):父接口ServiceInstanceChooser的方法,根据传入的服务名serviceId,从负载均衡器中挑选一个对应服务的实例。

execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest request):使用从负载均衡器中挑选出的服务实例来执行请求内容。

URI reconstructURI(ServiceInstance instance, URI original):为系统构建一个合适的host:port形式的URI。在分布式系统中,我们使用逻辑上的服务名称作为host来构建URI(替代服务实例的host:port形式)进行请求,比如http://myservice/path/to/service。在该操作的定义中,前者ServiceInstance对象是带有host和port的具体服务实例,而后者URI对象则是使用逻辑服务名定义为host的URI,而返回的URI内容则是通过ServiceInstance的服务实例详情拼接host:port形式的请求地址。

LoadBalancerInterceptor 

用于实现对客户端发起请求时进行拦截,以实现客户端负载均衡。

其中一个intercept()方法是实现拦截的核心方法。

 ZoneAwareLoadBalancer

ZoneAwareLoadBalancer继承自ILoadBalancer接口,是一个具体的负载均衡实现类,也是默认的负载均衡类,通过对chooseServer方法的实现选取某个服务实例。其内部通过均衡策略选择一个服务。

为RestTemplate增加了@LoanBalanced 注解后,实际上通过配置,为RestTemplate注入负载均衡拦截器,让负载均衡器选择根据其对应的策略选择合适的服务后,再发送请求。

猜你喜欢

转载自blog.csdn.net/weixin_41231928/article/details/107849876
今日推荐