一、dubbo簡(jiǎn)介
1.1 dubbo是什么
Apache Dubbo (incubating)是一款高性能、輕量級(jí)的開(kāi)源Java RPC框架,它提供了三大核心能力:面向接口的遠(yuǎn)程方法調(diào)用,智能容錯(cuò)和負(fù)載均衡,以及服務(wù)自動(dòng)注冊(cè)和發(fā)現(xiàn)。
1.2 dubbo官網(wǎng)
http://dubbo.apache.org/
1.3 dubbo的演變
隨著互聯(lián)網(wǎng)的發(fā)展,網(wǎng)站應(yīng)用的規(guī)模不斷擴(kuò)大,常規(guī)的垂直應(yīng)用架構(gòu)已無(wú)法應(yīng)對(duì),分布式服務(wù)架構(gòu)以及流動(dòng)計(jì)算架構(gòu)勢(shì)在必行,亟需一個(gè)治理系統(tǒng)確保架構(gòu)有條不紊的演進(jìn)。

單一應(yīng)用架構(gòu)
當(dāng)網(wǎng)站流量很小時(shí),只需一個(gè)應(yīng)用,將所有功能都部署在一起,以減少部署節(jié)點(diǎn)和成本。
此時(shí),用于簡(jiǎn)化增刪改查工作量的數(shù)據(jù)訪問(wèn)框架(ORM)是關(guān)鍵。
垂直應(yīng)用架構(gòu)
當(dāng)訪問(wèn)量逐漸增大,單一應(yīng)用增加機(jī)器帶來(lái)的加速度越來(lái)越小,將應(yīng)用拆成互不相干的幾個(gè)應(yīng)用,以提升效率。
此時(shí),用于加速前端頁(yè)面開(kāi)發(fā)的Web框架(MVC) 是關(guān)鍵。
分布式服務(wù)架構(gòu)
當(dāng)垂直應(yīng)用越來(lái)越多,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來(lái),作為獨(dú)立的服務(wù),逐漸形成穩(wěn)定的服務(wù)中心,使前端應(yīng)用能更快速的響應(yīng)多變的市場(chǎng)需求。
此時(shí),用于提高業(yè)務(wù)復(fù)用及整合的分布式服務(wù)框架(RPC)是關(guān)鍵。
流動(dòng)計(jì)算架構(gòu)
當(dāng)服務(wù)越來(lái)越多,容量的評(píng)估,小服務(wù)資源的浪費(fèi)等問(wèn)題逐漸顯現(xiàn),此時(shí)需增加一個(gè)調(diào)度中心基于訪問(wèn)壓力實(shí)時(shí)管理集群容量,提高集群利用率。
此時(shí),用于提高機(jī)器利用率的資源調(diào)度和治理中心(SOA)是關(guān)鍵。
1.4 dubbo架構(gòu)構(gòu)成
dubbo運(yùn)行架構(gòu)如下圖示:

