Java 微服務架構選型(Dubbo 和 Spring Cloud?)

2020-08-12 18:42:10

微服務(Microservices)是一種架構風格,一個大型複雜軟體應用由一個或多個微服務組成。系統中的各個微服務可被獨立部署,各個微服務之間是松耦合的。每個微服務僅關注於完成一件任務並很好地完成該任務。在所有情況下,每個任務代表着一個小的業務能力。

以往我們開發應用程式都是單體型,雖然開發和部署比較方便,但後期隨着業務的不斷增加,開發迭代和效能瓶頸等問題,將會困擾開發團隊,微服務就是解決此問題的有效手段,市面上有很多的微服務架構,比如最著名的兩個 Dubbo 和 Spring Cloud,我們該如何選擇呢?

關於 RPC/gRPC/HTTP/REST

因爲服務呼叫方式是 Dubbo 和 Spring Cloud 重要不同點,瞭解 RPC/gRPC/HTTP/REST 相關概念,有助於對比 Dubbo 和 Spring Cloud。

RPC 是遠端過程呼叫,其呼叫協定通常包含傳輸協定和編碼協定

HTTP 嚴格來說跟 RPC 不是一個層級的概念,HTTP 本身也可以作爲 RPC 的傳輸層協定

傳輸協定包含: 如著名的 gRPC 使用的 HTTP 2.0 協定,也有如 Dubbo 一類的自定義報文的 TCP 協定。編碼協定包含: 如基於文字編碼的 XML Json,也有二進制編碼的 ProtoBuf Binpack 等。

所謂的效率優勢是針對 HTTP 1.1 協定來講的,HTTP 2.0 協定已經優化編碼效率問題,像 gRPC 這種 RPC 庫使用的就是 HTTP 2.0 協定。

在跨語言呼叫的時候,REST 風格直接把 HTTP 作爲應用協定(直接和服務打交道),不同語言之間呼叫比較方便。

而 RPC 可以把 HTTP 作爲一種傳輸協定(比如 gRPC 使用 HTTP 2.0 協定傳輸),本身還會封裝一層 RPC 框架的應用層協定,不同語言之間呼叫需要依賴 RPC 協定(需要跨語言 RPC 庫實現,比如 Thrift)。

問題:爲什麼 Dubbo 比 Spring Cloud 效能要高一些?

回答:因爲 Dubbo 採用單一長連線和 NIO 非同步通訊(保持連線/輪詢處理),使用自定義報文的 TCP 協定,並且序列化使用定製 Hessian2 框架,適合於小數據量大併發的服務呼叫,以及服務消費者機器數遠大於服務提供者機器數的情況,但不適用於傳輸大數據的服務呼叫。而 Spring Cloud 直接使用 HTTP 協定(但也不是強系結,也可以使用 RPC 庫,或者採用 HTTP 2.0 + 長鏈接方式(Fegin 可以靈活設定))。

另外,Martin Fowler 的 MicroServices 一文,其定義的服務間通訊是 HTTP 協定的 REST API

Dubbo 是什麼?

https://github.com/apache/incubator-dubbo

Dubbo 是一個分佈式服務架構,致力於提供高效能和透明化的 RPC 遠端服務呼叫方案,以及 SOA 服務治理方案。簡單的說,Dubbo 就是個服務架構,說白了就是個遠端服務呼叫的分佈式框架

Dubbo 框架

模組註解:

  • Provider: 暴露服務的服務提供方
  • Consumer: 呼叫遠端服務的服務消費方
  • Registry: 服務註冊與發現的註冊中心
  • Monitor: 統計服務的呼叫次調和呼叫時間的監控中心
  • Container: 服務執行容器

流程詳解:

  • 0 服務容器負責啓動,載入,執行服務提供者(Standalone 容器)。
  • 1 服務提供者在啓動時,向註冊中心註冊自己提供的服務(Zookeeper/Redis)。
  • 2 服務消費者在啓動時,向註冊中心訂閱自己所需的服務。
  • 3 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推播變更數據給消費者。
  • 4 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
  • 5 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘發送一次統計數據到監控中心(根據數據可以動態調整權重)。

Dubbo 叢集容錯

