本地注册发现

本地注册发现是一种静态的服务发现机制。使用本地注册发现,需要在项目中引入如下依赖:

    <dependency>
      <groupId>org.apache.servicecomb</groupId>
      <artifactId>registry-local</artifactId>
    </dependency>

本地服务发现可以在很多不同的场景使用,能够帮助开发者解决很多系统集成问题,比如和网关的集成,和第三方服务的集成。

注册过程

和使用服务中心一样, 系统会自动完成注册。系统会从配置文件中读取本微服务的信息和实例信息,以及本微服务发布的 契约信息,将信息注册到内存中。

发现过程

发现过程也是从本地进行查找。因此系统需要配置本地的微服务信息和实例信息,以及契约信息。 提供了下面两种方式:

  • 使用配置文件的方式定义服务

    这种方式从配置文件(registry.yaml)中读取服务的 MicroserviceMicroserviceInstance 信息,从目录 microservices/{serviceName}/{schemaId}.yaml 或者 applications/{appId}/{serviceName}/{schemaId}.yaml 读取微服务的契约 信息。

    registry.yaml 格式:

      ```yaml
      ms1:
        - id: "001"
          version: "1.0"
          appid: exampleApp
          environment: development
          schemaIds:
            - hello
          instances:
            - endpoints:
                - rest://127.0.0.1:8080
        - id: "002"
          version: "2.0"
          environment: development
          appid: exampleApp
          schemaIds:
            - hello
          instances:
            - endpoints:
                - rest://127.0.0.2:8080
      ms2:
        - id: "003"
          version: "1.0"
          environment: development
          appid: exampleApp
          schemaIds:
            - hello
          instances:
            - endpoints:
                - rest://127.0.0.1:8081
      ``` 
    

    registry.yaml 指定了微服务的基本信息:应用ID (appId), 微服务名称 (serviceName), 微服务版本(version),环境(environment) 和契约;微服务实例基本信息:网络地址(endpoints)。

  • 使用 bean 的方式定义服务

      ```java
        @Bean
        public RegistryBean demoLocalRegistryServerBean2() {
          List<String> endpoints = new ArrayList<>();
          endpoints.add("rest://localhost:8080");
          List<Instance> instances = new ArrayList<>();
          instances.add(new Instance().setEndpoints(endpoints));
    
          return new RegistryBean()
              .setServiceName("demo-local-registry-server-bean2")
              .setId("003")
              .setVersion("0.0.3")
              .setAppId("demo-local-registry")
              .addSchemaInterface("CodeFirstEndpoint2", CodeFirstService.class)
              .setInstances(new Instances().setInstances(instances));
        }
      ```
    

    RegistryBean 的信息和 registry.yaml 的信息类似, 可以添加 Schema Interface 来添加 契约信息, 如果没有添加契约信息,这种方式也会从本地配置文件查找契约。 CodeFirstService 是一个接口, 和普通的 provider 接口定义类似:

      @Path("/register/url/codeFirst")
      @Produces("application/json")
      public interface CodeFirstService {
        @GET
        @Path("getName")
        String getName(@QueryParam("name") String name);
      }
    

本地注册发现的应用 - 调用第三方服务

可以有非常多的方式调用第三方服务,比如采用第三方提供的 Rest Client。 但是需要提供一种 透明的方式,让调用第三方服务的客户端代码和调用 servicecomb 微服务的 客户端代码风格完全一样,并且拥有所有 servicecomb 的客户端治理能力。

调用第三方服务里面介绍了servicecomb提供的一种 调用第三方服务的使用方式,这种方式依赖于使用服务中心作为注册发现。 可以看出使用本地服务发现能够非常方便的调用第三方服务。

只需要在原来的项目中引入本地注册发现,按照上述两种方式之一定义第三方服务的信息。 定义完成后,可以像访问 servicecomb 服务一样访问第三方服务,不用关心第三方服务是采用什么框架开发的。 下面代码片段来源于 demo, 演示了通过 java chassis 的方式调用服务中心接口。

public interface IServiceCenterEndpoint {
  // java name can not be `x-domain-name`, so interfaces define all parameters.
  @GetMapping(path = "/instances")
  Object getInstances(@RequestParam(name = "appId") String appId,
      @RequestParam(name = "serviceName") String serviceName,
      @RequestParam(name = "global") String global,
      @RequestParam(name = "version") String version,
      @RequestHeader(name = "x-domain-name") String domain);
}

@Component
public class ServiceCenterTestCase implements CategorizedTestCase {
  @RpcReference(microserviceName = "thirdParty-service-center", schemaId = "ServiceCenterEndpoint")
  IServiceCenterEndpoint serviceCenterEndpoint;

  @Override
  public void testRestTransport() throws Exception {
    // invoke service-center(3rd-parties)
    @SuppressWarnings("unchecked")
    Map<String, List<?>> result = (Map<String, List<?>>) serviceCenterEndpoint.getInstances(
        "demo-multi-registries",
        "demo-multi-registries-server",
        "true",
        "0.0.2",
        "default");
    TestMgr.check(result.get("instances").size(), 1);
  }
}