節(jié)點(diǎn)角色說(shuō)明:
(1)服務(wù)提供者(Provider):暴露服務(wù)的服務(wù)提供方,服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
(2)服務(wù)消費(fèi)者(Consumer): 調(diào)用遠(yuǎn)程服務(wù)的服務(wù)消費(fèi)方,服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù),服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
(3)注冊(cè)中心(Registry):注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者
(4)監(jiān)控中心(Monitor):服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心
調(diào)用關(guān)系說(shuō)明:
1、服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
2、服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
3、服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
4、注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。
5、服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
6、服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。
1.5 dubbo的特性
(1)連通性:
注冊(cè)中心負(fù)責(zé)服務(wù)地址的注冊(cè)與查找,相當(dāng)于目錄服務(wù),服務(wù)提供者和消費(fèi)者只在啟動(dòng)時(shí)與注冊(cè)中心交互,注冊(cè)中心不轉(zhuǎn)發(fā)請(qǐng)求,壓力較小監(jiān)控中心負(fù)責(zé)統(tǒng)計(jì)各服務(wù)調(diào)用次數(shù),調(diào)用時(shí)間等,統(tǒng)計(jì)先在內(nèi)存匯總后每分鐘一次發(fā)送到監(jiān)控中心服務(wù)器,并以報(bào)表展示服務(wù)提供者向注冊(cè)中心注冊(cè)其提供的服務(wù),并匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間不包含網(wǎng)絡(luò)開(kāi)銷服務(wù)消費(fèi)者向注冊(cè)中心獲取服務(wù)提供者地址列表,并根據(jù)負(fù)載算法直接調(diào)用提供者,同時(shí)匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間包含網(wǎng)絡(luò)開(kāi)銷注冊(cè)中心,服務(wù)提供者,服務(wù)消費(fèi)者三者之間均為長(zhǎng)連接,監(jiān)控中心除外注冊(cè)中心通過(guò)長(zhǎng)連接感知服務(wù)提供者的存在,服務(wù)提供者宕機(jī),注冊(cè)中心將立即推送事件通知消費(fèi)者注冊(cè)中心和監(jiān)控中心全部宕機(jī),不影響已運(yùn)行的提供者和消費(fèi)者,消費(fèi)者在本地緩存了提供者列表
注冊(cè)中心和監(jiān)控中心都是可選的,服務(wù)消費(fèi)者可以直連服務(wù)提供者
(2)健狀性:
監(jiān)控中心宕掉不影響使用,只是丟失部分采樣數(shù)據(jù)數(shù)據(jù)庫(kù)宕掉后,注冊(cè)中心仍能通過(guò)緩存提供服務(wù)列表查詢,但不能注冊(cè)新服務(wù)注冊(cè)中心對(duì)等集群,任意一臺(tái)宕掉后,將自動(dòng)切換到另一臺(tái)注冊(cè)中心全部宕掉后,服務(wù)提供者和服務(wù)消費(fèi)者仍能通過(guò)本地緩存通訊服務(wù)提供者無(wú)狀態(tài),任意一臺(tái)宕掉后,不影響使用服務(wù)提供者全部宕掉后,服務(wù)消費(fèi)者應(yīng)用將無(wú)法使用,并無(wú)限次重連等待服務(wù)提供者恢復(fù)
(3)伸縮性:
注冊(cè)中心為對(duì)等集群,可動(dòng)態(tài)增加機(jī)器部署實(shí)例,所有客戶端將自動(dòng)發(fā)現(xiàn)新的注冊(cè)中心
服務(wù)提供者無(wú)狀態(tài),可動(dòng)態(tài)增加機(jī)器部署實(shí)例,注冊(cè)中心將推送新的服務(wù)提供者信息給消費(fèi)者
(4)升級(jí)性:
當(dāng)服務(wù)集群規(guī)模進(jìn)一步擴(kuò)大,帶動(dòng)IT治理結(jié)構(gòu)進(jìn)一步升級(jí),需要實(shí)現(xiàn)動(dòng)態(tài)部署,進(jìn)行流動(dòng)計(jì)算,現(xiàn)有分布式服務(wù)架構(gòu)不會(huì)帶來(lái)阻力:

1.6 dubbo的調(diào)用方式
異步調(diào)用
基于NIO的非阻塞實(shí)現(xiàn)并行調(diào)用,客戶端不需要啟動(dòng)多線程即可完成并行調(diào)用多個(gè)遠(yuǎn)程服務(wù),相對(duì)多線程開(kāi)銷較小。

1.7 dubbo支持的注冊(cè)中心
Dubbo提供的注冊(cè)中心有如下幾種類型可供選擇:
Multicast注冊(cè)中心
Zookeeper注冊(cè)中心
Redis注冊(cè)中心
Simple注冊(cè)中心
ZooKeeper是一個(gè)開(kāi)源的分布式服務(wù)框架,它是Apache Hadoop項(xiàng)目的一個(gè)子項(xiàng)目,主要用來(lái)解決分布式應(yīng)用場(chǎng)景中存在的一些問(wèn)題,如:統(tǒng)一命名服務(wù)、狀態(tài)同步服務(wù)、集群管理、分布式應(yīng)用配置管理等,它支持Standalone模式和分布式模式,在分布式模式下,能夠?yàn)榉植际綉?yīng)用提供高性能和可靠地協(xié)調(diào)服務(wù),而且使用ZooKeeper可以大大簡(jiǎn)化分布式協(xié)調(diào)服務(wù)的實(shí)現(xiàn),為開(kāi)發(fā)分布式應(yīng)用極大地降低了成本。
ZooKeeper總體架構(gòu)

