本文分享自华为云社区《Java Chassis 3技术解密:与Spring Cloud的互操作》,作者: liubao68。

Java Chassis 3一个很重要的设计原则:利用架构的韧性设计来解决兼容性问题。

比如通过引入微服务网关,来解决不同语言、不同框架、遗留系统之间的互操作问题。 本文在这个架构原则基础上,讨论一个更加细粒度的互操作问题,并借此解密Java Chassis3在运行时设计依赖上的技术细节。

首先,我们描述一个互操作的场景和假设。

  • Spring Cloud和Java Chassis应用同时注册到注册中心。引入了Spring Cloud Gateway作为网关,网关也注册到注册中心。
  • Spring Cloud微服务和Java Chassis微服务相互调用。它们彼此作为消费者的时候,不需要感知对方是不同的框架,做到透明调用。

从技术原理上梳理下上述互操作需要满足的条件:

  • Spring Cloud和Java Chassis需要有相互认识的注册信息。核心包括:应用名称、服务名称、地址信息和格式等。 需要的共同注册中心越少,越容易对注册中心和客户端进行选型。 在本例子中,我们选择 Service Center 或者 Nacos 作为注册中心,并选择Spring Cloud Huawei实现Spring Cloud注册。
  • Spring Cloud访问Java Chassis,只需要一个地址信息,依赖较少。 Java Chassis访问Spring Cloud,需要知道Spring Cloud应用提供的契约信息。

Java Chassis区别于Spring Cloud的REST调用的部分,就是契约依赖。 Spring Cloud通过FeignClient来声明客户端契约,客户端都需要在FeignClient中重复书写REST标签;Java Chassis有两种模式发现契约:从注册中心发现和从Provider实例发现。 Java Chassis3默认采用从Provider实例发现, Java Chassis2采用从注册中心发现。 从Provider发现的好处是可以降低对于注册中心元数据管理能力的要求,本例既可以采用 Service Center 作为注册中心,也可以选择 Nacos 作为注册中心。

从Provider发现,要求Provider实现如下接口:

/**
* Java Chassis internal management apis.
*/
@Path("/scb/management")
public interface ManagementEndpoint {
String NAME = "scb-management"; /**
* Health of this instance. If the instanceId match this instance, and this service is ready
* to service return true. Otherwise, return false.
*
* This api is for internal instance status usage. Load balancer will call this api to check if
* the target instance is alive.
*/
@GET
@Path("/health")
boolean health(@QueryParam("instanceId") String instanceId, @QueryParam("registryName") String registryName); /**
* Schemas of this instance.
*
* This api is for internal schema loading usage.
*/
@POST
@Path("/schema/contents")
Map<String, String> schemaContents();
}

它包含一个健康检查接口和一个查询契约的接口。 当Spring Cloud应用实现上述接口以后,它就具备了Java Chassis微服务需要的基础特征,这样Java Chassis就可以像访问本框架的微服务一样访问Spring Cloud框架开发的微服务应用。 为了简化,在Spring Cloud简单实现了该接口,该实现接口从 export 目录加载契约信息,只需要将Spring Cloud需要对外暴露的 REST 接口的符合 Open API 3.0规范的契约文件放到这个目录下面 。

@RestController
@RequestMapping(("/scb/management"))
public class JavaChassisManagementEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaChassisManagementEndpoint.class); @Autowired
private Registration registration; @GetMapping(path = "/health")
public boolean health(@RequestParam("instanceId") String instanceId,
@RequestParam("registryName") String registryName) {
return "sc-registry".equals(registryName) && registration.getInstanceId().equals(instanceId);
} @PostMapping(path = "/schema/contents")
public Map<String, String> schemaContents() {
try {
List<URI> resourceUris = ResourceUtil.findResourcesBySuffix("export", ".yaml");
Map<String, String> result = new HashMap<>(resourceUris.size());
for (URI uri : resourceUris) {
String path = uri.toURL().getPath();
String[] segments = path.split("/");
if (segments.length < 2 || !"export".equals(segments[segments.length - 2])) {
continue;
}
result.put(segments[segments.length - 1].substring(0, segments[segments.length - 1].indexOf(".yaml")),
IOUtils.toString(uri, StandardCharsets.UTF_8));
}
return result;
} catch (IOException | URISyntaxException e) {
LOGGER.error("Load schema ids failed from microservices. {}.", e.getMessage());
return Collections.emptyMap();
}
}
}

Java Chassis与Spring Cloud互操作的例子放到了ServiceComb Samples , 这个例子也提供了使用 Nacos 作为注册中心和配置中心的实现, 只需要将 Profile 设置为 Nacos 即可。

