1 Dubbo介紹
1.1 dubbox簡介
隨着互聯網的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分佈式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。
-
單一應用架構
當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。
此時,用於簡化增刪改查工作量的 數據訪問框架(ORM) 是關鍵。 -
垂直應用架構
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率。
此時,用於加速前端頁面開發的 Web框架(MVC) 是關鍵。 -
分佈式服務架構
當垂直應用越來越多,應用之間交互不可避免,將核心業務抽取出來,作爲獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。
此時,用於提高業務複用及整合的 分佈式服務框架(RPC) 是關鍵。 -
流動計算架構
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個調度中心基於訪問壓力實時管理集羣容量,提高集羣利用率。
此時,用於提高機器利用率的 資源調度和治理中心(SOA) 是關鍵。
dubbox是dubbo的擴展,主要在dubbo的基礎上進行了一下的改進:
1、支持REST風格遠程調用(HTTP + JSON/XML):基於非常成熟的JBoss RestEasy框架,在dubbo中實現了REST風格(HTTP + JSON/XML)的遠程調用,以顯著簡化企業內部的跨語言交互,同時顯著簡化企業對外的Open API、無線API甚至AJAX服務端等等的開發。事實上,這個REST調用也使得Dubbo可以對當今特別流行的“微服務”架構提供基礎性支持。 另外,REST調用也達到了比較高的性能,在基準測試下,HTTP + JSON與Dubbo 2.x默認的RPC協議(即TCP + Hessian2二進制序列化)之間只有1.5倍左右的差距,詳見文檔中的基準測試報告。
2、支持基於Kryo和FST的Java高效序列化實現:基於當今比較知名的Kryo和FST高性能序列化庫,爲Dubbo默認的RPC協議添加新的序列化實現,並優化調整了其序列化體系,比較顯著的提高了Dubbo RPC的性能,詳見文檔中的基準測試報告。
3、支持基於Jackson的JSON序列化:基於業界應用最廣泛的Jackson序列化庫,爲Dubbo默認的RPC協議添加新的JSON序列化實現。
4、支持基於嵌入式Tomcat的HTTP remoting體系:基於嵌入式tomcat實現dubbo的HTTP remoting體系(即dubbo-remoting-http),用以逐步取代Dubbo中舊版本的嵌入式Jetty,可以顯著的提高REST等的遠程調用性能,並將Servlet API的支持從2.5升級到3.1。(注:除了REST,dubbo中的WebServices、Hessian、HTTP Invoker等協議都基於這個HTTP remoting體系)。
5、升級Spring:將dubbo中Spring由2.x升級到目前最常用的3.x版本,減少版本衝突帶來的麻煩。
6、升級ZooKeeper客戶端:將dubbo中的zookeeper客戶端升級到最新的版本,以修正老版本中包含的bug。
7、支持完全基於Java代碼的Dubbo配置:基於Spring的Java Config,實現完全無XML的純Java代碼方式來配置dubbo
8、調整Demo應用:暫時將dubbo的demo應用調整並改寫以主要演示REST功能、Dubbo協議的新序列化方式、基於Java代碼的Spring配置等等。
9、修正了dubbo的bug 包括配置、序列化、管理界面等等的bug。
1.2 dubbo架構構成
dubbo運行架構如下圖示:
- 節點角色說明:
- 1
- 2
- 3
- 調用關係說明:
1、服務容器負責啓動,加載,運行服務提供者。
2、服務提供者在啓動時,向註冊中心註冊自己提供的服務。
3、服務消費者在啓動時,向註冊中心訂閱自己所需的服務。
4、註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者。
5、服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用。
6、服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。
1.3 dubbo的特性
(1) 連通性:
註冊中心負責服務地址的註冊與查找,相當於目錄服務,服務提供者和消費者只在啓動時與註冊中心交互,註冊中心不轉發請求,壓力較小監控中心負責統計各服務調用次數,調用時間等,統計先在內存彙總後每分鐘一次發送到監控中心服務器,並以報表展示服務提供者向註冊中心註冊其提供的服務,並彙報調用時間到監控中心,此時間不包含網絡開銷服務消費者向註冊中心獲取服務提供者地址列表,並根據負載算法直接調用提供者,同時彙報調用時間到監控中心,此時間包含網絡開銷註冊中心,服務提供者,服務消費者三者之間均爲長連接,監控中心除外註冊中心通過長連接感知服務提供者的存在,服務提供者宕機,註冊中心將立即推送事件通知消費者註冊中心和監控中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表
註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者
(2) 健狀性:
監控中心宕掉不影響使用,只是丟失部分採樣數據數據庫宕掉後,註冊中心仍能通過緩存提供服務列表查詢,但不能註冊新服務註冊中心對等集羣,任意一臺宕掉後,將自動切換到另一臺註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地緩存通訊服務提供者無狀態,任意一臺宕掉後,不影響使用服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復
(3) 伸縮性:
註冊中心爲對等集羣,可動態增加機器部署實例,所有客戶端將自動發現新的註冊中心
服務提供者無狀態,可動態增加機器部署實例,註冊中心將推送新的服務提供者信息給消費者
(4) 升級性:
當服務集羣規模進一步擴大,帶動IT治理結構進一步升級,需要實現動態部署,進行流動計算,現有分佈式服務架構不會帶來阻力:
1.4 dubbo的調用方式
- 異步調用
基於NIO的非阻塞實現並行調用,客戶端不需要啓動多線程即可完成並行調用多個遠程服務,相對多線程開銷較小。
- 本地調用
本地調用,使用了Injvm協議,是一個僞協議,它不開啓端口,不發起遠程調用,只在JVM內直接關聯,但執行Dubbo的Filter鏈。
Define injvm protocol:
- 1
Set default protocol:
- 1
Set service protocol:
- 1
Use injvm first:
- 1
- 2
- 3
- 4
- 5
- 6
注意:服務暴露與服務引用都需要聲明injvm=“true”
1.5 dubbo支持的註冊中心
Dubbo提供的註冊中心有如下幾種類型可供選擇:
- Multicast註冊中心
- Zookeeper註冊中心
- Redis註冊中心
- Simple註冊中心
ZooKeeper是一個開源的分佈式服務框架,它是Apache Hadoop項目的一個子項目,主要用來解決分佈式應用場景中存在的一些問題,如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置管理等,它支持Standalone模式和分佈式模式,在分佈式模式下,能夠爲分佈式應用提供高性能和可靠地協調服務,而且使用ZooKeeper可以大大簡化分佈式協調服務的實現,爲開發分佈式應用極大地降低了成本。
ZooKeeper總體架構
ZooKeeper集羣由一組Server節點組成,這一組Server節點中存在一個角色爲Leader的節點,其他節點都爲Follower。當客戶端Client連接到ZooKeeper集羣,並且執行寫請求時,這些請求會被髮送到Leader節點上,然後Leader節點上數據變更會同步到集羣中其他的Follower節點。
1.6 dubbo支持的遠程通信協議
遠程通信需要指定通信雙方所約定的協議,在保證通信雙方理解協議語義的基礎上,還要保證高效、穩定的消息傳輸。Dubbo繼承了當前主流的網絡通信框架,主要包括如下幾個:
- Mina
- Netty
- Grizzly
1.7 dubbo支持的遠程調用協議
Dubbo支持多種協議,如下所示:
- Dubbo協議
- Hessian協議
- HTTP協議
- RMI協議
- WebService協議
- Thrift協議
- Memcached協議
- Redis協議
在通信過程中,不同的服務等級一般對應着不同的服務質量,那麼選擇合適的協議便是一件非常重要的事情。你可以根據你應用的創建來選擇。例如,使用RMI協議,一般會受到防火牆的限制,所以對於外部與內部進行通信的場景,就不要使用RMI協議,而是基於HTTP協議或者Hessian協議。
1.8 dubbo集羣容錯和負載均衡
1、集羣容錯
在集羣調用失敗時,Dubbo提供了多種容錯方案,缺省爲failover重試。
-
Failover Cluster
失敗自動切換,當出現失敗,重試其它服務器。(缺省)
通常用於讀操作,但重試會帶來更長延遲。
可通過retries=“2”來設置重試次數(不含第一次)。 -
Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。
通常用於非冪等性的寫操作,比如新增記錄。 -
Failsafe Cluster
失敗安全,出現異常時,直接忽略。
通常用於寫入審計日誌等操作。 -
Failback Cluster
失敗自動恢復,後臺記錄失敗請求,定時重發。
通常用於消息通知操作。 -
Forking Cluster
並行調用多個服務器,只要一個成功即返回。
通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。
可通過forks=“2”來設置最大並行數。 -
Broadcast Cluster
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯。(2.1.0開始支持)
通常用於通知所有提供者更新緩存或日誌等本地資源信息。
2、負載均衡
- Random LoadBalance隨機,按權重設置隨機概率。
在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。
-
RoundRobin LoadBalance 輪循,按公約後的權重設置輪循比率。
存在慢的提供者累積請求問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。 -
LeastActive LoadBalance 最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。
使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大。 -
ConsistentHash LoadBalance 一致性Hash,相同參數的請求總是發到同一提供者。
當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
配置如:
- 1
1.9 dubbo源代碼結構
Dubbo以包結構來組織各個模塊,各個模塊及其關係,如圖所示:
-
dubbo-common 公共邏輯模塊,包括Util類和通用模型。
-
dubbo-remoting 遠程通訊模塊,相當於Dubbo協議的實現,如果RPC用RMI協議則不需要使用此包。
-
dubbo-rpc 遠程調用模塊,抽象各種協議,以及動態代理,只包含一對一的調用,不關心集羣的管理。
-
dubbo-cluster 集羣模塊,將多個服務提供方僞裝爲一個提供方,包括:負載均衡、容錯、路由等,集羣的地址列表可以是靜態配置的,也可以是由註冊中心下發。
-
dubbo-registry 註冊中心模塊,基於註冊中心下發地址的集羣方式,以及對各種註冊中心的抽象。
-
dubbo-monitor 監控模塊,統計服務調用次數,調用時間的,調用鏈跟蹤的服務。
-
dubbo-config 配置模塊,是Dubbo對外的API,用戶通過Config使用Dubbo,隱藏Dubbo所有細節。
-
dubbo-container 容器模塊,是一個Standalone的容器,以簡單的Main加載Spring啓動,因爲服務通常不需要Tomcat/JBoss等Web容器的特性,沒必要用Web容器去加載服務。
1.10 Dubbo內核實現之SPI簡單介紹
Dubbo採用微內核+插件體系,使得設計優雅,擴展性強。那所謂的微內核+插件體系是如何實現的呢!即我們定義了服務接口標準,讓廠商去實現(如果不瞭解spi的請谷歌百度下), jdk通過ServiceLoader類實現spi機制的服務查找功能。
JDK實現spi服務查找: ServiceLoader
首先定義下示例接口
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
ServiceLoader會遍歷所有jar查找META-INF/services/com.example.Spi文件
A廠商提供實現
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
在A廠商提供的jar包中的META-INF/services/com.example.Spi文件內容爲:
com.a.example.SpiAImpl #廠商A的spi實現全路徑類名
B廠商提供實現
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在B廠商提供的jar包中的META-INF/services/com.example.Spi文件內容爲:
com.b.example.SpiBImpl #廠商B的spi實現全路徑類名
ServiceLoader.load(Spi.class)讀取廠商A、B提供jar包中的文件,ServiceLoader實現了Iterable接口可通過while for循環語句遍歷出所有實現。
一個接口多種實現,就如策略模式一樣提供了策略的實現,但是沒有提供策略的選擇, 使用方可以根據isSupport方法根據業務傳入廠商名來選擇具體的廠商。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
SPI接口定義
定義了@SPI註解
- 1
- 2
- 3
只有在接口打了@SPI註解的接口類纔會去查找擴展點實現,會依次從這幾個文件中讀取擴展點
- 1
- 2
- 3
- 4
- 5
我們以Protocol接口爲例, 接口上打上SPI註解,默認擴展點名字爲dubbo
- 1
- 2
- 3
- 4
具體實現的類有:
所以說:Remoting實現是Dubbo協議的實現
2 Dubbo架構部署搭建
2.1 準備工作
在開始搭建dubbox服務架構前需要完成以下準備工作:
- 下載安裝運行zookeeper 具體安裝過程詳見zookeeper官網:http://zookeeper.apache.org/ 使用版本爲3.4.7
- 下載安裝tomcat 具體安裝過程詳見zookeeper官網:http://tomcat.apache.org/ 使用版本爲:7.0.67
- 下載dubbox代碼 github地址:http://dangdangdotcom.github.io/dubbox
2.2 build dubbox源碼
下載好dubbox的源代碼之後,可以看到dubbox的項目架構構成如下:
從上圖可以看出dubbox包含的各個組件和功能模塊。
其中dubbo-admin爲dubbox的監控管理平臺。dubbo-demo中有提供一些dubbox的各種使用實例。我們通過運行dubbo-demo中提供的功能實例來了解dubbox的使用和大致運行原理。
在dubbox中的官方github中提供瞭如下的說明:
1、git clone https://github.com/dangdangdotcom/dubbox
2、在checkout出來的dubbox目錄執行mvn install -Dmaven.test.skip=true來嘗試編譯一下dubbo(並將dubbo的jar安裝到本地maven庫)
3、在checkout出來的dubbox根目錄執行mvn idea:idea或者mvn
eclipse:eclipse,來創建IDE工程文件
4、將項目導入IDE
5、下載解壓一個zookeeper,編輯其conf/zoo.cfg後啓動zookeeper用作dubbo註冊中心:bin/zkServer.sh start
6、用IDE運行/dubbo-demo/dubbo-demo-provider/…/test目錄下的DemoProvider啓動dubbo服務端,目前他會分別啓動dubbo協議(包括用kryo和FST序列化)和REST協議的服務
7、用IDE運行/dubbo-demo/dubbo-demo-consumer/…/test目錄下的DemoConsumer來啓動dubbo客戶端調用上面的服務端,直接看console的輸出即可
8、用IDE運行/dubbo-demo/dubbo-demo-consumer/…/test目錄下的RestClient來啓動rest客戶端(模擬非dubbo的rest客戶端)調用上面的服務端,直接看console的輸出即可
9、可以在瀏覽器中直接訪問http://localhost:8888/services/users/100.xml或者http://localhost:8888/services/users/101.json之類來測試REST服務
10、瞭解tomcat和IDE集成的同事,可以直接在IDE中將/dubbo-demo/dubbo-demo-provider/部署到tomcat上,用tomcat的servlet容器來發布REST服務(要同時修改dubbo-demo-provider.xml,請看那個文件中的註釋),然後用6、7、8中的方式來訪問它。(當然也可以在命令行直接mvn package,然後將生成的war部署到外面的tomcat中做測試)
11、如果想看服務監控效果,或者避免demo拋出找不到監控的異常警告,用IDE運行/dubbo-simple/dubbo-simple-monitor/…/test目錄下的SimpleMonitor來啓動監控中心即可。
下載代碼,執行下邊的命令:
- 1
但是經測試如直接mvn install 的話會出現一系列的build 失敗信息。
需要先修改dubbox根目錄下的pom.xml文件,註釋:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
等部分。
然後再運行mvn install, 一般情況下有可能還是會build失敗。
嘗試不同的網絡環境下build,總會成功的。
2.3 運行dubbox-admin
在成功的build好dubbox源代碼之後,可以在IDE中運行dubbo-demo項目中的例子。
在運行之前需要:
1.啓動zookeeper 執行如下命令啓動:
- 1
2.測試連接zookeeper 執行如下命令測試連接
- 1
如果發現你確實啓動了zookeeper,但是連接不上的情況。請檢查防火牆設置。
3.部署dubbo-admin到你的tomcat
首先需要將dubbo-admin.war解壓後拷貝所有的文件到 webapp下的/ROOT目錄中(首先請刪除ROOT目錄中的所有文件)。 然後在部署目錄(即/ROOT目錄)下的WEB-INF目錄中找到dubbo.properties文件,打開該文件有如下配置項:
- 1
- 2
- 3
其中dubbo.registry.address項需要配置爲註冊中心的地址和端口,也就是zookeeper的地址和端口
dubbo.admin.root.password爲root管理用戶的登錄密碼。
dubbo.admin.guest.password爲guest用戶的登錄密碼。
啓動tomcat訪問dubbo-admin:
http://127.0.0.1:8686 可以看到註冊中心的系統環境,系統狀態已經供者情況
2.4 設置dubbo-demo中的配置,添加dubbo服務提供者
1.修改配置文件,設置註冊中心的地址爲安裝好的zookeeper
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
2.5 部署運行dubbo-demo-provider,dubbo-demo-consumer到測試服務器
將build之後的dubbo-demo-provider,dubbo-demo-consumer的target目錄打包上傳至需要部署的服務端。
解壓後在target目錄編寫啓動腳本:
- 1
- 2
需要注意將所有依賴的jar包 類文件添加到classpath.
運行該腳本,觀察dubbo-admin中的監控情況
參考自:https://blog.csdn.net/xlgen157387/article/details/51865289