雖然微服務架構沒有公認的技術標准和規范或者草案,但業界已經有一些很有影響力的開源微服務架構框架提供了微服務的關鍵思路,例如 Dubbo 和 Spring Cloud。
微服務主要的優勢
1 降低復雜度
將原來耦合在一起的復雜業務拆分為單個服務,規避了原本復雜度無止境的積累。
每一個微服務專注於單一功能,並通過定義良好的接口清晰表述服務邊界;
每個服務開發者只專注服務本身,通過使用緩存、DAL(data access layer) 等各種技術手段來提升系統的性能,
而對於消費方來說完全透明。
2 可獨立部署
由於微服務具備獨立的運行進程,所以每個微服務可以獨立部署。
當業務迭代時只需要發布相關服務的迭代即可,
降低了測試的工作量同時也降低了服務發布的風險。
3 容錯
在微服務架構下,當某一組件發生故障時,故障會被隔離在單個服務中。
比如通過限流、熔斷等方式降低錯誤導致的危害,保障核心業務正常運行。
4 擴展
單塊架構應用也可以實現橫向擴展,就是將整個應用完整的復制到不同的節點。
當應用的不同組件在擴展需求上存在差異時,微服務架構便體現出其靈活性,
因為每個服務可以根據實際需求獨立進行擴展。
下面主要圍繞微服務的 技術選型、通訊協議、服務依賴模式、開始模式、運行模式等幾方面來綜合比較 Dubbo 和 Spring Cloud 這 2 種開發框架。
一 核心部件
微服務的核心要素在於服務的發現、注冊、路由、熔斷、降級、分布式配置,基於上述幾種必要條件對 Dubbo 和 Spring Cloud 做出對比。
總體架構
Dubbo 核心部件(如下圖):
-
Provider:暴露服務的提供方,可以通過 jar 或者容器的方式啟動服務。
-
Consumer:調用遠程服務的服務消費方。
-
Registry:服務注冊中心和發現中心。
-
Monitor:統計服務和調用次數,調用時間監控中心。(Dubbo 的控制台頁面中可以顯示,目前只有一個簡單版本。)
-
Container:服務運行的容器。

Dubbo 總體架構
Spring Cloud總體架構(如下圖):
-
Service Provider: 暴露服務的提供方。
-
Service Consumer:調用遠程服務的服務消費方。
-
EureKa Server: 服務注冊中心和服務發現中心。

Spring Cloud 總體架構
點評:從整體架構上來看,二者模式接近,都需要服務提供方,注冊中心,服務消費方。
二 微服務架構核心要素

Dubbo 只是實現了服務治理,而 Spring Cloud 子項目分別覆蓋了微服務架構下的眾多部件,服務治理只是其中的一個方面。
Dubbo 提供了各種 Filter,對於上述中“無”的要素,可以通過擴展 Filter 來完善。例如:
-
分布式配置: 可以使用淘寶的 diamond、百度的 disconf 來實現分布式配置管理。
-
服務跟蹤: 可以使用京東開源的 Hydra,或者擴展 Filter 用 Zippin 來做服務跟蹤。
-
批量任務: 可以使用當當開源的 Elastic-Job、tbschedule。
點評:從核心要素來看,Spring Cloud 更勝一籌,在開發過程中只要整合 Spring Cloud 的子項目就可以順利的完成各種組件的融合,而 Dubbo 卻需要通過實現各種 Filter 來做定制,開發成本以及技術難度略高。
三 通訊協議
基於通訊協議層面對 2 種框架支持的協議類型以及運行效率方面進行比較。
支持協議
Dubbo 使用 RPC 通訊協議,提供序列化方式如下:
-
Dubbo:Dubbo 缺省協議采用單一長連接和 NIO 異步通訊,適合於小數據量大並發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。
-
RMI:RMI 協議采用 JDK 標准的 java.rmi.* 實現,采用阻塞式短連接和 JDK 標准序列化方式。
-
Hessian:Hessian 協議用於集成 Hessian 的服務,Hessian 底層采用 HTTP 通訊,采用 Servlet 暴露服務,Dubbo 缺省內嵌 Jetty 作為服務器實現。
-
HTTP:采用 Spring 的 Http Invoker 實現。
-
Webservice:基於 CXF 的 frontend-simple 和 transports-http 實現。
Spring Cloud
Spring Cloud 使用 HTTP 協議的 REST API。
性能比較
使用一個 Pojo 對象包含 10 個屬性,請求 10 萬次,Dubbo 和 Spring Cloud 在不同的線程數量下,每次請求耗時(ms)如下:

