主頁 > 後端開發 > 實踐案例:同程藝龍網的 Dubbo 升級經驗總結

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

2022-12-02 06:48:03 後端開發

本篇為同程藝龍旅行網 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 技能

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/538933.html

標籤:其他

上一篇:Mybatis快取機制

下一篇:golang的jsonrpc客戶端通用寫法

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more