詳解Java Chassis 3與Spring Cloud的互操作

华为云开发者联盟發表於2024-04-10

本文分享自華為雲社群《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介面來實現其特殊功能。透過這種架構韌性的理念,降低了技術持續演進的包袱,為敏捷迭代,持續創新奠定了方向,減少了相容性問題的爭論。

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章