dubbo-go 的開發、設計與功能介紹

dubbo-go 的前世此生

1

dubbo-go 是目前 Dubbo 多語言生態最火熱的項目。dubbo-go 最先的版本應該要追溯到 2016 年,由社區於雨同窗編寫 dubbo-go 的第一版。當時不少東西沒有現成的輪子,如 Go 語言沒有像 netty 同樣的基於事件的網絡處理引擎、 hessian2 協議沒有 Go 語言版本實現,加上當時 Dubbo 也沒有開始從新維護。因此從協議庫到網絡引擎,再到上層 dubbo-go ,其實都是從零開始寫的。java

在 2018 年,攜程開始作 Go 語言的一些中間件以搭建內部的 Go 語言生態,須要有一個 Go 的服務框架能夠與攜程的現有 dubbo soa 生態互通。因此由我負責重構了 dubbo-go 並開源出這個版本。當時調研了不少開源的 Go 語言服務框架,當時可以支持 hessian2 協議的並跟 Dubbo 能夠打通的僅找到了當時於雨寫的 dubbo-go 早期版本。因爲攜程對社區版本的 Dubbo 作了挺多的擴展,源於對擴展性的需求咱們 Go 語言版本須要一個更易於擴展的版本,加上當時這個版本自己的功能也比較簡單,因此咱們找到了做者合做重構了一個更好的版本。通過了大半年時間,在上圖第三階段 19 年 6 月的時候,基本上已經把 dubbo-go 重構了一遍,整體的思路是參考的 Dubbo 總體的代碼架構,用Go語言徹底重寫了一個完整的具有服務端跟消費端的 Golang rpc/ 微服務框架。linux

後來咱們將重構後的版本 dubbo-go 1.0 貢獻給 Apache 基金會,到如今已通過去了兩個多月的時間,近期社區發佈了1.1版本。目前爲止,已經有包括攜程在內的公司已經在生產環境開始了試用和推廣。git

Start dubbo-go

如今的 dubbo-go 已經可以跟 Java 版本作比較好的融合互通,同時 dubbo-go 自身也是一個完成的 Go 語言 rpc/ 微服務框架,它也能夠脫離 java dubbo 來獨立使用。
這邊簡單介紹一下用法,寫一個 hello world 的例子。
2github

上圖是一個簡單的 java service ,註冊爲一個 Dubbo 服務,是一個簡單的獲取用戶信息的例子。golang

3

上圖是 dubbo-go 的客戶端,來訂閱和調用這個 Java 的 Dubbo 服務。Go 語言客戶端須要顯式調用 SetConsumerService 來註冊須要訂閱的服務,而後經過調用 dubbo-go-hessian2 庫的 registerPOJO 方法來註冊 user 對象,作 Java 和 Go 語言之間的自定義 pojo 類型轉換。具體的服務調用方法就是聲明一個的 GetUser 閉包,即可直接調用。web

4

上圖,一樣的能夠基於 dubbo-go 發佈一個 GetUser 的服務端,使用方式相似,發佈完後能夠被 dubbo java 的客戶端調用。
5apache

如上圖所示,如今已經作到了這樣一個程度,一樣一份 dubbo-go 客戶端代碼,能夠去調用 dubbo-go 的服務端,也能夠去調用 Dubbo Java 的服務端;一樣一份 dubbo-go 的服務端代碼,能夠被 dubbo-go 客戶端和 Java 客戶端調用,因此基本上使用 Dubbo 做爲 PPC 框架的 Go 語言應用跟 Java 應用是沒有什麼阻礙的,是徹底的跨語言 RPC 調用。更重要的是 dubbo-go 繼承了 Dubbo 的許多優勢,如易於擴展、服務治理功能強大,你們在用 Go 語言開發應用的過程當中,若是也遇到相似須要與 Dubbo Java 打通的需求,或者須要找一個服務治理功能完備的 Go 微服務框架,能夠看下咱們 dubbo-go 項目。api

dubbo-go 的組成項目

下面介紹一下 dubbo-go 的組成項目,爲了方即可以被其餘項目直接複用, dubbo-go 拆分紅了多個項目,並所有以 Apache 協議開源。服務器

apache/dubbo-go
dubbo-go 主項目, Dubbo 服務端、客戶端完整 Go 語言實現。websocket