面對服務消費方,當業務邏輯中需要呼叫一個服務時,真正呼叫的其實是 Dubbo 建立的一個 Proxy,該 Proxy 會把呼叫轉化成呼叫指定的 Invoker(Cluster 將 Directory 中的多個 Invoker 僞裝成一個 Invoker,對上層透明,僞裝過程包含了容錯邏輯,呼叫失敗後,重試另一個(通過 LoadBalance),Invoker 封裝了 Provider 地址及 Service 介面資訊)。而在這一系列的委託呼叫的過程裡就完成了服務治理的邏輯,最終完成呼叫。

Dubbo 特點

  • 遠端通訊: 提供對多種基於長連線的 NIO 框架抽象封裝(非阻塞 I/O 的通訊方式,Mina/Netty/Grizzly),包括多種執行緒模型,序列化(Hessian2/ProtoBuf),以及「請求-響應」模式的資訊交換方式。
  • 叢集容錯: 提供基於介面方法的透明遠端過程呼叫(RPC),包括多協定支援(自定義 RPC 協定),以及軟負載均衡(Random/RoundRobin),失敗容錯(Failover/Failback),地址路由,動態設定等叢集支援。
  • 自動發現: 基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。

Dubbo 發展歷程

  • 2008 年,阿裡巴巴開始內部使用 Dubbo。
  • 2009 年初,發佈 1.0 版本。
  • 2010 年初,發佈 2.0 版本。
  • 2011 年 10 月,阿裡巴巴宣佈開源,版本爲 2.0.7。
  • 2012 年 3 月,發佈 2.1.0 版本。
  • 2013 年 3 月,發佈 2.4.10 版本。
  • 2014 年 10 月,發佈 2.3.11 版本,之後版本停滯。
  • 2017 年 9 月,阿裡巴巴重新啓動維護,重點升級所依賴 JDK 及元件版本,發佈 2.5.4/5 版本。
  • 2017 年 10 月,發佈 2.5.6 版本。
  • 2017 年 11 月,發佈 2.5.7 版本,後期整合 Spring Boot。
  • 2014 年 10 月,噹噹網 Fork 了 Dubbo 版本,命名爲 Dubbox-2.8.0,並支援 HTTP REST 協定。

Dubbo 負責人說明(重新啓動維護是接受的採訪):

 

Spring Cloud 是什麼?

https://github.com/spring-cloud

Spring Cloud 基於 Spring Boot,爲微服務體系開發中的架構問題,提供了一整套的解決方案——服務註冊與發現,服務消費,服務保護與熔斷,閘道器,分佈式呼叫追蹤,分佈式設定管理等。

重點:

  • 基於 Spring Boot
  • 雲服務、分佈式框架集合(衆多)

核心功能:

  • 分佈式/版本化設定
  • 服務註冊和發現
  • 路由
  • 服務和服務之間的呼叫
  • 負載均衡
  • 斷路器
  • 分佈式訊息傳遞

Spring Cloud 完整技術

Spring Cloud 元件架構

 

流程:

  • 請求統一通過 API 閘道器(Zuul)來存取內部服務。
  • 閘道器接收到請求後,從註冊中心(Eureka)獲取可用服務。
  • 由 Ribbon 進行均衡負載後,分發到後端具體範例。
  • 微服務之間通過 Feign 進行通訊處理業務。
  • Hystrix 負責處理服務超時熔斷。
  • Turbine 監控服務間的呼叫和熔斷相關指標。

Spring Cloud工具框架

 

Dubbo 一些優點

 

Dubbo 一些問題

 

 

Spring Cloud 的一些優點

 