ZooKeeper集群由一組Server節(jié)點(diǎn)組成,這一組Server節(jié)點(diǎn)中存在一個(gè)角色為L(zhǎng)eader的節(jié)點(diǎn),其他節(jié)點(diǎn)都為Follower。當(dāng)客戶端Client連接到ZooKeeper集群,并且執(zhí)行寫(xiě)請(qǐng)求時(shí),這些請(qǐng)求會(huì)被發(fā)送到Leader節(jié)點(diǎn)上,然后Leader節(jié)點(diǎn)上數(shù)據(jù)變更會(huì)同步到集群中其他的Follower節(jié)點(diǎn)。
1.8 dubbo支持的遠(yuǎn)程通信協(xié)議
遠(yuǎn)程通信需要指定通信雙方所約定的協(xié)議,在保證通信雙方理解協(xié)議語(yǔ)義的基礎(chǔ)上,還要保證高效、穩(wěn)定的消息傳輸。Dubbo繼承了當(dāng)前主流的網(wǎng)絡(luò)通信框架,主要包括如下幾個(gè):
Mina
Netty
Grizzly
1.9 dubbo集群容錯(cuò)和負(fù)載均衡
1、集群容錯(cuò)
在集群調(diào)用失敗時(shí),Dubbo提供了多種容錯(cuò)方案,缺省為failover重試。
Failover Cluster
失敗自動(dòng)切換,當(dāng)出現(xiàn)失敗,重試其它服務(wù)器。(缺省)
通常用于讀操作,但重試會(huì)帶來(lái)更長(zhǎng)延遲。
可通過(guò)retries=“2”來(lái)設(shè)置重試次數(shù)(不含第一次)。
Failfast Cluster
快速失敗,只發(fā)起一次調(diào)用,失敗立即報(bào)錯(cuò)。
通常用于非冪等性的寫(xiě)操作,比如新增記錄。
Failsafe Cluster
失敗安全,出現(xiàn)異常時(shí),直接忽略。
通常用于寫(xiě)入審計(jì)日志等操作。
Failback Cluster
失敗自動(dòng)恢復(fù),后臺(tái)記錄失敗請(qǐng)求,定時(shí)重發(fā)。
通常用于消息通知操作。
Forking Cluster
并行調(diào)用多個(gè)服務(wù)器,只要一個(gè)成功即返回。
通常用于實(shí)時(shí)性要求較高的讀操作,但需要浪費(fèi)更多服務(wù)資源。
可通過(guò)forks=“2”來(lái)設(shè)置最大并行數(shù)。
Broadcast Cluster
廣播調(diào)用所有提供者,逐個(gè)調(diào)用,任意一臺(tái)報(bào)錯(cuò)則報(bào)錯(cuò)。(2.1.0開(kāi)始支持)
通常用于通知所有提供者更新緩存或日志等本地資源信息。
2、負(fù)載均衡
- Random LoadBalance隨機(jī),按權(quán)重設(shè)置隨機(jī)概率。
在一個(gè)截面上碰撞的概率高,但調(diào)用量越大分布越均勻,而且按概率使用權(quán)重后也比較均勻,有利于動(dòng)態(tài)調(diào)整提供者權(quán)重。
RoundRobin LoadBalance輪循,按公約后的權(quán)重設(shè)置輪循比率。
存在慢的提供者累積請(qǐng)求問(wèn)題,比如:第二臺(tái)機(jī)器很慢,但沒(méi)掛,當(dāng)請(qǐng)求調(diào)到第二臺(tái)時(shí)就卡在那,久而久之,所有請(qǐng)求都卡在調(diào)到第二臺(tái)上。
LeastActive LoadBalance最少活躍調(diào)用數(shù),相同活躍數(shù)的隨機(jī),活躍數(shù)指調(diào)用前后計(jì)數(shù)差。
使慢的提供者收到更少請(qǐng)求,因?yàn)樵铰奶峁┱叩恼{(diào)用前后計(jì)數(shù)差會(huì)越大。
ConsistentHash LoadBalance一致性Hash,相同參數(shù)的請(qǐng)求總是發(fā)到同一提供者。
當(dāng)某一臺(tái)提供者掛時(shí),原本發(fā)往該提供者的請(qǐng)求,基于虛擬節(jié)點(diǎn),平攤到其它提供者,不會(huì)引起劇烈變動(dòng)
五、RPC的幾種方法
5.1 RPC遠(yuǎn)程過(guò)程調(diào)用
RPC(Remote Procedure Call Protocol)遠(yuǎn)程過(guò)程調(diào)用協(xié)議,通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)上請(qǐng)求調(diào)用某種服務(wù)。
一次RPC調(diào)用的過(guò)程大概有10步:
1.執(zhí)行客戶端調(diào)用語(yǔ)句,傳送參數(shù)
2.調(diào)用本地系統(tǒng)發(fā)送網(wǎng)絡(luò)消息
3.消息傳送到遠(yuǎn)程主機(jī)
4.服務(wù)器得到消息并取得參數(shù)
5.根據(jù)調(diào)用請(qǐng)求以及參數(shù)執(zhí)行遠(yuǎn)程過(guò)程(服務(wù))
6.執(zhí)行過(guò)程完畢,將結(jié)果返回服務(wù)器句柄
7.服務(wù)器句柄返回結(jié)果,調(diào)用遠(yuǎn)程主機(jī)的系統(tǒng)網(wǎng)絡(luò)服務(wù)發(fā)送結(jié)果
8.消息傳回本地主機(jī)
9.客戶端句柄由本地主機(jī)的網(wǎng)絡(luò)服務(wù)接收消息
10.客戶端接收到調(diào)用語(yǔ)句返回的結(jié)果數(shù)據(jù)
5.2 RPC的原理