說明:客戶端和服務端配置均采用阿里雲的 ECS 服務器,4 核 8G 配置,Dubbo 采用默認的 Dubbo 協議。
點評:Dubbo 支持各種通信協議,而且消費方和服務方使用長鏈接方式交互,通信速度上略勝 Spring Cloud,如果對於系統的響應時間有嚴格要求,長鏈接更合適。
服務依賴方式
Dubbo
服務提供方與消費方通過接口的方式依賴,服務調用設計如下:
-
Interface 層:服務接口層,定義了服務對外提供的所有接口。
-
Molel 層:服務的 DTO 對象層。
-
Business層:業務實現層,實現 Interface 接口並且和 DB 交互。
因此需要為每個微服務定義各自的 Interface 接口,並通過持續集成發布到私有倉庫中。調用方應用對微服務提供的抽象接口存在強依賴關系,開發、測試、集成環境都需要嚴格的管理版本依賴。
通過 maven 的 install & deploy 命令把 Interface 和 Model 層發布到倉庫中,服務調用方只需要依賴 Interface 和 Model 層即可。
在開發調試階段只發布 Snapshot 版本,等到服務調試完成再發布 Release 版本,通過版本號來區分每次迭代的版本。通過 xml 配置方式即可接入 Dubbo,對程序無入侵。

Dubbo 接口依賴方式
Spring Cloud
服務提供方和服務消費方通過 Json 方式交互,因此只需要定義好相關 Json 字段即可,消費方和提供方無接口依賴。通過注解方式來實現服務配置,對於程序有一定入侵。

點評:Dubbo 服務依賴略重,需要有完善的版本管理機制,但是程序入侵少。
而 Spring Cloud 通過 Json 交互,省略了版本管理的問題,但是具體字段含義需要統一管理,自身 Rest API 方式交互,為跨平台調用奠定了基礎。
組件運行流程
Dubbo
下圖中的每個組件都是需要部署在單獨的服務器上,Gateway 用來接受前端請求、聚合服務,並批量調用后台原子服務。每個 Service 層和單獨的 DB 交互。

Dubbo 組件運行流程
Dubbo 組件運行:
-
Gateway:前置網關,具體業務操作,Gateway 通過 Dubbo 提供的負載均衡機制自動完成。
-
Service:原子服務,只提供該業務相關的原子服務。
-
Zookeeper:原子服務注冊到 ZK 上。
Spring Cloud 組件運行

Spring Cloud組件運行:
-
所有請求都統一通過 API 網關(Zuul)來訪問內部服務。
-
網關接收到請求后,從注冊中心(Eureka)獲取可用服務。
-
由 Ribbon 進行均衡負載后,分發到后端的具體實例。
-
微服務之間通過 Feign 進行通信處理業務。
點評:業務部署方式相同,都需要前置一個網關來隔絕外部直接調用原子服務的風險。
Dubbo 需要自己開發一套 API 網關,而 Spring Cloud 則可以通過 Zuul 配置即可完成網關定制。
使用方式上 Spring Cloud 略勝一籌。
微服務架構組成以及注意事項
到底使用是 Dubbo 還是 Spring Cloud 並不重要,重點在於如何合理的利用微服務。
下面是一張互聯網通用的架構圖,其中每個環節都是微服務的核心部分。

