总的来说Ribbon的负载均衡主要是通过LoadBalancerClient来实现的,而LoadBalancerClient交给ILoadBalancer来处理,ILoadBalancer通过配置IRule,IPing这写信息,来向EurekaClient获取注册列表,默认情况下,每隔10秒钟向EurekaClient发送一个ping,检测是否需要更新注册列表的信息。获取到注册列表之后,通过IRule中选择的负载均衡策略来进行负载均衡。
使用RestTemplate和Ribbon结合做负载均衡。需要在IoC容器中注入一个RestTemplate的Bean,并且在这个Bean上添加@LoadBalanced注解,这是RestTemplate就结合Ribbon开启了负载均衡功能。
负载均衡器的核心类是LoadBalancerClient,LoadBalancerClient是一个接口,它继承了ServiceInstanceChooser,实现类是RibbonLoadBalancerClient,这个实现类很重要,负载均衡的请求就是由他来处理的。在RibbonLoadBalancerClient中choose方法是用来选择服务实例的,choose方法通过调用getrserver()方法获取服务实例,然后交给ILoadBalancer这个类来选择服务实例。
ILoadBalancer是一个接口,定义了一些实现负载均衡的方法,比如addServer()添加一个server集合,chooseServer()根据key获取可用的server集合。
ILoadBalancer的子类是BaseLoadBalancer,BaseLoadBalancer的实现类是DynamicServerListLoadBalancer。在DynamicServerListLoadBalancer当中,需要配置IClientConfig,IRule,IPing,ServerList,ServerListFilter,ILoadBalancer。
- IClientConfig是用来配置负载均衡客户端的
- IRule:有很多默认的实现类,这些实现类对应着不同的负载均衡策略。常见的有RandomRule随机选择一个server。RoundRobinRule,轮询的方式选择server。还可以根据自己的需要自己实现负载均衡算法。
- IPing用来向server发送ping,判断一个server是否有响应,有相应就说明是可用的。
- ServerList是一个接口,定义了方法获取注册列表信息
- ServerListFilter是一个接口,定义方法,根据一定的条件选择性地获取sever的注册列表。
EurekaClient的实现类是DiscoveryClient,这个实现类提供了服务注册,获取服务注册列表信息的功能。
负载均衡器是通过EurekaClient获取服务注册列表信息,通过IRule的负载均衡策略选择服务,然后通过ping判断服务是否可用。那么负载均衡器间隔多长时间从EurekaClient获取一次注册信息?
在BaseLoadBalancer的构造方法中,开启了一个PingTask任务,在setupPingTask方法,里面设置默认10秒钟向Eureka Client发送一个心跳ping。如果服务的可用性发生了改变或者服务数量和之前不一致,就重新拉取服务注册列表。LoadBalancerClient有了这些注册列表就根据IRule中的策略来进行负载均衡。
为什么在RestTemplate类的Bean上添加一个@LoadBalancer注解就能使用Ribbon的负载均衡?
主要是因为在LoadBalancerAutoConfiguration类中,维护了一个RestTemplate对象的列表,这个类表被@LoadBalanced注解修饰,并且给这个列表中的RestTemplate对象添加了拦截器,在拦截的方法中把远程调度的方法交给Ribbon的负载均衡器LoadBalancedClient来处理,完成负载均衡的功能。