Spring cloud负载均衡Ribbon&LoadBalancer

Springcloud提供了两种负载均衡实现Ribbon和LoadBalancer

  • 在使用时引入对应的starter依赖即可
  • 默认使用的是Ribbon,因此在使用Loadbalancer时,除了引入Loadbalancer的starter依赖外,还要排除掉ribbon的依赖,这样生效的就是Loadbalancer
  • Ribbon只支持RestTemplate,LoadBalancer支持RestTemplate以及响应式客户端WebClient
  • Ribbon是基于Netflix Ribbon 实现的一套客户端的负载均衡工具,LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器, 用来替代Ribbon。

spring-cloud公共组件核心类

LoadBalancerAutoConfiguration

负载均衡自动配置类,属于spring-cloud-common包,不管是Ribbon还是LoadBalancer都使用了该配置类

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
  • @ConditionalOnClass生效条件:存在RestTemplate类
  • @ConditionalOnBean生效条件:存在LoadBalancerClient客户端的bean,如ribbon客户端RibbonLoadBalancerClient
  • 定义bean对象
    LoadBalancerInterceptor 拦截器
    SmartInitializingSingleton的bean对象,在所有bean创建完成后调用,使用@LoadBalanced定制RestTemplate,调用RestTemplateCustomizer#customize给RestTemplate添加拦截器LoadBalancerInterceptor
NamedContextFactory

用于创建SpringCloud子容器,在子容器中可以创建不同的bean,即可以给每个服务(需要调用的微服务)设置不同的容器,对应的配置类有默认配置类,也有全局配置类,也可以为单个bean定义配置。

  • Map contexts:key是ribbon中就是服务名,value是子容器
  • Map configurations:key是ribbon中就是服务名,value是该服务自定义的配置类
  • createContext():创建spring容器
    1、configurations配置类中,有没有该服务的配置类,若有,则注册配置类
    2、configurations配置类中,有没有默认的配置类,即beanName以default开头的全局配置类,若有,则注册配置类
    3、注册默认客户端配置类:如:RibbonClientConfiguration
    4、增加环境变量:ribbon.client.name,值为对应的服务名
    5、refresh刷新容器

RibbonAutoConfiguration:ribbo默认配置类,List< RibbonClientSpecification >
configurations是空的不用注册
RibbonNacosAutoConfiguration:nacos默认配置类,使用@RibbonClients注入全局默认配置类NacosRibbonClientConfiguration,需要注册

Ribbon

RibbonAutoConfiguration

ribbon自动配置类,属于netflix.ribbon包

@Configuration
@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)
@RibbonClients
@AutoConfigureAfter(
    name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({ LoadBalancerAutoConfiguration.class,
                      AsyncLoadBalancerAutoConfiguration.class })
@EnableConfigurationProperties({ RibbonEagerLoadProperties.class,
                                ServerIntrospectorProperties.class })
public class RibbonAutoConfiguration {
  • @Conditional生效条件:存在Ribbon、RestTemplate类
  • @AutoConfigureBefore以下配置前生效
    LoadBalancerAutoConfiguration:spring-cloud公共组件中的负载均衡配置类
    AsyncLoadBalancerAutoConfiguration:负载均衡异步配置类
  • @RibbonClients:使用Import导入RibbonClientConfigurationRegistrar,将@RibbonClients注解的类注册到容器中,其中beanName:default.XXX.RibbonClientSpecification,beanClass为RibbonClientSpecification
  • 定义bean对象
    ribbon客户端RibbonLoadBalancerClient的bean对象
RibbonClientConfiguration

ribbon客户端配置类

@Import({ HttpClientConfiguration.class, OkHttpRibbonConfiguration.class,
         RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class })
public class RibbonClientConfiguration {
	@Bean
	@ConditionalOnMissingBean
	public IClientConfig ribbonClientConfig() {
	}
	@Bean
	@ConditionalOnMissingBean
	public IRule ribbonRule(IClientConfig config) {
		ZoneAvoidanceRule rule = new ZoneAvoidanceRule();
		rule.initWithNiwsConfig(config);
		return rule;
	}
	@Bean
	@ConditionalOnMissingBean
	@SuppressWarnings("unchecked")
	public ServerList<Server> ribbonServerList(IClientConfig config) {
	     .....
		return serverList;
	}
	@Bean
	@ConditionalOnMissingBean
	public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
			ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
			IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
		return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList,
				serverListFilter, serverListUpdater);
	}
}
  • 使用Import导入支持的http客户端,并给其注入负载均衡器等
  • 定义bean对象
    IClientConfig:Ribbon的客户端配置,默认采用DefaultClientConfigImpl实现
    IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现
    ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现
    ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现
    IPing:Ribbon的实例检查策略,默认采用DummyPing实现
    ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现

