實踐案例:同程藝龍網的 Dubbo 升級經驗總結

来源:https://www.cnblogs.com/apache-dubbo/archive/2022/12/01/16942431.html
-Advertisement-
Play Games

什麼是緩存? 為什麼使用緩存? 什麼場景下使用緩存? 緩存(Cache)就是數據交換的緩衝區,一個臨時存儲數據的地方,當我們讀取數據時會首先從緩存中查找需要的數據,如果找到了則直接執行,找不到的話再從記憶體中找。 在實際開發中,我們會經常對資料庫進行數據查詢,而從資料庫讀取數據的效率是非常低下的,並且 ...


本篇為同程藝龍旅行網 Apache Dubbo 的實踐案例總結。感興趣的朋友可以訪問官網瞭解更多詳情,或搜索關註官方微信公眾號 Apache Dubbo 跟進最新動態。

作者信息:

  • 嚴浩:同程藝龍高級開發,負責服務治理相關工作, Apache Dubbo Committer。
  • 胥皓:同程藝龍高級開發,負責服務治理相關工作。

Dubbo3在同程旅行的實踐

背景

在微服務發展初期,市場上還沒有成熟和流行的 RPC 框架,我們公司內部自研開發了一套名為 DSF (Distributed Service Framework) 的 RPC 框架,支撐起了公司業務的高速發展。但是隨著技術的快速迭代和人員的不斷變更,開發者既要修複之前的 BUG 又要跟上技術的更新,開發維護成本越來越高。另一方面,現在應用程式都在往雲原生方向發展與設計,公司也在這方面做出探索。因此公司微服務框架的演進已經到了岔路口,是全新升級原有的 SDK,還是選擇擁抱開源?

考慮到升級現有的 SDK 在一段時間之後可能依然會面臨現在的問題,最後我們選擇了擁抱開源。在一番調研之後我們選擇了 Dubbo3 作為公司的下一代 RPC 框架,擔任微服務治理體系的數據面。

目前 Dubbo3 在公司的落地開發工作已經完成,通過本文我們對公司內部 Dubbo3 的實踐及收益做了深入總結。

Dubbo3 核心功能介紹

Dubbo 社區關於 Dubbo 3 的文檔和資料越來越完善,以下是我們從社區引用的一些內容。

Dubbo3 被社區寄予厚望,將其視為下一代雲原生服務框架打造,Dubbo3 提供的核心特性列表,主要包括四部分。

  1. 全新服務發現模型。應用粒度服務發現,面向雲原生設計,適配基礎設施與異構系統;性能與集群伸縮性大幅提升。
  2. 下一代 RPC 協議 Triple。基於 HTTP/2 的 Triple 協議,相容 gRPC;網關穿透性強、多語言友好、支持 Reactive Stream。
  3. 統一流量治理模型。面向雲原生流量治理,SDK、Mesh、VM、Container 等統一治理規則;能夠支持更豐富的流量治理場景。
  4. Service Mesh。在最新的3.1.0的版本中支持Sidecar Mesh 與 Proxyless Mesh,提供更多架構選擇,降低遷移、落地成本。

Dubbo3 的核心功能點(如應用級服務發現以 ip、port 為區分實例)和公司內部的服務模型一致,極大地減少了我們的適配工作。還有在 Service Mesh 中對 Sidecar Mesh 與 Proxyless Mesh 的支持也將減少後續公司對 Mesh 方案的探索成本,包括 Dubbo3 在多語言體系的發展也為異構架構提供了支撐。

總的來說,Dubbo3 非常契合公司的技術體系和後續的發展方向。此外,Dubbo 在開發者中的熟悉度、社區的高活躍度和完善的文檔建設也都能為推動 Dubbo3 的使用帶來不少的幫助。

方案調研

在瞭解了 Dubbo3 的核心功能和基本工作原理之後我們開始前期工作階段。

公司內部存在微服務體系 RPC 框架 DSF 和承擔服務發現、路由、上下負載等功能的控制中心,如果讓用戶直接切換到 Dubbo3 使用完全隔離的一套微服務體系會對用戶帶來高額的升級和切換成本。所以我們選擇用 Dubbo3 替換之前的 DSF 框架作為數據面,將 Dubbo3 接入當前的微服務控制中心。同時要求 Dubbo3 支持原有 DSF 框架的私有協議,與 DSF 框架能夠相互發現和調用,進一步降低用戶升級成本。