客户故事:在架构选型变化的时候,解决功能迁移和兼容性问题是最大的挑战。一些客户将Spring Cloud应用改造为Java Chassis的过程中,发现一些功能不支持,比如SseEmitter、WebSocket等。 如果选择支持这些能力,Java Chassis需要实现很多Servlet能力,这些能力规划会和微服务技术架构存在冲突。 对于这些场景,我们选择通过架构韧性来保留这些功能,比如将提供SseEmitter、WebSocket功能的独立出微服务,采用Spring Boot开发,这些应用可以通过调用Java Chassis微服务的REST接口来实现其特殊功能。通过这种架构韧性的理念,降低了技术持续演进的包袱,为敏捷迭代,持续创新奠定了方向,减少了兼容性问题的争论。

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

详解Java Chassis 3与Spring Cloud的互操作的更多相关文章

  1. java基础(十五)----- Java 最全异常详解 ——Java高级开发必须懂的

    本文将详解java中的异常和异常处理机制 异常简介 什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常. Java异常的分类和类结构图 1.Java中的所 ...

  2. 详解java动态代理机制以及使用场景

    详解java动态代理机制以及使用场景 https://blog.csdn.net/u011784767/article/details/78281384 深入理解java动态代理的实现机制 https ...

  3. 「跬步千里」详解 Java 内存模型与原子性、可见性、有序性

    文题 "跬步千里" 主要是为了凸显这篇文章的基础性与重要性(狗头),并发编程这块的知识也确实主要围绕着 JMM 和三大性质来展开. 全文脉络如下: 1)为什么要学习并发编程? 2) ...

  4. 详解Java GC的工作原理+Minor GC、FullGC

    详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...

  5. Protocol Buffer技术详解(Java实例)

    Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...

  6. Spring Cloud Netflix多语言/非java语言支持之Spring Cloud Sidecar

    Spring Cloud Netflix多语言/非java语言支持之Spring Cloud Sidecar 前言 公司有一个调研要做,调研如何将Python语言提供的服务纳入到Spring Clou ...

  7. 详解Java中的clone方法

    详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ...

  8. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

  9. 第三节:带你详解Java的操作符,控制流程以及数组

    前言 大家好,给大家带来带你详解Java的操作符,控制流程以及数组的概述,希望你们喜欢 操作符 算数操作符 一般的 +,-,*,/,还有两个自增 自减 ,以及一个取模 % 操作符. 这里的操作算法,一 ...

  10. 第十八节:详解Java抽象类和接口的区别

    前言 对于面向对象编程来说,抽象是它的特征之一. 在Java中,实现抽象的机制分两种,一为抽象类,二为接口. 抽象类为abstract class,接口为Interface. 今天来学习一下Java中 ...

随机推荐

  1. MindSponge分子动力学模拟——使用MDAnalysis工具进行后分析(2024.02)

    技术背景 分子动力学模拟(Molecule Dynamics Simulation,MD),本质上是一门采样技术.通过配置力场参数.拓扑结构和积分器,对一个给定的体系不断的采样,最终得到一系列的轨迹. ...

  2. 【Azure Redis 缓存】Azure Redis 遇见的连接不上问题和数据丢失的情况解答

    问题描述 PHP应用再连接Azure Redis服务时,出现Connection Timed out.当通过升级提高Azure Redis的性能时候,发现之前的数据丢失了. 问题解答 当Redis服务 ...

  3. 【Azure Developer】解答《美丽的数学》一书中P120页的一道谜题:寻找第四个阶乘和数

    一道谜题 在观看<美丽的数学>一书中,在120页中有一道谜题: 数字145被称为一个阶乘和数, 因为它具有以下有趣的属性,如果我们将它的各位数字的阶乘相加,会得到该数字本身 1! +4! ...

  4. C++11的类型转换

    //C类型转换 /* C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败 显式类型转化:需要用户自己处理. 隐式类型:界定:相关类型,相近类型,意义相似的类 ...

  5. Java 常用类 String的使用

    1 package com.bytezero.stringclass; 2 3 import com.sun.tools.javac.Main; 4 import jdk.jfr.StackTrace ...

  6. C++ Qt开发:运用QThread多线程组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QTh ...

  7. 2、dubbo原理

    图例说明: 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口. 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖 ...

  8. 玩转SpringBoot:SpringBoot的几种定时任务实现方式

    引言 在现代软件开发中,定时任务是一种常见的需求,用于执行周期性的任务或在特定的时间点执行任务.这些任务可能涉及数据同步.数据备份.报表生成.缓存刷新等方面,对系统的稳定性和可靠性有着重要的影响.Sp ...

  9. Android 多module情况下module依赖aar问题处理

    原文: Android 多module情况下module依赖aar问题处理 - Stars-One的杂货小窝 问题描述 负责一个大项目Android工程项目,新增了一个module,而此module由 ...

  10. day04-实现SpringBoot底层机制

    实现SpringBoot底层机制 Tomcat底层启动分析+Spring容器初始化+Tomcat关联Spring容器 1.任务1-创建Tomcat,并启动 (1)创建一个Maven项目,修改pom.x ...