Spring Cloud 的一些問題

  • Spring Cloud Config 設定中心,利用 Git 集中管理程式的設定。
  • Spring Cloud Netflix 整合衆多Netflix的開源軟體。
  • Spring Cloud Netflix Eureka 服務中心(類似於管家的概念,需要什麼直接從這裏取,就可以了),一個基於 REST 的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。
  • Spring Cloud Netflix Hystrix 熔斷器,容錯管理工具,旨在通過熔斷機制 機製控制服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。
  • Spring Cloud Netflix Zuul 閘道器,是在雲平臺上提供動態路由,監控,彈性,安全等邊緣服務的框架。Web 網站後端所有請求的前門。
  • Spring Cloud Netflix Archaius 設定管理 API,包含一系列設定管理API,提供動態型別化屬性、執行緒安全設定操作、輪詢框架、回撥機制 機製等功能。
  • Spring Cloud Netflix Ribbon 負載均衡
  • Spring Cloud Netflix Fegin REST用戶端
  • Spring Cloud Bus 訊息匯流排,利用分佈式訊息將服務和服務範例連線在一起,用於在一個叢集中傳播狀態的變化。
  • Spring Cloud for Cloud Foundry 利用 Pivotal Cloudfoundry 整合你的應用程式。
  • Spring Cloud Cloud Foundry Service Broker 爲建立管理雲託管服務的服務代理提供了一個起點。
  • Spring Cloud Cluster 叢集工具,基於 Zookeeper, Redis, Hazelcast, Consul 實現的領導選舉和平民狀態模式的抽象和實現。
  • Spring Cloud Consul 基於 Hashicorp Consul 實現的服務發現和設定管理。
  • Spring Cloud Security 安全控制,在 Zuul 代理中爲 OAuth2 REST 用戶端和認證頭轉發提供負載均衡。
  • Spring Cloud Sleuth 分佈式鏈路監控,SpringCloud 應用的分佈式追蹤系統,和 Zipkin,HTrace,ELK 相容。
  • Spring Cloud Data Flow 一個雲本地程式和操作模型,組成數據微服務在一個結構化的平臺上。
  • Spring Cloud Stream 訊息元件,基於 Redis,Rabbit,Kafka 實現的訊息微服務,簡單宣告模型用以在 Spring Cloud 應用中收發訊息。
  • Spring Cloud Stream App Starters 基於 Spring Boot 爲外部系統提供 Spring 的整合。
  • Spring Cloud Task 短生命週期的微服務,爲 Spring Booot 應用簡單宣告新增功能和非功能特性。
  • Spring Cloud Task App Starters。
  • Spring Cloud Zookeeper 服務發現和設定管理基於 Apache Zookeeper。
  • Spring Cloud for Amazon Web Services 快速和亞馬遜網路服務整合。
  • Spring Cloud Connectors 便於PaaS應用在各種平臺上連線到後端像數據庫和訊息經紀服務。
  • Spring Cloud Starters (專案已經終止並且在 Angel.SR2 後的版本和其他專案合併)
  • Spring Cloud CLI 命令列工具,外掛用 Groovy 快速的建立 Spring Cloud 元件應用。
  • Dubbo 支援 RPC 呼叫,服務之間的呼叫效能會很好。
  • 支援多種序列化協定,如 Hessian、HTTP、WebService。
  • Dobbo Admin後臺管理功能強大,提供了路由規則、動態設定、存取控制、權重調節、均衡負載等功能。
  • 在國內影響力比較大,中文社羣文件較爲全面
  • 阿裡最近重新啓動維護
  • Registry 嚴重依賴第三方元件(zookeeper 或者 redis),當這些元件出現問題時,服務呼叫很快就會中斷。
  • Dubbo 只支援 RPC 呼叫。使得服務提供方(抽象介面)與呼叫方在程式碼上產生了強依賴,服務提供者需要不斷將包含抽象介面的 jar 包打包出來供消費者使用。一旦打包出現問題,就會導致服務呼叫出錯,並且以後發佈部署會成很大問題(太強的依賴關係)。
  • 另外,以後要相容 .NET Core 服務,Dubbo RPC 本身不支援跨語言(可以用跨語言 RPC 框架解決,比如 Thrift、gRPC(重複封裝了),或者自己再包一層 REST 服務,提供跨平臺的服務呼叫實現,但相對麻煩很多)
  • Dubbo 只是實現了服務治理,其他微服務架構並未包含,如果需要使用,需要結合第三方框架實現(比如分佈式設定用淘寶的 Diamond、服務跟蹤用京東的 Hydra,但使用相對麻煩些),開發成本較高,且風險較大。
  • 社羣更新不及時(雖然最近在瘋狂更新),但也難免阿裡以後又不更新了,就尷尬了。
  • 主要是國內公司使用,但阿裡內部使用 HSF,相對於 Spring Cloud,企業應用會差一些。
  • 有強大的 Spring 社羣、Netflix 等公司支援,並且開源社羣貢獻非常活躍
  • 標準化的將微服務的成熟產品和框架結合一起,Spring Cloud 提供整套的微服務解決方案,開發成本較低,且風險較小
  • 基於 Spring Boot,具有簡單設定、快速開發、輕鬆部署、方便測試的特點。
  • 支援 REST 服務呼叫,相比於 RPC,更加輕量化和靈活(服務之間只依賴一紙契約,不存在程式碼級別的強依賴),有利於跨語言服務的實現,以及服務的發佈部署。另外,結合 Swagger,也使得服務的文件一體化
  • 提供了 Docker 及 Kubernetes 微服務編排支援。
  • 國內外企業應用非常多,經受了大公司的應用考驗(比如 Netfilx 公司),以及強大的開源社羣支援。
  • 支援 REST 服務呼叫,可能因爲介面定義過輕,導致定義文件與實際實現不一致導致服務整合時的問題(可以使用統一文件和版本管理解決,比如 Swagger)。
  • 另外,REST 服務呼叫效能會比 RPC 低一些(但也不是強系結)
  • Spring Cloud 整合了大量元件,相關文件比較複雜,需要針對性的進行閱讀。