這樣用戶在編程習慣上和 Dubbo3 的使用完全保持一致,在服務治理上(如上下負載、同中心路由、實例標簽等功能)的使用與 DSF 保持一致。由於協議相容,新的 Dubbo3 應用和原有 DSF 應用之間也能實現互相發現和調用。

要完成這個目標,需要去拓展 Dubbo3 SDK 的註冊模塊支持從現有的控制中心進行服務註冊與發現、擴展自定義協議與 DSF 服務相互調用。藉助於Dubbo 強大的插件機制,我們在沒有修改 Dubbo 框架任何代碼的基礎上輕鬆地完成了這個目標,用戶只需要引入 Dubbo 3.0 以上版本的 SDK 和我們開發的插件包即可。

整體的架構流程如下:

Dubbo3 落地的方案需要滿足以下三點要求:

  1. Dubbo3 要接入現有的控制中心,由控制中心完成服務註冊發現和服務治理功能;
  2. Dubbo3 能夠和 DSF 能夠相互調用,滿足此要求需要兩個框架能夠互相服務發現並且協議能夠相容;
  3. 通過插件機制完成所有功能,不能修改 Dubbo 源碼,用戶可以自由地升級 Dubbo3 SDK 的版本;

服務註冊發現相容

既然需要將 Dubbo3 的應用級註冊接入到控制中心,而且需要與 DSF 服務進行服務發現,就需要瞭解 Dubbo3 應用級發現的流程才能對其進行更好的拓展。

應用級服務發現核心原理

我們從 Dubbo 最經典的工作原理圖說起。Dubbo 從設計之初就內置了服務地址發現的能力,Provider 註冊地址到註冊中心,Consumer 通過訂閱實時獲取註冊中心的地址更新,在收到地址列表後,Consumer 基於特定的負載均衡策略發起對 Provider 的 RPC 調用。
在這個過程中:

  1. 每個 Provider 通過特定的 key 向註冊中心註冊本機可訪問地址;
  2. 註冊中心通過這個 key 對 Provider 實例地址進行聚合;
  3. Consumer 通過同樣的 key 從註冊中心訂閱,以便及時收到聚合後的地址列表;

可以看到介面級服務發現是以介面為維度進行服務註冊的,併在註冊數據上攜帶了服務的配置和元數據。這種方式簡單易用而且可以輕鬆實現應用、介面、方法粒度的服務治理。但由此帶來的註冊數據的放大問題會給註冊中心造成較大壓力,還有就是與現在雲原生的服務模型並不相容,不能與 Kubernetes 相容。

面對這些不足,在 Dubbo3 架構下社區認真思考了兩個問題:

  1. 如何在保留易用性、功能性的同時,重新組織 URL 地址數據,避免冗餘數據的出現,讓 Dubbo 3 能支撐更大規模集群水平擴容?
  2. 如何在地址發現層面與其他的微服務體系如 Kubernetes、Spring Cloud 打通?

最終,社區給出的方案也是非常巧妙和經典,將之前介面級服務的數據拆成兩部分。屬於實例模型的 ip 和 port 註冊到註冊中心,而屬於業務屬性的 RPC 元數據和 RPC 服務配置統一由 Dubbo Provider 的 MetadataService RPC 服務提供或者由元數據中心提供。在服務消費端和提供端之間建立了一條內置的 RPC 服務信息協商機制,也稱為"服務自省"。全新的應用級服務發現模型,相比之前介面級別單機記憶體下降 50% 且極大的減少了註冊中心的壓力。

還有一個問題是換成了應用級服務發現之後,Consumer 是如何知道訂閱的介面是屬於哪一個服務的?因為 Dubbo 的編程模型是以介面為維度的。Dubbo3 提供了兩種解決方案:一是從元數據中心存儲介面和應用名的映射關係,二是通過 Consumer 在介面上通過 providerBy 配置手動指定服務提供方的名稱。

