1. 程式人生 > >Java 微服務架構選型

Java 微服務架構選型

聯合 開源 5.7 多協議 阻塞 接受 trace 情況 項目

轉載自 https://www.cnblogs.com/xishuai/p/dubbo-and-spring-cloud.html

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

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

公司近期打算向 Java 微服務技術轉型(一步一步實現,會考慮兼容 .NET/.NET Core),以下是我整理的相關內容,如果你有更好的建議和意見,歡迎探討~~~

關於 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 負責人說明(重啟維護是接受的采訪):

阿裏內部使用 HSF,原因業務屬性規模有關。
這裏就不得不提到目前的一些文章在談到微服務的時候總是拿 Spring Cloud 和 Dubbo 來對比,需要強調的是 Dubbo 未來的定位並不是要成為一個微服務的全面解決方案,而是專註在 RPC 領域,成為微服務生態體系中的一個重要組件。至於大家關註的微服務化衍生出的服務治理需求,我們會在 Dubbo 積極適配開源解決方案,甚至啟動獨立的開源項目予以支持。
受眾主要來自國內各友商以及個人開發者,希望將來能夠將用戶拓展到全球,代表國人在 RPC 領域與 gRPC(基於 HTTP 2.0)、Finagle 等競爭。

Spring Cloud 是什麽?

https://github.com/spring-cloud

Spring Cloud 基於 Spring Boot,為微服務體系開發中的架構問題,提供了一整套的解決方案——服務註冊與發現,服務消費,服務保護與熔斷,網關,分布式調用追蹤,分布式配置管理等。

Spring Boot 是 Spring 的一套快速配置腳手架,使用默認大於配置的理念,用於快速開發單個微服務。

重點:

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

核心功能:

  • 分布式/版本化配置
  • 服務註冊和發現
  • 路由
  • 服務和服務之間的調用
  • 負載均衡
  • 斷路器
  • 分布式消息傳遞

Spring Cloud 完整技術

技術分享圖片

Spring Cloud 組件架構

技術分享圖片

流程:

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

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 一些優點

  • Dubbo 支持 RPC 調用,服務之間的調用性能會很好。
  • 支持多種序列化協議,如 Hessian、HTTP、WebService。
  • Dobbo Admin後臺管理功能強大,提供了路由規則、動態配置、訪問控制、權重調節、均衡負載等功能。
  • 在國內影響力比較大,中文社區文檔較為全面
  • 阿裏最近重啟維護

Dubbo 一些問題

  • Registry 嚴重依賴第三方組件(zookeeper 或者 redis),當這些組件出現問題時,服務調用很快就會中斷。
  • Dubbo 只支持 RPC 調用。使得服務提供方(抽象接口)與調用方在代碼上產生了強依賴,服務提供者需要不斷將包含抽象接口的 jar 包打包出來供消費者使用。一旦打包出現問題,就會導致服務調用出錯,並且以後發布部署會成很大問題(太強的依賴關系)。
  • 另外,以後要兼容 .NET Core 服務,Dubbo RPC 本身不支持跨語言(可以用跨語言 RPC 框架解決,比如 Thrift、gRPC(重復封裝了),或者自己再包一層 REST 服務,提供跨平臺的服務調用實現,但相對麻煩很多)
  • Dubbo 只是實現了服務治理,其他微服務框架並未包含,如果需要使用,需要結合第三方框架實現(比如分布式配置用淘寶的 Diamond、服務跟蹤用京東的 Hydra,但使用相對麻煩些),開發成本較高,且風險較大。
  • 社區更新不及時(雖然最近在瘋狂更新),但也難免阿裏以後又不更新了,就尷尬了。
  • 主要是國內公司使用,但阿裏內部使用 HSF,相對於 Spring Cloud,企業應用會差一些。

Spring Cloud 的一些優點

  • 有強大的 Spring 社區、Netflix 等公司支持,並且開源社區貢獻非常活躍
  • 標準化的將微服務的成熟產品和框架結合一起,Spring Cloud 提供整套的微服務解決方案,開發成本較低,且風險較小
  • 基於 Spring Boot,具有簡單配置、快速開發、輕松部署、方便測試的特點。
  • 支持 REST 服務調用,相比於 RPC,更加輕量化和靈活(服務之間只依賴一紙契約,不存在代碼級別的強依賴),有利於跨語言服務的實現,以及服務的發布部署。另外,結合 Swagger,也使得服務的文檔一體化
  • 提供了 Docker 及 Kubernetes 微服務編排支持。
  • 國內外企業應用非常多,經受了大公司的應用考驗(比如 Netfilx 公司),以及強大的開源社區支持。

Spring Cloud 的一些問題

  • 支持 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。

官方介紹:

Steeltoe is an open source project that enables .NET developers to implement industry standard best practices when building resilient microservices for the cloud. The Steeltoe client libraries enable .NET Core and .NET Framework apps to easily leverage Netflix Eureka, Hystrix, Spring Cloud Config Server, and Cloud Foundry services.

關於 Service Mesh

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

Service Mesh 又譯作“服務網格”,作為服務間通信的基礎設施層

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

  • Linkerd(https://github.com/linkerd/linkerd):第一代 Service Mesh,2016 年 1 月 15 日首發布,業界第一個 Service Mesh 項目,由 Buoyant 創業小公司開發(前 Twitter 工程師),2017 年 7 月 11 日,宣布和 Istio 集成,成為 Istio 的數據面板。
  • Envoy(https://github.com/envoyproxy/envoy):第一代 Service Mesh,2016 年 9 月 13 日首發布,由 Matt Klein 個人開發(Lyft 工程師),之後默默發展,版本較穩定。
  • Istio(https://github.com/istio/istio):第二代 Service Mesh,2017 年 5 月 24 日首發布,由 Google、IBM 和 Lyft 聯合開發,只支持 Kubernetes 平臺,2017 年 11 月 30 日發布 0.3 版本,開始支持非 Kubernetes 平臺,之後穩定的開發和發布。
  • Conduit(https://github.com/runconduit/conduit):第二代 Service Mesh,2017 年 12 月 5 日首發布,由 Buoyant 公司開發(借鑒 Istio 整體架構,部分進行了優化),對抗 Istio 壓力山大,也期待 Buoyant 公司的毅力。
  • nginMesh(https://github.com/nginmesh/nginmesh):2017 年 9 月首發布,由 Nginx 開發,定位是作為 Istio 的服務代理,也就是替代 Envoy,思路跟 Linkerd 之前和 Istio 集成很相似,極度低調,GitHub 上的 star 也只有不到 100。
  • Kong(https://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,因為是很新的概念(去年年底才火起來),相關的框架並未真正用於生產環境,所以這邊就不考慮了,但以後可能會發展的非常好。

Java 微服務架構選型