服務呼叫方式的不同

Spring Cloud 拋棄了 Dubbo 的 RPC 通訊,採用的是基於 HTTP 的 REST 方式。嚴格來說,這兩種方式各有優劣。雖然從一定程度上來說,後者犧牲了服務呼叫的效能,但也避免了上面提到的原生 RPC 帶來的問題。而且 REST 相比 RPC 更爲靈活,服務提供方和呼叫方的依賴只依靠一紙契約,不存在程式碼級別的強依賴,這在強調快速演化的微服務環境下,顯得更加合適。

 

Dubbo 和 Spring Cloud 對比

Dubbo 專注 RPC 和服務治理,Spring Cloud 則是一個微服務架構生態。

ZooKeeper 和 Eureka 的區別

鑑於服務發現對服務化架構的重要性,Dubbo 實踐通常以 ZooKeeper 爲註冊中心(Dubbo 原生支援的 Redis 方案需要伺服器時間同步,且效能消耗過大)。針對分佈式領域著名的 CAP 理論(C——數據一致性,A——服務可用性,P——服務對網路分割區故障的容錯性),Zookeeper 保證的是 CP ,但對於服務發現而言,可用性比數據一致性更加重要,AP 勝過 CP,而 Eureka 設計則遵循 AP 原則
Spring Cloud 支援 Consul(CA)和 Zookeeper,但不推薦使用。

網易考拉選型參考

當前開源上可選用的微服務架構主要有 Dubbo、Spring Cloud 等,鑑於 Dubbo 完備的功能和文件且在國內被衆多大型網際網路公司選用,考拉自然也選擇了 Dubbo 作爲服務化的基礎框架。其實相比於 Dubbo,Spring Cloud 可以說是一個更完備的微服務解決方案,它從功能性上是 Dubbo 的一個超集,個人認爲從選型上對於一些中小型企業 Spring Cloud 可能是一個更好的選擇。提起 Spring Cloud,一些開發的第一印象是 HTTP + JSON 的 REST 通訊,效能上難堪重用,其實這也是一種誤讀。微服務選型要評估以下幾點:內部是否存在異構系統整合的問題;備選框架功能特性是否滿足需求;HTTP 協定的通訊對於應用的負載量會否真正成爲瓶頸點(Spring Cloud 也並不是和 HTTP + JSON 強制系結的,如有必要 Thrift、ProtoBuf 等高效的 RPC、序列化協定同樣可以作爲替代方案);社羣活躍度、團隊技術儲備等。作爲已經沒有團隊持續維護的開源專案,選擇 Dubbo 框架內部就必須要組建一個維護團隊,先不論你要準備要整合多少功能做多少改造,作爲一個支撐所有工程正常運轉的基礎元件,問題的及時響應與解答、重大缺陷的及時修復能力就已足夠重要。

Dubbo 和 Spring Cloud 比喻