相容方案

如果是 Dubbo Consumer 調用 Dubbo Provider,我們只需要按部就班參考其他應用級別服務發現的插件比如 Zookeeper、Nacos 開發就可以完成此功能。如果 DSF Client 要調用 Dubbo Provider 我們是將相容邏輯放在了控制中心,避免用戶 SDK 的升級成本。剩下的相容流程只有 Dubbo Consumer 調用 DSF Server 了,因為要求儘量不要修改 Dubbo 框架的源碼,所以這裡的相容邏輯我們只能在註冊中心的插件中完成。

上面介紹應用級服務發現的核心原理的時候提到應用級服務發現有 3 個關鍵的步驟

  1. 通過元數據的 mapping 獲取介面對應的服務名或者通過介面配置中的 providerBy 指定;
  2. 通過服務名獲取實例列表,實例以 ip、port 為維度,並且在實例信息中攜帶元數據的 revision;
  3. 調用 Dubbo Provider 的 MetaService 獲取實例的元數據信息,組裝介面數據;

Dubbo 服務 調用 DSF 服務相容流程的第一步非常簡單,因為 DSF 並沒有介面與服務名的 mapping 數據,所以通過 providerBy 指定介面所屬的 DSF 服務名。第二步因為 DSF 服務的註冊模型也是應用級的,實例的數據完全可以相容這一部分也很簡單。最關鍵的一步在於如何獲取 DSF 服務的元數據,很顯然現有的 DSF 服務並不具有 MetaService 的介面。

上面提到 Dubbo3 支持兩種方式獲取實例的元數據。預設就是從 Dubbo Provider 的 MetaService 獲取實例的元數據信息,也支持從元數據中心獲取實例的元數據信息,只需要將實例的 dubbo.metadata.storage-type 屬性設置為 remote 即可。而 DSF 服務正好發佈了 API 的契約數據到控制中心用作服務測試和定址相容,完全可以將 DSF 的契約數據轉換為 Dubbo 的元數據的格式,滿足服務發現的流程。

以下為 Dubbo Consumer 發現 DSF 服務的流程

完成服務發現的相容之後,用戶在調用 DSF 服務的時候僅需要在介面上通過 providerBy 指定介面對應的服務即可,使用成本極低。

協議相容與服務治理

協議相容

完成服務發現的相互相容之後,離 Dubbo 與 DSF 服務的相互調用的目標只剩最後一塊拼圖,在插件中實現 DSF 協議即可。
相比服務發現的各種數據相容,協議的相容比較清晰,只需要根據 Dubbo 協議擴展說明進行自定義協議擴展完成 DSF 數據格式相容即可。

Dubbo 協議擴展需要實現以下介面:

  • org.apache.dubbo.rpc.Exporter
  • org.apache.dubbo.rpc.Invoker
  • org.apache.dubbo.rpc.Protocol

當用戶調用 refer() 所返回的 Invoker 對象的 invoke() 方法時,協議需相應執行同 URL 遠端 export() 傳入的 Invoker 對象的 invoke() 方法。其中,refer() 返回的 Invoker 由協議實現,協議通常需要在此 Invoker 中發送遠程請求,export() 傳入的 Invoker 由框架實現並傳入,協議不需要關心。也就是說服務提供方在容器啟動的時候就進行服務的暴露,而服務調用方需要通過協議進行Invoker的調用。我們的擴展如下:

最後完成的效果如下,用戶只需要在 pom 中引入 Dubbo3 以上的任意版本和開發的插件,配置上指定註冊中心地址和協議為 dsf 即可,其他使用方式和 Dubbo3 保持一致。

<properties>
    <dubbo.version>3.0.11</dubbo.version>
    <dubbo-dsf.version>1.0.0</dubbo-dsf.version>
</properties>

<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>${dubbo.version}</version>
</dependency>
<dependency>
    <groupId>com.ly.dsf</groupId>
    <artifactId>dubbo-dsf-extensions-all</artifactId>
    <version>${dubbo-dsf.version}</version>
</dependency>

配置文件

# 註冊地址為控制中心
dubbo.registry.address=dsf://{address}
# 協議指定 dsf
dubbo.protocol.name=dsf
dubbo.consumer.protocol=dsf

