Go 語言體系下的微服務框架選型:Dubbo-go

阿里巴巴雲原生發表於2023-04-11

*作者簡介:牛學蔚(GitHub: @justxuewei):Apache Dubbo PMC,對雲原生、中介軟體、容器等領域有濃厚興趣,活躍在 Dubbo 和 Kata containers 兩個開源專案中。*


## 01 Go 微服務體系發展與選型


隨著微服務技術的快速發展,其在各個領域都形成了一系列事實標準,在 Kubernetes 和容器技術加持下,雲原生微服務已經成為了主流解決方案。而 Go 語言作為雲原生領域最 受歡迎的開發語言,正被越來越多的企業作為微服務開發的首 選語言,其中比較流行的包括 Go-micro、Go-zero、Dubbo-go 等。作為 Dubbo 微服務體系中多語言實現的一員,在 2022 年 Dubbo-go 以微服務領跑者的角色積極擁抱雲原生標準,探索了 Proxyless Mesh 形態,配合適配 Pixiu 雲原生閘道器,形成了完善的 Dubbo-go 微服務生態矩陣。


以 Dubbo-go 為中心的微服務體系在多個知名企業中成功落地和實踐,框架的穩定性在實際場景下經受住了考驗。截止今年已有 60+ 家企業在我們的使用者列表中登記,其中較為典型案例請參考文章《小米電商 Apache Dubbo-go 微服務實踐》。小米電商選用了 Dubbo-go + Nacos + sidecar + etcd + mirpc 為核心的微服務體系,除了看中了 Dubbo-go 的互聯互通和服務治理能力外,也認可 Dubbo-go 在微服務方向的沉澱和積累。


## 02 Dubbo-go 簡介


### 2.1 什麼是 Dubbo-go


Apache Dubbo 是一款易用、高效能的 WEB 和 RPC 框架,同時為構建企業級微服務提供服務發現、流量治理、可觀測、認證鑑權等能力、工具與最 佳實踐。Dubbo3 從設計上不繫結程式語言,社群目前提供了 Java、Go、Rust、Node.js 等多語言實現,在未來,我們計劃為所有主流語言提供對等的微服務開發體驗。


Dubbo 框架作為國內最 具影響力的開源微服務開發框架之一,擁有非常高的關注度和活躍度,在 GitHub 上擁有 3.8 萬+ stars。Dubbo 專案於 2017 年捐贈給 Apache 基金會,在經歷了短短 15 個月孵化後順利畢業,在 Apache 基金會管理的全部專案中關注度排名第三(前兩名分別是 echarts 和 superset),Dubbo-go 作為 Dubbo 多語言生態的重要一員,很好的相容 Dubbo 生態的同時提供面向 Go 語言體系的微服務開發體驗。


Dubbo-go(專案地址 github.com/apache/dubbo-go)作為 Dubbo 多語言生態的重要組成部分,目前完全兌現了 Dubbo3 架構的核心能力,並且在雲原生時代,憑藉 Go 語言無需重量級虛擬機器、靜態編譯以及垃圾回收的特性,獲得了廣泛關注,其應用規模也逐漸擴大。從特性上來說,Dubbo-go 目前支援 HTTP/2、TCP、gRPC 協議通訊、服務發現、流量管控、配置管理、全鏈路追、視覺化觀測等諸多新特性,Dubbo3 已是眾多使用者生產環境首 選的微服務框架(使用者列表);在生態建設方面,Dubbo-go 適配了包括 Zookeeper、Nacos、Sentinel、Zipkin、Kubernetes、Prometheus、雲原生 API 閘道器專案 Dubbo-pixiu、非同步網路庫 Dubbo-getty、Hessian2 等生態專案。


2022 年 Dubbo-go 社群以生態互聯、開發者體驗、穩定性為切入點,不斷最佳化系統架構,社群榮獲多個開源獎項:


-   Dubbo 生態被評為 2021 年中國 20 大最活躍社群之一

-   Dubbo-go 入圍 2021 年“科創中國”榜單。

-   Dubbo-go 開源社群被 OSCHINA 評為“2022 年度 OSCHINA 優秀開源技術團隊”。


### 2.2 重要特性


**通訊協議:** 遵循 Dubbo 核心架構設計,Dubbo-go 在實現上不繫結通訊協議,目前支援 HTTP/2、TCP (Dubbo2)、JSONRPC、gRPC、HTTP 等多種通訊協議,開發者可以根據使用場景靈活的選擇通訊協議。