apache/dubbo-go-hession2
目前應用最普遍,與 Java 版本兼容程度最高的 hessian2 協議 Go 語言實現,已經被多個 GolangRPC & Service Mesh 項目使用。

dubbo-go/getty
dubbo-go 異步網絡 I/O 庫,將網絡處理層解耦。

dubbo-go/gost
基本類庫,定義了 timeWheel、hashSet、taskPool 等。

dubbo-go/dubbo-go-benchmark
用於對 dubbo-go 進行簡單的壓力測試,性能測試。

apache/dubbo-go-hessian2

6

先簡單介紹一下 dubbo-go-hessian2 項目。該項目就是 hessian2 協議的 Go 語言實現,最基本的能夠將 Java 的基本數據類型和複雜數據類型(如一些包裝類和list接口實現類)與 golang 這邊對應。
詳情能夠參考這裏

另外 Dubbo Java 服務端能夠不捕獲異常,將異常類經過 hession2 協議序列化經過網絡傳輸給消費端,消費端進行反序列化對該異常對象並進行捕獲。咱們通過一段時間的整理,目前已經支持在 Go 消費端定義對應 Java 的超過 40 種 exception 類,來實現對 Java 異常的捕獲,即便用 dubbo-go 也能夠作到直接捕獲 Java 服務端拋出的異常。

另外對於 Java 端 BigDecimal 高精度計算類的支持。涉及到一些金融相關的計算會有相似的需求,因此也對這個類進行了支持。

其餘的,還有映射 java 端的方法別名,主要的緣由是 Go 這邊語言的規約,須要被序列化的方法名必須是首字母大寫。而 Java 這邊沒有這種規範,因此咱們加了一個 hessian 標籤的支持,能夠容許用戶手動映射 Java 端的方法名稱。

基本上如今的 dubbo-go 已經知足絕大多數與 Java 的類型互通需求,咱們近期也在實現對 Java 泛型的支持。

dubbo-go/getty

7

Go 語言天生就是一個異步網絡 I/O 模型,在 linux 上 Go 語言寫的網絡服務器也是採用的 epoll 做爲最底層的數據收發驅動,這跟 java 在 linux 的 nio 實現是同樣的。因此 Go 語言的網絡處理天生就是異步的。咱們須要封裝的實際上是基於 Go 的異步網絡讀寫以及以後的處理中間層。getty 將網絡數據處理分爲三層,入向方向分別通過對網絡 i/o 封裝的 streaming 層、根據不一樣協議對數據進行序列化反序列化的 codec 層,以及最後數據上升到須要上層消費的 handler 層。出向方向基本與入向通過的相反。每一個連接的 IO 協程是成對出現的,好比讀協程負責讀取、 codec 邏輯而後數據到 listener 層,而後最後的事件由業務協程池來處理。

該項目目前是與 dubbo-go 解耦出來的,因此你們若是有相似需求能夠直接拿來用,目前已經有對於 tcp/udp/websocket 的支持。

Apache / dubbo-go

8

dubbo-go 主項目,咱們重構的這一版主要是基於 Dubbo 的分層代碼設計,上圖是 dubbo-go 的代碼分層。基本上與 Java 版本 Dubbo 現有的分層一致,因此 dubbo-go 也繼承了 Dubbo 的一些優良特性,好比整潔的代碼架構、易於擴展、完善的服務治理功能。

咱們攜程這邊,使用的是本身的註冊中心,能夠在 dubbo-go 擴展機制的基礎上靈活擴展而無需去改動 dubbo-go 的源代碼。

dubbo-go 的功能介紹

dubbo-go 已實現功能

目前 dubbo-go 已經實現了 Dubbo 的經常使用功能(如負責均衡、集羣策略、服務多版本多實現、服務多註冊中心多協議發佈、泛化調用、服務降級熔斷等),其中服務註冊發現已經支持 zookeeper/etcd/consul/nacos 主流注冊中心。這裏不展開詳細介紹,目前 dubbo-go 支持的功能能夠查看項目 readme 中的 feature list ,詳情參考:https://github.com/apache/dubbo-go#feature-list

目前社區正在開發中的功能,主要是早期用戶使用過程當中提出的一些需求,也是生產落地一些必需的需求,如監控、調用鏈跟蹤以及服務路由、動態配置中心等更高級的服務治理需求。

dubbo-go 功能介紹之泛化調用

9