服務治理

Dubbo3 有非常強大的流量治理的功能,同時我們內部的控制中心也有服務治理的功能,部分功能也有重合。

對於這部分的取捨,我們打算控制中心原有的功能對 Dubbo3 服務依然支持,如服務發現、同中心定址、上下負載、服務測試等操作和之前保持一致。而 Dubbo 特有的服務治理功能如動態配置、Mesh 路由,我們將新增功能對其支持,保證 Dubbo3 功能的完整。

總結

Dubbo 3 是一個優秀的微服務框架,提供的 SPI 以及 Extension 機制能夠非常方便的讓用戶去擴展實現想要功能。而且 Dubbo3 也更適應目前雲原生的架構,Dubbo 3.1.x 版本支持 Sidecar 和 Proxyless 的 Mesh 方案,而且社區也在準備開源 Java Agent 方式的 Proxyless,這樣就能較好的將微服務架框的 Framework 與數據面解耦,降低微服務框架的維護成本和升級成本。我們也會和社區一起探索,共建 Dubbo 社區的繁榮。

搜索關註官方微信公眾號:Apache Dubbo,瞭解更多業界最新動態,掌握大廠面試必備 Dubbo 技能


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 案例介紹 歡迎來到我的小院,我是霍大俠,恭喜你今天又要進步一點點了!我們來用JavaScript編程實戰案例,做一個隨機密碼生成器。用戶點擊生成,輸入框內就會生成一個由數字、大小寫字母、特殊符號隨機組合而成的密碼。通過實戰我們將學會Math.floor方法、substring方法、clipboard ...
  • Error Error是JavaScript語言中的一個標準的內置對象,專門用於處理JS開發中的運行時錯誤。 當我們的JS代碼在運行過程中發生錯誤的話,就會拋出Error對象,整個程式將會中斷在錯誤發生的代碼處,不再繼續執行,這也是錯誤類型必須重視的原因:它會導致頁面無法顯示或者功能失效。 Erro ...
  • File類和IO流 File類 概述 public class File 文件和目錄路徑名的抽象表示 文件和目錄是可以通過File封裝成對象的 封裝的不是文件,而是一個路徑(可以存在,也可以不存在);要通過具體的操作將這個路徑轉化為具體存在 public class FileDemo { publi ...
  • 1.可以從現有的類派生出新類。這稱為類的繼承。新類稱為次類、子類或派生類。現有的類稱為超類、父類或基類。 2.構造方法用來構造類的實例。不同於屬性和方法,子類不繼承父類的構造方法。它們只能用關鍵字super從子類的構造方法中調用。 3.構造方法可以調用重載的構造方法或它的父類的構造方法。這種調用必須 ...
  • Java 程式員在日常工作中經常會聽到 SPI,而且很多框架都使用了 SPI 的技術,那麼問題來了,到底什麼是 SPI 呢?今天阿粉就帶大家好好瞭解一下 SPI。 SPI 概念 SPI 全稱是 Service Provider Interface,是一種 JDK 內置的動態載入實現擴展點的機制,通過 ...
  • 一、引言 在上一篇文章中《這麼簡單,還不會使用java8 stream流的map()方法嗎?》分享了使用stream的map()方法,不知道小伙伴還有印象嗎,先來回顧下要點,map()方法是把一個流中的元素T轉換為另外一個新流中的元素R,轉換完成後兩個流的元素個數不發生改變,具體怎麼使用,請小伙伴移 ...
  • 大家好,這裡是 main工作室。 開發工具合集 是 電腦編程語言 和 嵌入式軟體/硬體 開發工具的下載與安裝,每篇一個開發工具。 本篇所講的開發工具為: Dev-Cpp 一、介紹 Dev-Cpp Dev-Cpp 是一個 Windows 環境下的一個適合於初學者使用的輕量級 C/C++ 集成開發環境 ...
  • 服務端 package main import ( "errors" "fmt" "log" "net" "net/rpc" "net/rpc/jsonrpc" "os" ) // 算數運算結構體 type Arith struct { } // 算數運算請求結構體 type ArithReques ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...