**服務註冊:** 支援 Client-based 服務發現機制,支援註冊中心適配如 Nacos、Consul、Zookeeper 等。Dubbo3 的服務發現機制誕生於阿里巴巴超大規模微服務電商叢集實踐場景,其在效能、可伸縮性、易用性等方面的表現大幅領先於業界大多數主流開源產品。


**配置中心:** Dubbo 配置中心可實現應用配置的遠端託管,支援配置變更的實時感知,目前支援 Nacos、Apollo(攜程開源)、ZooKeeper 等作為配置中心。


**負載均衡:** Dubbo 提供了多種負載均衡策略,如隨機負載均衡策略、一致性雜湊負載、基於權重的輪詢、最小活躍度優先、自適應負載均衡 P2C 等。


**流量控制:** Dubbo 的流量管控規則可以基於應用、服務、方法、引數等粒度精準的控制流量走向,基於此可靈活的實現超時時間調整、開啟訪問日誌、金絲雀釋出、引數路由、同區域優先、按比例流量分發等。除此之外,透過接入 Hystrix、Sentinel 等,Dubbo-go 還支援自適應限流、限流熔斷等。


**分散式事務:** 支援 Seata-golang 分散式事務框架,實現了 AT 模式和 TCC 模式分散式事務的呼叫,AT 模式相較 TCC 模式對程式碼的入侵性更小、需要開發的介面更少,但 AT 模式對事務操作的資料持有全域性鎖,TCC 模型效能更好。


**鏈路追蹤:** 支援基於 Jaeger、ZipKin 的鏈路追蹤能力。


**指標視覺化:** 支援使用 Prometheus 收集框架指標和使用者指標。


**可擴充套件性:** Dubbo-go 提供了靈活的 extension 擴充套件機制,使用者可隨時根據自己的需求靈活擴充套件服務發現、負載均衡、配置中心、流量管控規則、全鏈路追蹤等中介軟體。


## 03 過去一年我們做了什麼


### 3.1 優雅上下線


在微服務場景下,業務是以容器的形式對外提供服務,k8s 能夠方便的對 Pod 進行滾動升級,在舊版本被替換的時候應該達到無損下線的效果,即容器不能被銷燬直到沒有正在處理的請求。如果其不能被正確實現,對於承載高流量的線上服務來說,在更新期間可能會導致大量的請求報錯,甚至可能觸發報警,其影響是巨大的。優雅上下線功能是 Dubbo-go 3.0 正式版本釋出後的第一個重大增強,王曉偉同學(GitHub: @XiaoWeiKIN)貢獻了全流程的優雅上下線能力。


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


Dubbo 經典的呼叫流程如上圖所示,這裡麵包含了服務提供者(Provider)、服務消費者(Consumer)以及註冊中心(Registry)三個關鍵元件,一個服務能夠被呼叫,首先需要提供者準備服務並對外暴露埠(步驟 0),然後提供者需要將呼叫資訊註冊到註冊中心中(步驟 1),消費者則會透過非同步訂閱的方式獲取最新的提供者資料(步驟 2),註冊中心在有新資料後會主動推送給消費者(步驟 3),此時消費者已經有本次呼叫的全部資訊了,最後消費者傳送呼叫請求(步驟 4),這樣就完成了整個呼叫鏈路。


在單體應用中,上述邏輯非常清晰和簡單,但是在大規模微服務叢集中,這個邏輯的每一個細節都需要被仔細推敲後,才能保證上下線的過程中呼叫不出錯。


