原文链接:bbs.huaweicloud.com/blogs/42074…

Java Chassis 的早期版别依靠于 Service Center,供给了许多差异化的竞争力:

  • 接口等级转发。 通过注册中心办理微服务的每个版别的元数据,特别是契约数据。 结合契约数据,能够完成版别等级的路由能力。 比方一个微服务存在 v1 和 v2 两个版别, 其间 v1 版别存在接口 op1, op2, v2 版别存在接口 op1, op2, op3, 在灰度场景, Java Chassis能够主动将 op3 的拜访转发到 v2 版别,将 op1, op2 的拜访在 v1, v2版别做负载均衡。
  • 根据 version-rule 的实例选择。 客户端能够装备 version-rule, 比方 last, 2.0 等。 这样客户端能够依据实际情况,挑选实例的版别。

Java Chassis过度依靠 Service Center, 为产品的开展带来了一些瓶颈。 Java Chassis的生态推行依靠于 Service Center的生态推行, 不利于Java Chassis被更多用户运用。 随着云的开展, 越来越多的客户也希望一套代码,能够在不同的云环境运转,有些云产商未供给Service Center运转环境,那么用户选择Java Chassis 就会存在顾忌。

根据上述原因, Java Chassis简化了注册发现的依靠,界说了简单简单完成的接口,并根据Nacos供给了完成,未来还会供给zookeeper等完成。 Java Chassis 采用了一系列新的规划模式, 确保了在下降注册中心功能依靠的前提下,不下降运用自身的可靠性。

接口等级转发的代替方案

依靠于 Service Center, Java Chassis供给了接口等级转发。 Java Chassis 3 首要做的一个改变是删除了关于接口等级转发的支撑。 这样关于注册中心的依靠复杂度至少能够下降 70%。 然而灰度场景仍然对许多事务比较重要, Java Chassis 3运用灰度发布处理这个问题。 运用灰度发布的优点是不必依靠注册中心供给版别元数据办理能力,只需要每个实例具备版别号等简单元数据信息。

servicecomb:
  # enable router for edge service
  router:
    type: router
  routeRule:
    business: |
      - precedence: 2
        match:
          apiPath:
            prefix: "/business/v2"
        route:
          - weight: 100
            tags:
              version: 2.0.0
      - precedence: 1
        match:
          apiPath:
            prefix: "/business/v1/dec"
        route:
          - weight: 50
            tags:
              version: 1.1.0
          - weight: 50
            tags:
              version: 2.0.0

注册发现接口及其完成

Java Chassis 3 只需要运用Discovery接口就能够供给新的注册发现支撑。 Java Chassis会调用findServiceInstances查询实例,假如后续实例发生改变,注册中心完成通过InstanceChangedListener通知 Java Chassis.

/**
 * This is the core service discovery interface. <br/>
 */
public interface Discovery<D extends DiscoveryInstance> extends SPIEnabled, SPIOrder, LifeCycle {
  interface InstanceChangedListener<D extends DiscoveryInstance> {
    /**
     * Called by Discovery Implementations when instance list changed.
     * @param registryName Name of the calling discovery implementation
     * @param application Microservice application
     * @param serviceName Microservice name
     * @param updatedInstances The latest updated instances.
     */
    void onInstanceChanged(String registryName, String application, String serviceName, List<D> updatedInstances);
  }
  String name();
  /**
   * If this implementation enabled for this microservice.
   */
  boolean enabled(String application, String serviceName);
  /**
   * Find all instances.
   *
   * Life Cycle:This method is called anytime after <code>run</code>.
   *
   * @param application application
   * @param serviceName microservice name
   * @return all instances match the criteria.
   */
  List<D> findServiceInstances(String application, String serviceName);
  /**
   * Discovery can call InstanceChangedListener when instance get changed.
   */
  void setInstanceChangedListener(InstanceChangedListener<D> instanceChangedListener);
}

Java Chassis 3 通过Registration来办理注册, 注册过程分为initrundestroy简单的生命周期, 能够在init准备注册的数据,run执行注册,destroy则在注册失利或者体系中止的时分执行。