架構分解:
-
網關集群:數據的聚合、實現對接入客戶端的身份認證、防報文重放與防數據篡改、功能調用的業務鑒權、響應數據的脫敏、流量與並發控制等。
-
業務集群:一般情況下移動端訪問和瀏覽器訪問的網關需要隔離,防止業務耦合。
-
Local Cache:由於客戶端訪問業務可能需要調用多個服務聚合,所以本地緩存有效的降低了服務調用的頻次,同時也提示了訪問速度。本地緩存一般使用自動過期方式,業務場景中允許有一定的數據延時。
-
服務層:原子服務層,實現基礎的增刪改查功能,如果需要依賴其他服務需要在 Service 層主動調用。
-
Remote Cache:訪問 DB 前置一層分布式緩存,減少 DB 交互次數,提升系統的TPS。
-
DAL:數據訪問層,如果單表數據量過大則需要通過 DAL 層做數據的分庫分表處理。
-
MQ:消息隊列用來解耦服務之間的依賴,異步調用可以通過 MQ 的方式來執行。
-
數據庫主從:服務化過程中必經的階段,用來提升系統的 TPS。
注意事項:
-
服務啟動方式建議使用jar方式啟動,啟動速度快,更容易監控。
-
緩存、緩存、緩存,系統中能使用緩存的地方盡量使用緩存,通過合理的使用緩存可以有效的提高系統的TPS。
-
服務拆分要合理,盡量避免因服務拆分而導致的服務循環依賴。
-
合理的設置線程池,避免設置過大或者過小導致系統異常。
總結
Dubbo 出生於阿里系,是阿里巴巴服務化治理的核心框架,並被廣泛應用於中國各互聯網公司;只需要通過 Spring 配置的方式即可完成服務化,對於應用無入侵,設計的目的還是服務於自身的業務為主。
雖然阿里內部原因 Dubbo 曾經一度暫停維護版本,但是框架本身的成熟度以及文檔的完善程度,完全能滿足各大互聯網公司的業務需求。
如果我們使用配置中心、分布式跟蹤這些內容都需要自己去集成,這樣無形中增加了使用 Dubbo 的難度。
Spring Cloud 是大名鼎鼎的 Spring 家族的產品, 專注於企業級開源框架的研發。
Spring Cloud 自從發布到現在,仍然在不斷的高速發展,幾乎考慮了服務治理的方方面面,開發起來非常的便利和簡單。
Dubbo 於 2017 年開始又重啟維護,發布了更新后的 2.5.7 版本,而 Spring Cloud 更新的非常快,目前已經更新到 Finchley.M2。
因此,企業需要根據自身的研發水平和所處階段選擇合適的架構來解決業務問題,不管是 Dubbo 還是 Spring Cloud 都是實現微服務有效的工具。
Round 1:背景
Dubbo,是阿里巴巴服務化治理的核心框架,並被廣泛應用於阿里巴巴集團的各成員站點。阿里巴巴近幾年對開源社區的貢獻不論在國內還是國外都是引人注目的,比如:JStorm捐贈給Apache並加入Apache基金會等,為中國互聯網人爭足了面子,使得阿里巴巴在國人眼里已經從電商升級為一家科技公司了。
Spring Cloud,從命名我們就可以知道,它是Spring Source的產物,Spring社區的強大背書可以說是Java企業界最有影響力的組織了,除了Spring Source之外,還有Pivotal和Netfix是其強大的后盾與技術輸出。其中Netflix開源的整套微服務架構套件是Spring Cloud的核心。
小結:如果拿Dubbo與Netflix套件做對比,前者在國內影響力較大,后者在國外影響力較大,我認為在背景上可以打個平手;但是若要與Spring Cloud做對比,由於Spring Source的加入,在背書上,Spring Cloud略勝一籌。不過,英雄不問出處,在背景這一點上,不能作為選擇框架的主要因素,當您一籌莫展的時候,可以作為參考依據。
Round 2:社區活躍度
我們選擇一個開源框架,社區的活躍度是我們極為關注的一個要點。社區越活躍,解決問題的速度越快,框架也會越來越完善,不然當我們碰到問題,就不得不自己解決。而對於團隊來說,也就意味着我們不得不自己去維護框架的源碼,這對於團隊來說也將會是一個很大的負擔。
小結:在社區活躍度上,Spring Cloud毋庸置疑的優於Dubbo,這對於沒有大量精力與財力維護這部分開源內容的團隊來說,Spring Cloud會是更優的選擇。
Round 3:架構完整度
或許很多人會說Spring Cloud和Dubbo的對比有點不公平,Dubbo只是實現了服務治理,而Spring Cloud下面有17個子項目(可能還會新增)分別覆蓋了微服務架構下的方方面面,服務治理只是其中的一個方面,一定程度來說,Dubbo只是Spring Cloud Netflix中的一個子集。但是在選擇框架上,方案完整度恰恰是一個需要重點關注的內容。
根據Martin Fowler對 微服務架構 的描述中,雖然該架構相較於單體架構有模塊化解耦、可獨立部署、技術多樣性等諸多優點,但是由於分布式環境下解耦,也帶出了不少測試與運維復雜度。
根據微服務架構在各方面的要素,看看Spring Cloud和Dubbo都提供了哪些支持。
| Dubbo | Spring Cloud | |
|---|---|---|
| 服務注冊中心 | Zookeeper | Spring Cloud Netflix Eureka |
| 服務調用方式 | RPC | REST API |
| 服務網關 | 無 | Spring Cloud Netflix Zuul |
| 斷路器 | 不完善 | Spring Cloud Netflix Hystrix |
| 分布式配置 | 無 | Spring Cloud Config |
| 服務跟蹤 | 無 | Spring Cloud Sleuth |
| 消息總線 | 無 | Spring Cloud Bus |
| 數據流 | 無 | Spring Cloud Stream |
| 批量任務 | 無 | Spring Cloud Task |
| …… | …… | …… |
以上列舉了一些核心部件,大致可以理解為什么之前說Dubbo只是類似Netflix的一個子集了吧。當然這里需要申明一點,Dubbo對於上表中總結為“無”的組件不代表不能實現,而只是Dubbo框架自身不提供,需要另外整合以實現對應的功能,比如:
- 分布式配置:可以使用淘寶的diamond、百度的disconf來實現分布式配置管理。但是Spring Cloud中的Config組件除了提供配置管理之外,由於其存儲可以使用git,因此它天然的實現了配置內容的版本管理,可以完美的與應用版本管理整合起來。
- 服務跟蹤:可以使用京東開源的Hydra
- 批量任務:可以使用當當開源的Elastic-Job
- ……
雖然,Dubbo自身只是實現了服務治理的基礎,其他為保證集群安全、可維護、可測試等特性方面都沒有很好的實現,但是幾乎大部分關鍵組件都能找到第三方開源來實現,這些組件主要來自於國內各家大型互聯網企業的開源產品。
RPC vs REST
另外,由於Dubbo是基礎框架,其實現的內容對於我們實施微服務架構是否合理,也需要我們根據自身需求去考慮是否要修改,比如Dubbo的服務調用是通過RPC實現的,但是如果仔細拜讀過Martin Fowler的 microservices 一文,其定義的服務間通信是HTTP協議的REST API。那么這兩種有何區別呢?
先來說說,使用Dubbo的RPC來實現服務間調用的一些痛點:
- 服務提供方與調用方接口依賴方式太強:我們為每個微服務定義了各自的service抽象接口,並通過持續集成發布到私有倉庫中,調用方應用對微服務提供的抽象接口存在強依賴關系,因此不論開發、測試、集成環境都需要嚴格的管理版本依賴,才不會出現服務方與調用方的不一致導致應用無法編譯成功等一系列問題,以及這也會直接影響本地開發的環境要求,往往一個依賴很多服務的上層應用,每天都要更新很多代碼並install之后才能進行后續的開發。若沒有嚴格的版本管理制度或開發一些自動化工具,這樣的依賴關系會成為開發團隊的一大噩夢。而REST接口相比RPC更為輕量化,服務提供方和調用方的依賴只是依靠一紙契約,不存在代碼級別的強依賴,當然REST接口也有痛點,因為接口定義過輕,很容易導致定義文檔與實際實現不一致導致服務集成時的問題,但是該問題很好解決,只需要通過每個服務整合swagger,讓每個服務的代碼與文檔一體化,就能解決。所以在分布式環境下,REST方式的服務依賴要比RPC方式的依賴更為靈活。
- 服務對平台敏感,難以簡單復用:通常我們在提供對外服務時,都會以REST的方式提供出去,這樣可以實現跨平台的特點,任何一個語言的調用方都可以根據接口定義來實現。那么在Dubbo中我們要提供REST接口時,不得不實現一層代理,用來將RPC接口轉換成REST接口進行對外發布。若我們每個服務本身就以REST接口方式存在,當要對外提供服務時,主要在API網關中配置映射關系和權限控制就可實現服務的復用了。
相信這些痛點也是為什么當當網在dubbox(基於Dubbo的開源擴展)中增加了對REST支持的原因之一。
小結:Dubbo實現了服務治理的基礎,但是要完成一個完備的微服務架構,還需要在各環節去擴展和完善以保證集群的健康,以減輕開發、測試以及運維各個環節上增加出來的壓力,這樣才能讓各環節人員真正的專注於業務邏輯。而Spring Cloud依然發揚了Spring Source整合一切的作風,以標准化的姿態將一些微服務架構的成熟產品與框架揉為一體,並繼承了Spring Boot簡單配置、快速開發、輕松部署的特點,讓原本復雜的架構工作變得相對容易上手一些(如果您讀過我之前關於Spring Cloud的一些核心組件使用的文章,應該能體會這些讓人興奮而激動的特性,傳送門)。所以,如果選擇Dubbo請務必在各個環節做好整套解決方案的准備,不然很可能隨着服務數量的增長,整個團隊都將疲於應付各種架構上不足引起的困難。而如果選擇Spring Cloud,相對來說每個環節都已經有了對應的組件支持,可能有些也不一定能滿足你所有的需求,但是其活躍的社區與高速的迭代進度也會是你可以依靠的強大后盾。
Round 4:文檔質量
Dubbo的 文檔 可以說在國內開源框架中算是一流的,非常全,並且講解的也非常深入,由於版本已經穩定不再更新,所以也不太會出現不一致的情況,另外提供了中文與英文兩種版本,對於國內開發者來說,閱讀起來更加容易上手,這也是dubbo在國內更火一些的原因吧。
Spring Cloud由於整合了大量組件,文檔在體量上自然要比dubbo多很多,文檔內容上還算簡潔清楚,但是更多的是偏向整合,更深入的使用方法還是需要查看其整合組件的詳細文檔。另外由於Spring Cloud基於Spring Boot,很多例子相較於傳統Spring應用要簡單很多(因為自動化配置,很多內容都成了約定的默認配置),這對於剛接觸的開發者可能會有些不適應,比較建議了解和學習Spring Boot之后再使用Spring Cloud,不然可能會出現很多一知半解的情況。
小結:雖然Spring Cloud的文檔量大,但是如果使用Dubbo去整合其他第三方組件,實際也是要去閱讀大量第三方組件文檔的,所以在文檔量上,我覺得區別不大。對於文檔質量,由於Spring Cloud的迭代很快,難免會出現不一致的情況,所以在質量上我認為Dubbo更好一些。而對於文檔語言上,Dubbo自然對國內開發團隊來說更有優勢。
總結
通過上面再幾個環節上的分析,相信大家對Dubbo和Spring Cloud有了一個初步的了解。就我個人對這兩個框架的使用經驗和理解,打個不恰當的比喻:使用Dubbo構建的微服務架構就像組裝電腦,各環節我們的選擇自由度很高,但是最終結果很有可能因為一條內存質量不行就點不亮了,總是讓人不怎么放心,但是如果你是一名高手,那這些都不是問題;而Spring Cloud就像品牌機,在Spring Source的整合下,做了大量的兼容性測試,保證了機器擁有更高的穩定性,但是如果要在使用非原裝組件外的東西,就需要對其基礎有足夠的了解。
從目前Spring Cloud的被關注度和活躍度上來看,很有可能將來會成為微服務架構的標准框架。所以,Spring Cloud的系列文章,我會繼續寫下去。也歡迎各位朋友一起交流,共同進步。