**![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")**


**優雅上線**的目標是解決服務上線呼叫報錯的問題,主要針對微服務場景下的呼叫依賴問題。在 Dubbo 生態中,Service 表示一個服務,能夠被暴露並被其他服務呼叫,Reference 表示引用,可以簡單的理解為下游服務。一個典型呼叫結構如上圖所示,該服務對外暴露一個介面,同時引用了下游的 N 個服務。該服務在上線的時候應該嚴格遵循以下流程,首先保證下游服務的引用被成功初始化,之後再初始化 Service 對外暴露服務,最後再向註冊中心註冊服務。優雅上線相對來說邏輯比較簡單,只需要嚴格遵循初始化過程的依賴關係就能保證上線過程中服務能夠被正常呼叫。


**優雅下線**是優雅上下線的難點,涉及到了訊號監聽、反註冊、等待已有請求完成呼叫等邏輯。在需要銷燬容器的時候,kubelet 會向容器傳送 SIGTERM 訊號,Dubbo-go 會進入優雅下線流程,此時容器並不會立刻被銷燬。即將下線的提供者首先會執行反註冊,即向註冊中心中刪除自己的資訊,消費者可以透過訂閱獲得這個資訊,這個過程需要一定的時間。換句話說,在消費者獲得這個刪除資訊之前,流量還是有可能會流向該提供者,此時提供者應該拒絕這部分請求。當然除了下線期間的新請求外,還有殘留的來自上游的請求以及自己呼叫下游的請求,我們分別為這兩種情況設定一個計數器,當兩個計數器都被清零時,可以認為該提供者是“乾淨”的。Dubbo-go 的策略是拒絕新請求,等待已放行的舊請求。最後,銷燬協議並關閉監聽,該容器就能夠被安全的摘除。


在啟動優雅上下線後,叢集內無錯誤請求,成功率保持在100%。


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


### 3.2 新一代柔性 服務


在去年釋出 Dubbo-go 3.0 版本的時候,柔性 服務首 次作為一個重要特性被提出。時隔一年,我們帶來了全新升級的新一代柔性 服務,在新版本中我們將爬山演算法替換為峰值干預演算法,在經過多次測試後新演算法行為可控性更高、效能更優異,這部分工作由來自北京郵電大學的張業鵬同學(GitHub: @CoolIceV)貢獻。


柔性 服務是一種更智慧的負載均衡演算法。傳統負載均衡演算法大多是基於消費者視角,它們共同的侷限性是無法根據服務提供者的當前狀態動態調整分流策略,如 RR、hash 等演算法。這些演算法總是以儘可能公平的機率分配流量,但在實踐中公平不等於負載均衡。


爬山演算法是一種容量預估的演算法,服務提供者需要將一些關鍵資訊回傳給消費者,比如時延、請求排隊數量、預估容量等,消費者使用 P2C 演算法選擇一個負載最低的作為本次請求的提供者。這些資料實效性要求非常高,如果這些資料是被動傳遞的,那麼很難保證實效性,如果這些資料是被主動探測的,那麼在一個大型叢集下感知成本非常高。基於上述問題,我們選擇了更可控的峰值干預演算法。


消費者部分中,我們使用了改良版的 P2C 演算法,採集的指標包括請求數(requests)、成功數(accepts)、請求時延(rtt)。與原實現方案不同的是,該版本採用了更合理的滑動視窗(SlidingWindowCounter)和指數移動平均(EMA)兩種帶有時序性的模組進行採集。


SlidingWindowCounter 會儲存時長為統計週期 T 的資料,整個週期內的資料被分割為若干個 Bucket,每個Bucket 儲存計數時長內的資料,當前所處的 Bucket 會隨著時間前進而向後移動。


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


EMA 利用指數移動平均演算法進行平滑、減小抖動,適用於統計時延型的指標,計算公式:


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


以下為一個客戶端請求 3 個服務端的測試結果,3 個服務端配置不同,分別為 1 核 1GB、2 核 2GB、3 核 3GB。蘭青色虛線代表開始使用上述負載均衡演算法,可以看到開啟前每個服務端接收到的請求數幾乎相同,開啟之後流量會根據提供者的規格進行智慧分流。


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


提供者基於一個 AutoConcurrencyLimiter 元件限流,在請求到達時會判斷已接受的請求是否超過最大處理量,如果超過了就會直接返回失敗,限流導致的失敗會影響負載均衡時的成功率,進而影響該例項被請求的可能性。與常規限流元件不同的是,該元件會根據取樣情況自動調整服務的最大處理量,不需要手動配置,而且增加了 CPU 負載作為啟動開關,可以減少被錯誤限流的數量。


該元件主要關注 QPS、無負載時延(NoLoadLatency)和最大併發量(maxConcurrency),同時有一個使用者指定的超引數 exploreRatio,表示探索最大併發量的程度。更新規則是


-   使用總請求數(包含未被取樣的資料)計算 QPS,新 QPS 更大時直接替換,更小則使用指數移動平均進行平滑處理。

-   使用取樣資料計算平均處理時延來估算 NoLoadLatency,平均時延變小才會更新,並使用指數移動平均進行平滑處理。

-   增加探索因子啟發式計算 maxConcurrency, 在取樣時延或 QPS 在探索允許的範圍之內時會逐步增大 exploreRatio,否則用指數移動平均的方式進行平滑處理


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


最後可以提供給使用者一個可以透過 cgroup v1 進行 CPU 限制,噹噹前提供者 CPU 負載過高的時候,會無條件拒絕一切新請求。CPU 限制是一種最壞情況下的兜底策略。


以下為 1 個客戶端請求一個服務端的測試結果,該測試隨著時間推移,QPS 會逐步增大,如藍線所示。可以看到當CPU 負載(橙線)過高時,有請求被限流(黃線),隨後即使 QPS 再增大,CPU 負載、請求成功數均已相對穩定。


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


### 3.3 Dubbo Mesh


今年 Dubbo Go 社群釋出了 Dubbo Mesh [1] 架構的完整實現,能夠以 Proxyless Mesh 的形式加入 Istio 服務網格,開啟了 Go 語言體系下的微服務新形態。


Istio 在架構層面分為控制平面(control plane)和資料平面(data plane),其中控制平面是一個名為 istiod 的程式,網路代理是 envoy 。Istiod 簡體 Kubernetes 資源(resources)獲取服務資訊,比如 Service、Endpoint 等,將這些資訊透過 xDS 協議傳送給位於資料平面的 envoy。Envoy 作為一個獨立代理程式以邊車(sidecar)形式執行,該程式與業務程式共同加入同一個網路,劫持業務流量並轉發到正確的位置。


服務網格能夠遮蔽複雜的服務治理細節,讓開發者能夠專注於業務實現。Istio 透過邊車的形式實現了業務邏輯的無侵入性,降低了系統之間的耦合性,帶來開發便利的同時也引入了轉發時延、額外資源消耗的問題。但是 Istio 作為雲原生時代的標杆產品,其架構模式和思路就有非常大的借鑑意義,針對上述提到的 Proxy Mesh 的弊端,我們提出了一套基於 Dubbo-go 的 Proxyless Mesh 微服務治理模式。


Proxyless Mesh 是無代理服務網格,由 Google 提出後,多個開源產品在這個方向進行了探索和實踐。其核心思路是用 SDK 代替獨立代理程式,SDK 作為資料平面接收來自控制平面的控制資訊,負責服務之間的通訊和治理工作。


Dubbo-go 為了融入 Istio 體系,將擴充套件出來的註冊發現流程進行了特殊改造。除了複用 Istio 提供的 EDS、CDS 主機發現的能力之外,增加了介面名到主機名的對映,作為源資料註冊在了控制平面上。客戶端在發起呼叫前持有介面名,透過查詢 istiod 上的後設資料資訊,拿到介面名到主機名到對映,轉換為主機名;再透過 EDS、CDS 和路由,完成主機名到下游端點例項的轉換。完成服務發現流程。


### 3.4 互聯互通的新典範:Polaris 和 Dubbo-go 全面對接


Dubbo-go 從釋出伊始,一直非常重視與各個開源產品之間的互聯互通,今年我們完成了與 Polaris 全面對接,這部分工作由社群鄧正威同學(GitHub: @jasondeng1997)和春少同學(GitHub: @chuntaojun)貢獻。


Polaris 是一款開源的服務治理平臺,致力於解決分散式和微服務架構中的服務管理、流量管理、配置管理、故障容錯和可觀測性問題,針對不同的技術棧和環境提供服務治理的標準方案和最 佳實踐。在經典 Dubbo-go 使用場景下,使用者需要自行部署註冊中心、可觀測服務、流量管理等元件,而 Polaris 內建了服務管理、流量管理、故障容錯、配置管理和可觀測性五大功能,能夠幫助使用者快速降低微服務開發門檻。


Polaris 有統一的控制平面,需要為 Dubbo-go 框架適配相應的資料平面 SDK,使用者只需要在 Dubbo-go 中開啟 Polaris,框架將自動透過 extension 機制進行注入,開發者無需其他額外的開發工作。從使用者資料流的維度,當使用者在 dubbogo 中啟用 Polaris 的服務治理能力後,業務流量實際處理流程如下:


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


當前 Polaris 已實現了 Dubbo-go 原生的服務註冊擴充套件點,因此原本服務註冊邏輯不需要進行任何調整,只需要在 dubbogo.yaml 配置檔案中新增 polaris 協議的註冊中心配置即可,如下所示。


```

dubbo:

  registries:

    demo:

      protocol: polaris

      address: {polaris-ip}:8091

```


其中 polaris-ip 表示北極星服務端 IP 地址,此時 Dubbo-go 框架就接入了 Polaris 服務治理框架。Polaris 還提供了流量管理、故障容錯等諸多內容,礙於篇幅限制這裡就不一一展開了,如果有興趣請參閱 《互聯互通的新典範:Polaris 和 Dubbo-go 全面對接》[2]。


### 3.5 TLS 安全通訊支援


在今年我們為 Dubbo 協議、Triple 協議和 gRPC 協議實現了 TLS 安全通訊功能,微服務之間能夠以可信的方式呼叫,該部分由社群張立斌同學(GitHub: @ZLBer)貢獻。


TLS 的前身是 SSL,被用於通訊加密,能夠保證傳輸內容不被其他主機檢視和篡改,已經被廣泛的應用於 HTTPS 等技術中。在開啟 TLS 之前,需要生成所需要的證照和秘鑰,我們假設其儲存在 x509 目錄中。啟用 TLS 不需要對業務邏輯進行修改,只需要設定相應的 Dubbo-go 配置檔案 dubbogo.yaml 即可。


消費者配置檔案:


```

dubbo:

  consumer:

    references:

      UserProvider:

        url: tri://localhost:20000

        protocol: tri

        serialization: json

        interface: com.apache.dubbogo.samples.rpc.extension.UserProvider

  tls_config:

      ca-cert-file: x509/server_ca_cert.pem

      tls-cert-file: x509/client2_cert.pem

      tls-key-file: x509/client2_key.pem

      tls-server-name: dubbogo.test.example.com

```


提供者配置檔案:


```

dubbo:

  protocols:

    triple:

      name: tri

      port: 20000

  provider:

    services:

      UserProvider:

        serialization: json

        interface: com.apache.dubbogo.samples.rpc.extension.UserProvider

  tls_config:

    ca-cert-file: x509/client_ca_cert.pem

    tls-cert-file: x509/server2_cert.pem

    tls-key-file: x509/server2_key.pem

    tls-server-name: dubbogo.test.example.com

```


在正確開啟 TLS 之後,提供者會輸出一條 "Server initialized the TLSConfig configuration" 日誌,消費者會輸出一條 "Client initialized the TLSConfig configuration" 日誌。更詳細的使用例項請參考 tls 示例 [3]。


## 04 展望 2023


2022 年是極不容易的一年,感謝大家的信任,也非常感謝社群中每位同學的貢獻。展望 2023 我們將會持續打磨框架,在優先保障穩定性的前提下持續提升易用性,打造一 流的 Go 語言微服務框架。


### 4.1 Dubbo 開源整體規劃


![image.png](~tplv-k3u1fbpfcp-zoom-1.image "image.png")


-   官網與文件體驗全面提升

-   Go、Node.js、Rust 等多語言體系建設

-   全面提升整體可觀測性

-   Dubbo Admin 一站式服務運維管控平臺

-   Dubbo Mesh 走向成熟

-   提升 HTTP 開發體驗,補全 Web 互通

-   打造 gRPC over Dubbo 最 佳實踐

-   完善的認證鑑權體系


### 4.2 面向 Go 開發者全面使用體驗提升


Dubbo-go 基礎功能建設已經較為完善,同時在最近幾年中我們持續在 dubbo-go-samples 目錄完善示例程式碼 [4],能夠幫助使用者更加快速的上手專案。與此同時,Dubbo-go 文件內容還較為匱乏,程式碼示例只能讓框架跑起來,但是這裡面的使用和實現細節還需要在文件中進一步被詳細闡述,讓使用者知其然,更知其所以然。除了文件建設工作外,社群對開發者工具的建設工作高度重視,在 2023 年,我們計劃在 dubboctl 工具中整合更多命令,為使用者提供快速建立微服務、支援了 Hessian2 生成器、新建 Dubbo-go 專案等諸多特性。在 2023 年我們將會進一步提升文件和工具的建設工作,除了強大的功能之外,成為真正面向 Go 開發者的輕量、易用的框架。


**參考連結:**


1、[Dubbo-go-Mesh 開啟新一代 Go 微服務形態 ](http://mp.weixin.qq.com/s?spm=a2c6h.13046898.0.0.273c6ffap5EdCl&__biz=MzIzOTU0NTQ0MA==&mid=2247508364&idx=1&sn=6f3fc02aadc272ae29b9e55241f029e2&chksm=e92a9c83de5d15954d7dd2fa1c81971fc9d154677db28eabf92d9eb5c2ab376bf02ea4e8d2c8&scene=21#wechat_redirect)


2、<


3、<


4、<


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69953029/viewspace-2944864/,如需轉載,請註明出處,否則將追究法律責任。

相關文章