使用 Dubbo 構建的微服務架構就像組裝電腦,各環節我們的選擇自由度很高,但是最終結果很有可能因爲一條記憶體品質不行就點不亮了,總是讓人不怎麼放心,但是如果你是一名高手,那這些都不是問題;而 Spring Cloud 就像品牌機,在 Spring Source 的整合下,做了大量的相容性測試,保證了機器擁有更高的穩定性,但是如果要在使用非原裝元件外的東西,就需要對其基礎有足夠的瞭解。

.NET Core的相容方案

若使用 Spring Cloud,.NET Core 相容 Spring Cloud 比較好實現,因爲基於 REST 服務呼叫,可以自行實現其服務(Eureka 提供 REST API 進行服務註冊),也已有成熟的開源框架如 Steeltoe

關於 Service Mesh

2017 年底,非侵入式的 Service Mesh 技術從萌芽到走向了成熟。

Service Mesh 又譯作「服務網格」,作爲服務間通訊的基礎設施層

如果用一句話來解釋什麼是 Service Mesh,可以將它比作是應用程式或者說微服務間的 TCP/IP,負責服務之間的網路呼叫、限流、熔斷和監控。對於編寫應用程式來說一般無須關心 TCP/IP 這一層(比如通過 HTTP 協定的 RESTful 應用),同樣使用 Service Mesh 也就無須關係服務之間的那些原來是通過應用程式或者其他框架實現的事情,比如 Spring Cloud、OSS,現在只要交給 Service Mesh 就可以了。

  • Linkerdhttps://github.com/linkerd/linkerd):第一代 Service Mesh,2016 年 1 月 15 日首發布,業界第一個 Service Mesh 專案,由 Buoyant 創業小公司開發(前 Twitter 工程師),2017 年 7 月 11 日,宣佈和 Istio 整合,成爲 Istio 的數據面板。
  • Envoyhttps://github.com/envoyproxy/envoy):第一代 Service Mesh,2016 年 9 月 13 日首發布,由 Matt Klein 個人開發(Lyft 工程師),之後默默發展,版本較穩定。
  • Istiohttps://github.com/istio/istio):第二代 Service Mesh,2017 年 5 月 24 日首發布,由 Google、IBM 和 Lyft 聯合開發,只支援 Kubernetes 平臺,2017 年 11 月 30 日發佈 0.3 版本,開始支援非 Kubernetes 平臺,之後穩定的開發和發佈。
  • Conduithttps://github.com/runconduit/conduit):第二代 Service Mesh,2017 年 12 月 5 日首發布,由 Buoyant 公司開發(借鑑 Istio 整體架構,部分進行了優化),對抗 Istio 壓力山大,也期待 Buoyant 公司的毅力。
  • nginMeshhttps://github.com/nginmesh/nginmesh):2017 年 9 月首發布,由 Nginx 開發,定位是作爲 Istio 的服務代理,也就是替代 Envoy,思路跟 Linkerd 之前和 Istio 整合很相似,極度低調,GitHub 上的 star 也只有不到 100。
  • Konghttps://github.com/Kong/kong):比 nginMesh 更加低調,默默發展中。

總結

關於 Dubbo 和 Spring Cloud 的相關概念和對比,上面已經敘述的很清楚了,我個人比較傾向於 Spring Cloud,原因就是真正的微服務架構、提供整套的元件支援、使用簡單方便、強大的社羣支援等等,另外,因爲考慮到 .NET/.NET Core 的相容處理,RPC 並不能很好的實現跨語言(需要藉助跨語言庫,比如 gRPC、Thrift,但因爲 Dubbo 本身就是「gRPC」,在 Dubbo 之上再包一層 gRPC,有點重複封裝了),而 HTTP REST 本身就是支援跨語言實現,所以,Spring Cloud 這一點還是非常好的(Dubbox 也支援,但效能相比要差一些)。

但凡事無絕對,每件事物有好的地方也有不好的地方,總的來說,Dubbo 和 Spring Cloud 的主要不同體現在兩個方面:服務呼叫方式不同專注點不同(生態不同)

最後,關於 Service Mesh,因爲是很新的概念(去年年底才火起來),相關的框架並未真正用於生產環境,所以這邊就不考慮了,但以後可能會發展的非常好。

參考資料: