ServiceComb集成spring cloud zuul组件源码入门

文章目录

一. ServiceComb和Spring Cloud Zuul 集成思路

在学习Spring Cloud Zuul的时候在官网发现了下面的描述
在这里插入图片描述

Zuul starter不包括 discovery client, 所以为了实现基于service ID的路由转发,你必须同时在类路径下提供一个discovery client ( 可以使用 Eureka )

这点很重要,意味我们可以自定义服务发现客户端替代Eureka
关于服务发现的概念:https://www.jianshu.com/p/5eac16e9804a

在这里插入图片描述

DiscoveryClientRouteLocator 过滤器从一个DiscoveryClient(例如Eureka)和属性文件中加载了路由定义信息。
serviceId对应的路由信息从DiscoveryClient中获取。

从以上信息可知,Zuul会从DiscoveryClient中获取路由信息。而服务发现就在DiscoveryClient中实现。

在之前的实现的zuulserver项目中,pom文件中有如下依赖

        <dependency>
            <groupId>org.apache.servicecomb</groupId>
            <artifactId>spring-boot-starter-discovery</artifactId>
            <version>1.1.0</version>
        </dependency>

以上就是一个自定义discovery client。可以完全代替Eureka。这个discovery client是专门与ServiceComb的服务与发现注册中心ServiceCenter进行交互的。

服务发现原理

       服务发现有三个角色,服务提供者、服务消费者和服务中介。服务中介是联系服务提供者和服务消费者的桥梁。服务提供者将自己提供的服务地址注册到服务中介,服务消费者从服务中介那里查找自己想要的服务的地址,然后享受这个服务。服务中介提供多个服务,每个服务对应多个服务提供者。

在这里插入图片描述
在这里插入图片描述
再来一张Eureka的图对比一下
在这里插入图片描述

二. 源码分析

下面看下servicecomb discovery client的目录结构,很明显这是一个自定义的SpringBoot的starter项目。源码从github上下载:https://github.com/apache/servicecomb-java-chassis
在这里插入图片描述

springboot的starter项目一般是做自动化配置的。那么按照starter项目的思路来分析:

1. 自动配置入口

先看spring.factories文件是否有org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置或者@AutoConfigureBefore, @AutoConfigureAfter 注解。
发现在ScbDiscoveryClientConfiguration类中和ScbRibbonConfiguration类中分别有AutoConfigureBefore和AutoConfigureAfter注解,分别来看看这两个类做了什么。

2. ScbDiscoveryClientConfiguration类

这是一个Spring配置类,在这个类里只实例化了DiscoveryClient对象

@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
@Configuration
public class ScbDiscoveryClientConfiguration {
  @Bean
  @Order(5000)
  @ConditionalOnProperty(value = "servicecomb.discoveryClient.enabled", havingValue = "true", matchIfMissing = true)
  public DiscoveryClient cseDiscoveryClient() {
    return new ScbDiscoveryClient();
  }
}

代码如上,AutoConfigureBefore顾名思义,会在某个配置完成后自动执行当前配置。
这个配置类只实例化了一个DiscoveryClient对象。重点来了,这个DiscoveryClient对象就是给Zuul使用的!!! 
最终会被Zuul的 DiscoveryClientRouteLocator 过滤器 用来加载路由定义信息。

3. ScbRibbonConfiguration类

这是个Spring配置类,这个类是为了导入配置类RibbonAutoConfiguration.class

@Configuration
@EnableConfigurationProperties
@ConditionalOnBean(SpringClientFactory.class)
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = ScbRibbonClientConfiguration.class)
public class ScbRibbonConfiguration {

}

代码如上,没有任何实现,注意看@AutoConfigureAfter内指定的是RibbonAutoConfiguration类,所以会在Ribbon初始化配置执行当前类,再看另一个注解@RibbonClients ,指定了ScbRibbonClientConfiguration类来配置RibbonClient。下面看这个类。

4. ScbRibbonClientConfiguration类

这个类是Spring配置类,负责实例化Ribbon定制相关Bean

public class ScbRibbonClientConfiguration {
  @Bean
  public ServerList<Server> ribbonServerList(
      IClientConfig config) {
    ServiceCombServerList serverList = new ServiceCombServerList();
    serverList.initWithNiwsConfig(config);
    return serverList;
  }
}

代码如上, ServerList是Ribbon框架的东西(Ribbon是客户端负载均衡框架)。ServerList是存储服务实例的对象。
在这里插入图片描述
这个类实例化了一个ServiceCombServerList 对象。接着看下这个类。

5. ServiceCombServerList 类

这个类是给Ribbon使用,负责返回服务实例信息。

重点在下面这个方法,这个方法会去真正获取服务实例。最终返回的是可用微服务实例的真实ip地址和端口。
DiscoveryTree是ServiceComb的Registry包的,这个包是负责服务注册的。

...........
  private DiscoveryTree discoveryTree = new DiscoveryTree();
  @Override
  public List<Server> getInitialListOfServers() {
    DiscoveryContext context = new DiscoveryContext();
    context.setInputParameters(serviceId);
   //使用 ServiceComb的Registry包的 DiscoveryTree获取服务实例信息
    VersionedCache serversVersionedCache = discoveryTree.discovery(context,
        RegistryUtils.getAppId(),
        serviceId,
        DefinitionConst.VERSION_RULE_ALL);
    return serversVersionedCache.data();
  }
...........

DiscoveryTree的逻辑比较复杂,可以通过下面的处理流程了解其处理过程。参考官方文档
在这里插入图片描述

调用链太复杂,不详细展开分析,如下图,这个图是反的,最顶部的是最终调用的方法
在这里插入图片描述
直接看最终调用处:

6. ServiceRegistryClientImpl.findServiceInstances

在这个方法内直接调用ServiceCenter的rest接口Const.REGISTRY_API.MICROSERVICE_INSTANCES来获取相应的微服务实例信息 (http://127.0.0.1:30100/v4/default/registry/instances)

.......省略
  @Override
  public MicroserviceInstances findServiceInstances(String consumerId, String appId, String serviceName,
      String versionRule, String revision) {
    // must register self first, and then invoke findServiceInstances
	.......省略
    RequestParam requestParam = new RequestParam().addQueryParam("appId", appId)
        .addQueryParam("serviceName", serviceName)
        .addQueryParam("global", "true")
        .addQueryParam("version", versionRule)
        .addHeader("X-ConsumerId", consumerId);
    if (revision != null) {
      requestParam.addQueryParam("rev", revision);
    }
	//调用ServiceCenter的rest接口Const.REGISTRY_API.MICROSERVICE_INSTANCES来获取相应的微服务实例信息
    RestUtils.get(ipPort,
        Const.REGISTRY_API.MICROSERVICE_INSTANCES,
        requestParam,
        syncHandlerForInstances(countDownLatch, microserviceInstances));
    try {
      countDownLatch.await();
      if (!microserviceInstances.isNeedRefresh()) {
        return microserviceInstances;
      }
      if (microserviceInstances.getInstancesResponse() == null) {
        return null; // error
      }
      List<MicroserviceInstance> list = microserviceInstances.getInstancesResponse().getInstances();
      if (list == null) {
        microserviceInstances.getInstancesResponse().setInstances(new ArrayList<>());
      }
      return microserviceInstances;
    } catch (Exception e) {
		.......省略
    }
    return null;
  }
.......省略

三. 使用指南

demo地址: https://blog.csdn.net/kakuls/article/details/86509736

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值