5.3 RMI遠(yuǎn)程方法調(diào)用
RMI:遠(yuǎn)程方法調(diào)用(Remote Method Invocation)。能夠讓在客戶端Java虛擬機(jī)上的對(duì)象像調(diào)用本地對(duì)象一樣調(diào)用服務(wù)端java 虛擬機(jī)中的對(duì)象上的方法。

RMI遠(yuǎn)程調(diào)用步驟:
1,客戶調(diào)用客戶端輔助對(duì)象stub上的方法
2,客戶端輔助對(duì)象stub打包調(diào)用信息(變量,方法名),通過(guò)網(wǎng)絡(luò)發(fā)送給服務(wù)端輔助對(duì)象skeleton
3,服務(wù)端輔助對(duì)象skeleton將客戶端輔助對(duì)象發(fā)送來(lái)的信息解包,找出真正被調(diào)用的方法以及該方法所在對(duì)象
4,調(diào)用真正服務(wù)對(duì)象上的真正方法,并將結(jié)果返回給服務(wù)端輔助對(duì)象skeleton
5,服務(wù)端輔助對(duì)象將結(jié)果打包,發(fā)送給客戶端輔助對(duì)象stub
6,客戶端輔助對(duì)象將返回值解包,返回給調(diào)用者
7,客戶獲得返回值
5.4 RPC與RMI的區(qū)別
(1)方法調(diào)用方式不同:
RMI中是通過(guò)在客戶端的Stub對(duì)象作為遠(yuǎn)程接口進(jìn)行遠(yuǎn)程方法的調(diào)用。每個(gè)遠(yuǎn)程方法都具有方法簽名。如果一個(gè)方法在服務(wù)器上執(zhí)行,但是沒(méi)有相匹配的簽名被添加到這個(gè)遠(yuǎn)程接口(stub)上,那么這個(gè)新方法就不能被RMI客戶方所調(diào)用。
RPC中是通過(guò)網(wǎng)絡(luò)服務(wù)協(xié)議向遠(yuǎn)程主機(jī)發(fā)送請(qǐng)求,請(qǐng)求包含了一個(gè)參數(shù)集和一個(gè)文本值,通常形成“classname.methodname(參數(shù)集)”的形式。RPC遠(yuǎn)程主機(jī)就去搜索與之相匹配的類和方法,找到后就執(zhí)行方法并把結(jié)果編碼,通過(guò)網(wǎng)絡(luò)協(xié)議發(fā)回。
(2)適用語(yǔ)言范圍不同:
RMI只用于Java;
RPC是網(wǎng)絡(luò)服務(wù)協(xié)議,與操作系統(tǒng)和語(yǔ)言無(wú)關(guān)。
(3)調(diào)用結(jié)果的返回形式不同:
Java是面向?qū)ο蟮?,所以RMI的調(diào)用結(jié)果可以是對(duì)象類型或者基本數(shù)據(jù)類型;
RMI的結(jié)果統(tǒng)一由外部數(shù)據(jù)表示 (External Data Representation, XDR) 語(yǔ)言表示,這種語(yǔ)言抽象了字節(jié)序類和數(shù)據(jù)類型結(jié)構(gòu)之間的差異
5.5 Hessian(基于HTTP的遠(yuǎn)程方法調(diào)用)
基于HTTP協(xié)議傳輸,在性能方面還不夠完美,負(fù)載均衡和失效轉(zhuǎn)移依賴于應(yīng)用的負(fù)載均衡器,Hessian的使用則與RMI類似,區(qū)別在于淡化了Registry的角色,通過(guò)顯示的地址調(diào)用,利用HessianProxyFactory根據(jù)配置的地址create一個(gè)代理對(duì)象,另外還要引入Hessian的Jar包。