這裏詳細作幾個重點功能的介紹。首先是泛化調用,如上圖,這個也是社區同窗提的需求。該同窗公司內部有不少 Dubbo 服務,他們用 Go 作了一個 api gateway 網關,想要把 Dubbo 服務暴露成外網 http 接口。由於內部的 Dubbo 服務比較多,不可能每個 Dubbo 服務都去作一個消費端接口去作適配,這樣的話一旦服務端改動,客戶端也要改。因此他這邊的思路是作基於 dubbo-go 作泛化調用, api-gateway 解析出外網請求的地址,解析出想要調用的 Dubbo 服務的目標。基於dubbo-go consumer 泛化調用指定 service、method ,以及調用參數。

具體的原理是, dubbo-go 這邊做爲消費端,實際會經過本地 genericService.invoke 方法作代理,參數裏面包含了 service name,method name ,還包含被調用目標 service 須要的參數類型、值等數據,這些數據後面會經過 dubbo-go-hession2 作轉換,會將內容轉化成 map 類型,通過網絡發送到對應的 Java 服務端,而後 Java 那邊是接收的 map 類型的參數,會自動反序列化成本身的 pojo 類型。這樣就實現了 dubbo-go 做爲客戶端,泛化調用 Dubbo 服務端的目的。

dubbo-go 功能介紹之降級熔斷

10

降級熔斷這邊是基於的是你們比較熟悉的 hystrix 的 Go 語言版本,基於 hystrix ,用戶能夠定義熔斷規則和降級觸發的代碼段。降級熔斷支持是做爲一個獨立的 dubbo-go filter ,能夠靈活選擇是否啓用,若是不啓用就能夠在打包的時候不將依賴引入。Filter 層是 dubbo-go 中對於請求鏈路的一個責任鏈模式抽象,目前有許多功能都是基於動態擴展 filter 鏈來實現的,包括 trace、leastactive load balacne、log 等。降級熔斷設計成一個服務調用端獨立的filter能夠靈活知足調用端視角對於微服務架構中「防雪崩「的服務治理需求。

dubbo-go 功能介紹之動態配置

關於動態配置中心, Dubbo 的 2.6 到 2.7 版本作了一個比較大的變化,從以前的 url 配置形式過渡到了支持配置中心 yaml 格式配置的形式,治理粒度也從單服務級別的配置支持到了應用級別的配置,不過在2.7版本中仍是兼容 2.6 版本 url 形式進行服務配置的。dubbo-go 這邊考慮到跟 Dubbo2.6 和 2.7 的互通性,一樣支持 url 和配置文件方式的服務配置,同時兼容應用級別和服務級別的配置,跟 dubbo 保持一致,目前已經實現了zookeeper和apollo做爲配置中心的支持。

dubbo-go roadmap 2019-2020

11

最後是你們比較關注的,社區關於 dubbo-go 2019 年下半年的計劃,目前來看主要仍是現有功能的補齊和一些問題的修復,咱們的目標就是首先作到 Java 和 Go 在運行時的兼容互通和功能的一致,其次是查漏補缺 dubbo-go 做爲一個完整 Go 語言微服務框架在功能上的能夠改進之處。

另外值得關注的一點是,預計今年年末, dubbo-go 會發佈一個支持 kubernetes 做爲註冊中心的擴展,積極擁抱雲原生生態。關於雲原生的支持,社區前期作了積極的工做,包括討論關於 dubbo-go 與 Service Mesh 的關係以及在其中的定位,能夠確定的是, dubbo-go 將會配合 Dubbo 社區在 Service Mesh 方向的規劃並扮演重要角色,咱們初步預計會在明年給出與 Service Mesh開源社區項目集成的方案,請你們期待。

dubbo-go 社區目前屬於快速健康成長狀態,從捐贈給 Apache 後的不到3個月的時間裏,吸引了大批量的活躍開發者和感興趣的用戶,歡迎各位同道在使用或者學習中遇到問題可以來社區討論或者給予指正,也歡迎對 dubbo-go 有潛在需求或者對 dubbo-go 感興趣的同道能加入到社區中。

做者信息:何鑫銘,目前就任於攜程,基礎中臺研發部技術專家,dubbo-go 共同發起人、主要做者,Apache Dubbo committer,關注互聯網中臺以及中間件領域。

 

 

 

 

原文連接

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索