转载

Spring Cloud Ribbon 详解

加入 spring-cloud-starter-netflix-ribbon 依赖

代码中使用RibbonClient注解

@Configuration 
@RibbonClient(name = "foo", configuration = FooConfiguration.class) public class TestConfiguration {}
@Configuration protected static class FooConfiguration {

    @Bean 
    public ZonePreferenceServerListFilter serverListFilter() {
        ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
        filter.setZone("myTestZone");
        return filter; 
    }

    @Bean 
    public IPing ribbonPing() { 
        return new PingUrl(); 
    }

}

Ribbon客户端的配置, 如果不指定会使用默认的实现:

  • IClientConfig 客户端相关配置
  • IRule 定义负载均衡策略
  • IPing 定义如何ping目标服务实例来判断是否存活, ribbon使用单独的线程每隔一段时间(默认10s)对本地缓存的ServerList做一次检查
  • ServerList 定义如何获取服务实例列表. 两种实现基于配置的 ConfigurationBasedServerList 和基于Eureka服务发现的 DiscoveryEnabledNIWSServerList
  • ServerListFilter 用来使用期望的特征过滤静态配置动态获得的候选服务实例列表. 若未提供, 默认使用 ZoneAffinityServerListFilter
  • ILoadBalancer 定义了软负载均衡器的操作的接口. 一个典型的负载均衡器至少需要一组用来做负载均衡的服务实例, 一个标记某个服务实例不在旋转中的方法, 和对应的方法调用从实例列表中选出某一个服务实例.
  • ServerListUpdater DynamicServerListLoadBalancer用来更新实例列表的策略(推 EurekaNotificationServerListUpdater /拉 PollingServerListUpdater , 默认是拉)

分析

类结构

Spring Cloud Ribbon 详解

实现

实际使用中, 服务调用使用RestTemplate, 请求地址为 http://<serviceName>/<path> , 如 http://foo/
通过 @RibbonClient 注解为服务创建ribbon客户端, 名字为方法名. RestTemplate发送请求的时候, 请求会被 LoadBalancerInterceptor 拦截到, 使用服务对应的ribbon客户端. Ribbon客户端的 LoadBalancer 会从 ServerList 中根据 IRule 的规则选择某个服务实例作为请求对象. ServerList 有动态的实现, 更新列表时会使用 ServerListFilter 进行过滤.

RibbonClient注解

从注释上 @RibbonClient 为一个ribbon客户端声明配置信息. 把这个注解加在任何 @Configuration 标注的类上, 然后注入 SpringClientFactory 来访问创建的客户端.

从代码上看 @RibbonClient 引入了 RibbonClientConfigurationRegistrar . RibbonClientConfigurationRegistrar 实现了 ImportBeanDefinitionRegistrar 接口, 在 @Configuration 的解析极端调用接口的 registerBeanDefinitions 方法, 为ribbon客户端创建BeanDefinition

使用 name/valueconfiguration 创建一个 BeanDefinition . Definition的名为 <name>.RibbonClientSpecification , class为 RibbonClientSpecification .

FooConfiguration.class 也要使用 @Configuration 注解, 然后通过 RibbonClientConfigurationRegistrar 关联到Ribbon客户端的BeanDefinition. 所以 不能把FooConfiguration放到@ComponentScan的上下文中, 同样@SpringBootApplication也不行. 必要时使用exclude排除 , 否则会变成所有Ribbon客户端共享.

RibbonAutoConfiguration 中在创建 SpringClientFactory bean时, 会注入这些 RibbonClientSpecification . SpringClientFactory 继承了类 NamedContextFactory . 从注释看 NamedContextFactory 可以创建一组子上下文, 每个子上下文中可以使用一组的Specification来定义bean. 对于Ribbon来说, 每个ribbon客户端各自为一个子上下文, @RibbonClientconfiguration 指定的配置, 就是用来构建该子上下文的配置, 最终被用来构建ribbon客户端. 这些上下文有共同的父上下文, 即 ApplicationContext . 这就是为什么上面提到的 FooConfiguration 不能置于 ApplicationContext 中, 否则会被所有的Ribbon客户端共享配置.

LoadBalancerAutoConfiguration配置类

通过 RibbonAutoConfiguration 引入, 定义了几个重要的bean:

  • LoadBalancerRequestFactory : 1) 将Http请求封装成 ServiceRequestWrapper . ServiceRequestWrapper 继承并重写了 HttpRquestWrappergetURI 方法: 调用 LoadBalancerClientreconstructURI 方法,创建实际请求的地址. 2) 如果有提供 LoadBalancerRequestTransformer 的实例, 则使用这些实例对相求进行响应的转换.

    Spring Cloud Ribbon 详解
  • LoadBalancerInterceptor : Http请求拦截器, 将请求的 host 作为 serviceName 并使用 LoadBalancerRequestFactory 封装请求, 调用 LoadBalancerClientexecute 方法, 发送请求到真实的服务实例地址, 返回响应

  • RestTemplateCustomizer : 提供一个 RestTemplateCustomizer 的匿名类实现, 为所有的RestTemplate实例添加一个 LoadBalancerInterceptor 拦截器

RibbonAutoConfiguration配置类

通过spring.factories引入, RibbonAutoConfiguration 定义了几个重要的bean:

  • SpringClientFactory : 使用 @RibbonClient 注解引入的ribbon客户端的配置, 构建ribbon客户端的子上下文, 初始化ribbon客户端bean. 四个get方法, 分别返回对应 serviceIClient , ILoadBalancer , IClientConfig , RibbonLoadBalancerContext 实例.

    Spring Cloud Ribbon 详解
  • LoadBalancerClient : 使用Spring Cloud提供的实现 RibbonLoadBalancerClient . 通过 SpringClientFactory 创建一个 ILoadBalancer 实例, 通过 ILoadBalancer 返回一个 Server 实例. 使用 Server 实例.

    • reconstructURI(): 通过 SpringClientFactory 获取该服务ribbon客户端子上下文 RibbonLoadBalancerContext 对象, 调用 RibbonLoadBalancerContextreconstructURIWithServer 方法构建最终的请求地址
    • choose(): 通过 SpringClientFactory 获取该服务的服务均衡器, 使用负载均衡器的 IRule 返回服务实例.
    • execute(): 执行最终的请求, 并记录状态: ServerStatsStopwatch

      Spring Cloud Ribbon 详解

原文  http://atbug.com/spring-cloud-ribbon-breakdown-1/
正文到此结束
Loading...