/**
 * This is the core service registration interface. <br/>
 */
public interface Registration<R extends RegistrationInstance> extends SPIEnabled, SPIOrder, LifeCycle {
  String name();
  /**
   * get MicroserviceInstance </br>
   *
   * Life Cycle:This method is called anytime after <code>run</code>.
   */
  R getMicroserviceInstance();
  /**
   * update MicroserviceInstance status </br>
   *
   * Life Cycle:This method is called anytime after <code>run</code>.
   */
  boolean updateMicroserviceInstanceStatus(MicroserviceInstanceStatus status);
  /**
   * adding schemas to Microservice </br>
   *
   * Life Cycle:This method is called after <code>init</code> and before <code>run</code>.
   */
  void addSchema(String schemaId, String content);
  /**
   * adding endpoints to MicroserviceInstance </br>
   *
   * Life Cycle:This method is called after <code>init</code> and before <code>run</code>.
   */
  void addEndpoint(String endpoint);
  /**
   * adding property to MicroserviceInstance </br>
   *
   * Life Cycle:This method is called after <code>init</code> and before <code>run</code>.
   */
  void addProperty(String key, String value);
}

注册发现的组合

Java Chassis 3能够独立完成多个DiscoveryRegistration, 达到向多个注册中心注册和从多个注册中心发现实例的作用。 每个实例依据实例ID仅有来标识。 假如实例ID相同, 会被认为是同一个实例, 假如不同, 则会认为是不同的实例。 在Java Chassis 3技能解密:注册中心分区隔离中聊到了, Java Chassis 要求每次实例注册(新的进程), 生成仅有的实例ID, 以处理注册分区隔离带来的实例假下线问题。DiscoveryRegistration都包含了 Java Chassis 界说的根底信息。

/**
 * Standard information used for microservice instance registration and discovery.
 */
public interface MicroserviceInstance {
  /**
   * Environment(Required): Used for logic separation of microservice instance. Only
   * microservice instance with same environment can discovery each other.
   */
  String getEnvironment();
  /**
   * Application(Required): Used for logic separation of microservice instance. Only
   * microservice instance with same application can discovery each other.
   */
  String getApplication();
  /**
   * Service Name(Required): Unique identifier for microservice.
   */
  String getServiceName();
  /**
   * Service Name Alias(Optional): Unique identifier for microservice.
   *   This alias is used by registry implementation to support rename
   *   of a microservice, e.g. old consumers use old service name can
   *   find a renamed microservice service.
   */
  String getAlias();
  /**
   * Service Version(Required): version of this microservice.
   */
  String getVersion();
  /**
   * Data center info(Optional).
   */
  DataCenterInfo getDataCenterInfo();
  /**
   * Service Description(Optional)
   */
  String getDescription();
  /**
   * Service Properties(Optional)
   */
  Map<String, String> getProperties();
  /**
   * Service Schemas(Optional): Open API information.
   */
  Map<String, String> getSchemas();
  /**
   * Service endpoints(Optional).
   */
  List<String> getEndpoints();
  /**
   * Microservice instance id(Required). This id can be generated when microservice instance is starting
   * or assigned by registry implementation.
   *
   * When microservice instance is restarted, this id should be changed.
   */
  String getInstanceId();
  /**
   * Microservice service id(Optional). This is used for service center, other implementations may not
   * support service id.
   */
  default String getServiceId() {
    return "";
  }
}

在完成注册发现的时分,需要确保该接口界说的根底信息能够注册到注册中心,查询实例的时分,能够获取到这些信息。

客户故事:不把鸡蛋放到同一个篮子里边,是技能选型里边很重要的考量。处理方案的开放性和可代替性、云服务的可代替性,是许多客户都关注的问题。关于一个开源的技能结构,Java Chassis早期的版别虽然规划上也支撑不同的注册中心扩展,但是完成难度很高,不自觉的把客户运用其他注册中心替换 service center的要求变得不可行。供给更加简化的注册发现完成,虽然减少了少数有有竞争力的功能特性,但是极大下降了客户选型的顾忌。