LoadBalancer

属于spring-cloud-loadbalancer包
自动配置类LoadBalancerAutoConfiguration(属于spring-cloud-common包)和
BlockingLoadBalancerClientAutoConfiguration

BlockingLoadBalancerClientAutoConfiguration
@Configuration
@LoadBalancerClients
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@AutoConfigureBefore({
    org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class,
    AsyncLoadBalancerAutoConfiguration.class })
public class BlockingLoadBalancerClientAutoConfiguration {
  • @AutoConfigureAfter:配置类LoadBalancerAutoConfiguration(属于spring-cloud-loadbalancer包)后生效
  • @AutoConfigureBefore:指定配置类LoadBalancerAutoConfiguration(属于spring-common包)前生效
  • @LoadBalancerClients:功能类似@RibbonClients,使用Import导入LoadBalancerClientConfigurationRegistrar,将@LoadBalancerClients注解的类注册到容器中,其中beanName:default.XXX.LoadBalancerClientSpecification,beanClass为LoadBalancerClientSpecification
  • 定义bean对象
    客户端BlockingLoadBalancerClient:缺失ribbon客户端时才生效
LoadBalancerAutoConfiguration

属于spring-cloud-loadbalancer包

@Configuration
@LoadBalancerClients
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,
                      ReactiveLoadBalancerAutoConfiguration.class })
// @EnableCaching //TODO: how to enforce, or check conditions?
// @AutoConfigureBefore(CacheAutoConfiguration.class)
public class LoadBalancerAutoConfiguration {

@AutoConfigureBefore以下响应式配置前生效

  • ReactorLoadBalancerClientAutoConfiguration:在所有bean创建完成后调用,定制响应式编程客户端WebClient,给其添加拦截器ReactorLoadBalancerExchangeFilterFunction
  • ReactiveLoadBalancerAutoConfiguration:在所有bean创建完成后调用,定制响应式编程客户端WebClient,给其添加拦截器LoadBalancerExchangeFilterFunction

Nacos整合Ribbon

spring-cloud-starter-alibaba-nacos-discovery依赖了spring-cloud-starter-netflix-ribbon,因此只需要引入Nacos服务发现依赖,就会自动实现ribbon功能

RibbonNacosAutoConfiguration
@RibbonClients(defaultConfiguration = NacosRibbonClientConfiguration.class)
public class RibbonNacosAutoConfiguration {
}

@ConditionalOnRibbonNacos
public class NacosRibbonClientConfiguration {
	@Bean
	@ConditionalOnMissingBean
	public ServerList<?> ribbonServerList(IClientConfig config,
			NacosDiscoveryProperties nacosDiscoveryProperties) {
		NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties);
		serverList.initWithNiwsConfig(config);
		return serverList;
	}
}

使用@RibbonClients导入了全局默认配置类NacosRibbonClientConfiguration,在该配置类中定义了ServerList服务实例NacosServerList,通过负载均衡查找服务实例时会调用NacosServerList#getServers方法,从Nacos客户端获取服务实例

Ribbon调用流程

注册中心Nacos为例

  1. ribbon调用restTemplate.getForObject(“http://order-server/hello”,
    String.class)
  2. 调用LoadBalancerInterceptor#intercept方法,调用RibbonLoadBalancerClient#execute方法
  3. 获取负载均衡器getLoadBalancer(serviceId),从nacos客户端获取服务列表并缓存,serviceId为服务名order-server

调用NamedContextFactory给order-server创建子容器,给容器注册配置类(自定义的该服务的配置类、全局默认配置类:注册RibbonNacosAutoConfiguration),注册客户端配置类RibbonClientConfiguration,添加环境变量服务名ribbon.client.name:order-server

从容器中获取ILoadBalancer的bean对象,默认是ZoneAwareLoadBalancer,创建该bean对象,注入规则ZoneAvoidanceRule、服务列表NacosServerList、服务配置DefaultClientConfigImpl等;构造对象时,通过NacosServerList根据服务名从注册中心客户端获取服务实例数据,将其缓存在本地

  1. 通过负载均衡器根据算法选择一个服务实例
  2. 调用http请求,getURI()获取url时,调用RibbonLoadBalancerClient#reconstructURI,使用服务实例中的host:port替换服务名重组url;然后发起请求调用

你可能感兴趣的:(spring全家桶,spring,cloud,负载均衡,ribbon)