本文分享自华为云社区《JavaChassis3技术解密:易扩展的多种注册中心支持》,作者:liubao68。

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可以独立实现多个 Discovery 和 Registration, 达到向多个注册中心注册和从多个注册中心发现实例的作用。 每个实例根据实例ID唯一来标识。 如果实例ID相同, 会被认为是同一个实例, 如果不同, 则会认为是不同的实例。 在 Java Chassis 3技术解密:注册中心分区隔离 中聊到了, Java Chassis 要求每次实例注册(新的进程), 生成唯一的实例ID, 以解决注册分区隔离带来的实例假下线问题。 Discovery 和 Registration 都包含了 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的要求变得不可行。提供更加简化的注册发现实现,虽然减少了少量有有竞争力的功能特性,但是极大降低了客户选型的顾虑。

点击关注,第一时间了解华为云新鲜技术~

解密JavaChassis3:易扩展的多种注册中心支持的更多相关文章

  1. springcloud微服务总结二 注册中心

    一:netflix和springcloud关系 netflix公司开源了很多组件,包括服务注册与发现(Netflix Eureka).断路器(Netflix Hystrix).负载均衡(Netflix ...

  2. Dubbo -- 系统学习 笔记 -- 示例 -- 多注册中心

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多注册中心 可以自行扩展注册中心,参见:注册中心扩展 (1) 多注册中心注册 比如 ...

  3. 自研分布式高性能RPC框架及服务注册中心实践笔记【原创】【开源】

    痛点 1. bsf底层依赖springcloud,影响bsf更新springboot新版本和整体最新技术版本升级. 2. eureka已经闭源,且框架设计较重,同时引入eureka会自行引入较多spr ...

  4. Dubbo源码学习--注册中心分析

    相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 注册中心 关于注册中心,Dubbo提供了多个实现方式,有比较成熟的使用zookeeper 和 redis 的 ...

  5. 如果有人问你 Dubbo 中注册中心工作原理,就把这篇文章给他

    注册中心作用 开篇首先想思考一个问题,没有注册中心 Dubbo 还能玩下去吗? 当然可以,只要知道服务提供者地址相关信息,消费者配置之后就可以调用.如果只有几个服务,这么玩当然没问题.但是生产服务动辄 ...

  6. 开发dubbo应用程序(二)dubbo注册中心相关概述

    1.注册中心概述 ​ 在Dubbo微服务体系中,注册中心是其核心组件之一.Dubbo通过注册中心实现了分布式环境中各微服务之间的注册与发现,是各分布式节点之间的纽带.其主要作用如下: 动态加入.一个服 ...

  7. 这个Dubbo注册中心扩展,有点意思!

    今天想和大家聊聊Dubbo源码中实现的一个注册中心扩展.它很特殊,也帮我解决了一个困扰已久的问题,刚刚在生产中用了,效果很好,迫不及待想分享给大家. Dubbo的扩展性非常灵活,可以无侵入源码加载自定 ...

  8. 灵感乍现!造了个与众不同的Dubbo注册中心扩展轮子

    hello大家好呀,我是小楼. 作为一名基础组件开发,服务好每一位业务开发同学是我们的义务(KPI). 客服群里经常有业务开发同学丢来一段代码.一个报错,而我们,当然要微笑服务,耐心解答. 有的问题, ...

  9. Gitea 1.18 功能前瞻(其三):增强文本预览效果、继续扩展软件包注册中心、增强工单实用功能、完善了用户邀请机制和SEO

    今天是 10 月 26 日星期三,Gitea 周期性地发布了 1.18 的第一个 RC0 版本,在此阶段会收集一些功能和使用上的问题,随后还会发布 RC1,新功能的完整性和健壮性会逐步趋近正式版. 继 ...

  10. dubbo在idea下的使用创建 服务者,消费者 注册中心

    1.基于windows 下  spring 下的dubbo  需要书写配置文件 (1).创建带有web工程的项目 创建一个服务者 package cn.edu.aynu.bean; import lo ...

随机推荐

  1. <vue 基础知识 4、计算属性computed>

    代码结构 一.     计算属性简单使用 1.效果 2.代码 01-计算属性简单用法.html <!DOCTYPE html> <html lang="en"&g ...

  2. div模拟表格单元格合并

    效果如下图: html代码如下: 1 <ul class="schedule-list"> 2 <li class="schedule-title&qu ...

  3. Winform的使用

    Winform是什么 以下内容,来自朝夕教育课程,没有基础的可以去朝夕学学.这里主要是为了方便我自己回顾查询 创建Winform程序 Program类 Winform项目结构介绍 Winform控件简 ...

  4. Redis 主从复制架构配置及原理

    本文为博主原创,未经允许不得转载: 目录: 1. Redis 主从复制架构搭建 2. Redis 主从架构原理 3. Redis 断点续传 4. Jedis 连接 redis 主从架构一般配置一主多从 ...

  5. Gradle 出现 Could not resolve gradle

    Gradle 在进行 sync 的时候会出现 Caused by: org.gradle.internal.resolve.ModuleVersionResolveException: Could n ...

  6. spring--JDK动态代理和CGLIB代理的区别

    JDK 动态代理和 CGLIB 代理是 Java 中常用的两种动态代理实现方式,它们各有特点和适用场景: JDK 动态代理: JDK 动态代理是基于接口的代理方式,它使用 Java 反射机制来创建代理 ...

  7. [转帖]arm linux下编译xtrabackup-2.4.5

    环境:aarch64/centos7.6  glibc-2.17 编译器:gcc version 5.5.0 (GCC) 官方参考文档:https://www.percona.com/doc/perc ...

  8. [转帖]linux 内核协议栈 TCP time_wait 原理、配置、副作用

    https://my.oschina.net/u/4087916/blog/3051356   0. 手把手教你做中间件.高性能服务器.分布式存储技术交流群 手把手教你做中间件.高性能服务器.分布式存 ...

  9. vue3异步组件按需加载和vue2异步组件的按需加载

    vue3 按需加载组件 子组件.vue <template> <div> <p>这个组件按需加载</p> <h1>这个组件显示</h1 ...

  10. vue数据不响应,可能是用法有问题

    <template> <div> <div> <span>用户名: {{ userInfo.name }}</span> <span& ...