1.背景
想象下這么個(gè)場(chǎng)景:
有個(gè)做生活服務(wù)的APP箕母,主要提供一些生活化的咨詢信息吓妆,比如天氣嗜历、新聞宣渗、個(gè)人三金賬單抖所、政府辦事事項(xiàng)等等,那么把這些功能全部放入一個(gè)應(yīng)用肯定是不現(xiàn)實(shí)的痕囱。
按照分布式服務(wù)的設(shè)計(jì)理念田轧,可能最終的結(jié)果是用戶登錄、注冊(cè)相關(guān)的作為一個(gè)user應(yīng)用鞍恢,天氣相關(guān)的一個(gè)weather應(yīng)用傻粘,新聞資訊相關(guān)的一個(gè)news應(yīng)用,賬單相關(guān)的一個(gè)bill應(yīng)用帮掉,政府辦事相關(guān)的一個(gè)life應(yīng)用弦悉,這樣就被拆分成了若干個(gè)功能相對(duì)穩(wěn)定的應(yīng)用,同時(shí)應(yīng)用之間通過(guò)RPC調(diào)用蟆炊,共同構(gòu)成了一個(gè)分布式服務(wù)框架稽莉。
這種分布式服務(wù)架構(gòu)在流量、服務(wù)數(shù)量相對(duì)小的時(shí)候足夠滿足實(shí)際需要涩搓,但是在服務(wù)數(shù)量越來(lái)越大污秆、流量增大或者間斷性流量出現(xiàn)峰值、服務(wù)間調(diào)用越來(lái)越復(fù)雜的情況下缩膝,這種架構(gòu)就就很難再滿足需要了混狠。比如上述的APP這周搞推廣注冊(cè)送禮的活動(dòng)岸霹,突然間登錄疾层、注冊(cè)的操作暴增,此時(shí)負(fù)責(zé)處理相關(guān)業(yè)務(wù)的user應(yīng)用負(fù)荷增加贡避,出現(xiàn)響應(yīng)慢痛黎、超時(shí)、宕機(jī)的情況刮吧,怎么辦湖饱?按分布式服務(wù)框架,最簡(jiǎn)單直接的辦法是增加user應(yīng)用的實(shí)例杀捻、帶寬等硬件資源井厌,再在調(diào)用方或者Nginx端改改user應(yīng)用相關(guān)的負(fù)載列表,重啟over致讥。等推廣結(jié)束之后再改改負(fù)載列表仅仆,停掉增加的資源,重啟over.......
如此一來(lái)垢袱,反復(fù)地增加墓拜、刪除、停止请契、啟動(dòng)咳榜,只要中間某一步做錯(cuò)夏醉,就會(huì)造成難以想象的錯(cuò)誤。那么如何彈性涌韩、動(dòng)態(tài)地計(jì)算所需資源畔柔,又如何動(dòng)態(tài)地增加、刪除資源臣樱,最大程度不影響業(yè)務(wù)流轉(zhuǎn)释树,減少犯錯(cuò)誤的幾率,是一個(gè)新的課題擎淤。由此流動(dòng)式的架構(gòu)理念運(yùn)用而生奢啥,而dubbo框架正是流動(dòng)式計(jì)算架構(gòu)的一種。
2.Dubbo是什么
Dubbo是阿里旗下的一個(gè)彈性的分布式服務(wù)框架嘴拢,致力于提供高性能和透明化的RPC遠(yuǎn)程服務(wù)調(diào)用方案桩盲,以及SOA服務(wù)治理方案。
3.Dubbo能做什么
3.1.透明化的遠(yuǎn)程方法調(diào)用
沒(méi)有API侵入席吴,就能像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法赌结。
在實(shí)際項(xiàng)目中,通常會(huì)對(duì)Provider和Consumer使用的公共部分孝冒,抽象為一個(gè)通用的一個(gè)jar包柬姚,內(nèi)部定義需要的Service、DTO庄涡、POJO量承、工具類等。此時(shí)穴店,Provider端實(shí)現(xiàn)Service服務(wù)撕捍,Consumer引入jar包,申明服務(wù)泣洞。通過(guò)此種方法忧风,實(shí)現(xiàn)無(wú)API侵入,Service對(duì)Consumer透明球凰,但最終實(shí)現(xiàn)了Consumer對(duì)Provider的調(diào)用狮腿。
3.2.服務(wù)自動(dòng)注冊(cè)與發(fā)現(xiàn)
服務(wù)的注冊(cè)、發(fā)現(xiàn)呕诉、更新都是基于注冊(cè)中心Registry來(lái)實(shí)現(xiàn)的缘厢。
Registry與Provider、Registry與Consumer之間實(shí)現(xiàn)了基于Socket長(zhǎng)連接的實(shí)時(shí)心跳檢測(cè)义钉,每隔幾秒鐘檢測(cè)一次昧绣,收集Provider、Consumer的服務(wù)信息捶闸,整理更新服務(wù)列表夜畴。通過(guò)這樣的實(shí)現(xiàn)拖刃,Provider和Consumer均不再需要寫(xiě)死服務(wù)提供方地址,只需要配置注冊(cè)中心地址即可贪绘,實(shí)現(xiàn)動(dòng)態(tài)化兑牡。
3.3.軟負(fù)載均衡及容錯(cuò)機(jī)制
Dubbo提供了一系列的軟負(fù)載均衡算法供使用,可替代F5等硬件負(fù)載均衡器税灌,降低硬件成本均函,減少單點(diǎn)。
Consumer通過(guò)訂閱服務(wù)菱涤,在本地緩存可調(diào)用的服務(wù)列表苞也,在實(shí)際調(diào)用某服務(wù)時(shí),基于負(fù)載均衡算法粘秆,選取某一節(jié)點(diǎn)調(diào)用如迟。當(dāng)某服務(wù)節(jié)點(diǎn)宕機(jī)、或網(wǎng)絡(luò)不可用時(shí)攻走,Registry基于心跳檢測(cè)實(shí)時(shí)更新可調(diào)用者列表殷勘,并將更新信息推送到Consumer,由Consumer更新本地緩存昔搂,實(shí)現(xiàn)容錯(cuò)玲销,實(shí)現(xiàn)高可用。
4.Dubbo服務(wù)架構(gòu)及調(diào)用流程
Dubbo架構(gòu)圖如下所示:
節(jié)點(diǎn)角色說(shuō)明:
Provider: 暴露服務(wù)的服務(wù)提供方摘符。
Consumer: 調(diào)用遠(yuǎn)程服務(wù)的服務(wù)消費(fèi)方贤斜。
Registry: 服務(wù)注冊(cè)與發(fā)現(xiàn)的注冊(cè)中心,可選议慰。
Monitor: 統(tǒng)計(jì)服務(wù)的調(diào)用次調(diào)和調(diào)用時(shí)間的監(jiān)控中心蠢古,可選。
Container: 服務(wù)運(yùn)行容器别凹。
調(diào)用流程:
0. 服務(wù)容器負(fù)責(zé)啟動(dòng)、加載洽糟,運(yùn)行Provider炉菲。
1. Provider在啟動(dòng)時(shí),向Registry注冊(cè)自己提供的服務(wù)坤溃,Registry緩存服務(wù)列表拍霜,并建立長(zhǎng)連接心跳檢測(cè)。
2. Consumer在啟動(dòng)時(shí)薪介,向Registry訂閱自己所需的服務(wù)祠饺,并建立長(zhǎng)連接心跳檢測(cè)。
3. Registry返回服務(wù)提供者地址列表給Consumer并緩存汁政,如果服務(wù)有變更道偷,Registry將基于長(zhǎng)連接推送變更數(shù)據(jù)給Consumer并更新缀旁。
4. Consumer在使用服務(wù)時(shí),基于軟負(fù)載均衡算法勺鸦,從提供者地址列表中并巍,選一臺(tái)Provider進(jìn)行調(diào)用,如果調(diào)用失敗换途,則切換到另一臺(tái)調(diào)用懊渡。
5. Consumer和Provider,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間军拟,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到Monitor剃执。
5.Dubbo應(yīng)用搭建
Dubbo采用全Spring配置方式,透明化接入應(yīng)用懈息,只需用Spring加載Dubbo的配置即可忠蝗。
代碼結(jié)構(gòu)
代碼project結(jié)構(gòu)非常簡(jiǎn)單,如圖:
其中漓拾,
dubbo-api是公共的基礎(chǔ)包阁最,主要聲明provider和consumer共用的服務(wù)接口、工具類骇两、實(shí)體等速种,以jar包形式提供;
dubbo-provider是服務(wù)提供者低千,聲明provider需要提供的哪些服務(wù)配阵,以war包形式提供;
dubbo-customer是服務(wù)消費(fèi)者示血,聲明需要使用的服務(wù)棋傍,以war包形式提供;
dubbo-service是dubbo-api中服務(wù)的實(shí)現(xiàn)者难审,此包可直接包含在dubbo-provider中瘫拣,以jar包形式體現(xiàn)。
Dubbo-api
在公共jar包中告喊,定義服務(wù)接口麸拄,如下:
dubbo-service
在實(shí)現(xiàn)jar包中,實(shí)現(xiàn)dubbo-api中定義的接口(此實(shí)現(xiàn)對(duì)消費(fèi)方式透明的)黔姜,如下:
dubbo-provider
使用Spring配置聲明對(duì)外暴露服務(wù)拢切,主要包含:
dubbo-application服務(wù)提供者的名字:標(biāo)記唯一提供者;
dubbo-registry注冊(cè)中心地址及其端口:?jiǎn)?dòng)時(shí)秆吵,向注冊(cè)中心注冊(cè)服務(wù)淮椰,此處使用zookeeper;
dubbo-protocol通信協(xié)議及端口:各個(gè)終端之間通訊的協(xié)議,使用dubbo協(xié)議主穗;
dubbo-service暴露服務(wù)聲明:需要暴露哪些服務(wù)泻拦,就聲明哪些dubbo:service的Bean。
dubbo-customer
使用Spring配置黔牵,引用遠(yuǎn)程暴露的服務(wù)聪轿,主要包含:
dubbo-application服務(wù)消費(fèi)者名字:標(biāo)記唯一消費(fèi)者;
dubbo-registry注冊(cè)中心地址及其端口:?jiǎn)?dòng)時(shí)猾浦,向注冊(cè)中心訂閱服務(wù)陆错,并在本地緩存;
dubbo-reference服務(wù)引用:聲明需要使用的服務(wù)接口名稱金赦,和原生spring聲明bean的方式類似音瓷。
配置如下圖:
服務(wù)使用時(shí),像spring式注入JavaBean夹抗,類似本地化調(diào)用Service一樣使用绳慎,如圖:
dubbo工程搭建總結(jié)
通過(guò)上述代碼示例,不難看出dubbo使用其實(shí)非常簡(jiǎn)單漠烧,通過(guò)Spring配置全部搞定杏愤。對(duì)于消費(fèi)者來(lái)說(shuō),只需要知道服務(wù)在哪里已脓、服務(wù)名叫什么珊楼、有什么方法、入?yún)⑹悄男┘纯啥纫海恍枰纼?nèi)部的實(shí)現(xiàn)細(xì)節(jié)厕宗。這種特性完全無(wú)API侵入,實(shí)現(xiàn)各部分之間松散耦合堕担,減少依賴已慢。
6.Dubbo的高級(jí)特性
除了上述基本功能之外,dubbo具有諸多高級(jí)特性霹购,組成了dubbo整套架構(gòu)體系佑惠。
多元化注冊(cè)中心
注冊(cè)中心可以使用zookeeper、redis等作為注冊(cè)中心厕鹃,也可以去中心使用廣播形式兢仰。
zookeeper作為注冊(cè)中心,內(nèi)部存儲(chǔ)使用了目錄式結(jié)構(gòu)剂碴,此為推薦;
Redis這樣的K/V式數(shù)據(jù)存儲(chǔ)轻专,內(nèi)部則使用了服務(wù)名作為Key忆矛,URL地址作為Value,比如:
另廣播Multicast形式,啟動(dòng)時(shí)廣播自身的地址催训,無(wú)注冊(cè)中心洽议,此為測(cè)試使用。
集群容錯(cuò)
上述示例中漫拭,只使用了單個(gè)zk實(shí)例亚兄、單provider、單consumer采驻,實(shí)際生產(chǎn)中還可以配置多個(gè)實(shí)例即注冊(cè)中心集群审胚、provider集群、consumer集群礼旅,相同集群之間是等價(jià)的膳叨,最終為負(fù)載均衡提供條件。
軟負(fù)載均衡
當(dāng)注冊(cè)中心其他實(shí)例宕機(jī)痘系,只要有一個(gè)可提供服務(wù)則可保證整個(gè)應(yīng)用群可正常發(fā)布菲嘴、訂閱服務(wù);即使全部宕機(jī)只要之前的服務(wù)提供者可正常提供服務(wù)汰翠,雖不能發(fā)布和訂閱龄坪,但是消費(fèi)者任然可以調(diào)用,因?yàn)橄M(fèi)者本地緩存了可調(diào)用列表复唤。
Provider集群各實(shí)例提供了相同的服務(wù)健田,只要有實(shí)例新增或者宕機(jī),基于長(zhǎng)連接通訊苟穆,每個(gè)消費(fèi)者均能感知到并及時(shí)更新自身緩存列表抄课。實(shí)時(shí)調(diào)整路由群。
Consumer消費(fèi)者對(duì)服務(wù)進(jìn)行invoke調(diào)用時(shí)雳旅,會(huì)根據(jù)負(fù)載均衡算法跟磨,分發(fā)請(qǐng)求到某個(gè)provider實(shí)例,降低各個(gè)實(shí)例的負(fù)載攒盈。成熟的負(fù)載均衡算法有隨機(jī)抵拘、按公約權(quán)重輪詢、最少活躍調(diào)用數(shù)型豁、一致性Hash聘芜,使用者可以根據(jù)機(jī)器、網(wǎng)絡(luò)等情況實(shí)時(shí)分配和調(diào)整策略承匣,靈活方便留潦。
統(tǒng)一化管理平臺(tái)admin
dubbo提供了可視化的管理平臺(tái)dubbo-admin,使用者只要下載運(yùn)行應(yīng)用即可衣形。
此平臺(tái)提供了豐富的管理功能:
服務(wù)管理:有哪些服務(wù)驼侠,哪些在使用哪些已停止姿鸿,對(duì)應(yīng)的主機(jī)、端口倒源、權(quán)重是多少苛预,實(shí)時(shí)調(diào)整;
應(yīng)用管理:當(dāng)前有哪些應(yīng)用笋熬,各自是什么角色热某,相互調(diào)用關(guān)系是什么,使用的負(fù)載均衡算法是什么等等胳螟。
運(yùn)營(yíng)監(jiān)控中心
此為可選組件昔馋,對(duì)應(yīng)項(xiàng)目為dubbo-monitor,監(jiān)控SQL執(zhí)行旺隙、服務(wù)調(diào)用等統(tǒng)計(jì)信息绒极。和provider、Consumer一樣蔬捷,通過(guò)spring配置的形式垄提,聲明dubbo:monitor角色。在provider和consumer端周拐,聲明monitor地址铡俐,并定義AOP切面,收集監(jiān)控信息妥粟,并定時(shí)向監(jiān)控中心發(fā)送审丘。
7.Dubbo的缺點(diǎn)
上面敘述了種種dubbo的優(yōu)勢(shì),下面說(shuō)說(shuō)它的缺點(diǎn)勾给。
體系結(jié)構(gòu)方面
Dubbo要求將功能服務(wù)化滩报,抽象成若干個(gè)通用的小的服務(wù),形成分布式結(jié)構(gòu)播急。因此往往會(huì)在最后形成大量的服務(wù)脓钾,體系會(huì)非常龐大,管理起來(lái)比較困難桩警。但這跟它帶來(lái)的種種有點(diǎn)相比可训,還是微不足道的。
安全性方面
Dubbo在使用場(chǎng)景方面主要針對(duì)內(nèi)部的服務(wù)捶枢,由內(nèi)部人員進(jìn)行管理握截,一般很少對(duì)外部系統(tǒng)開(kāi)放。而通常對(duì)外的服務(wù)烂叔,一般建立WebService谨胞、Rest等形式的接口,并輔助OAuth等安全協(xié)議來(lái)來(lái)處理安全蒜鸡。這就造成了畜眨,Dubbo在安全方面實(shí)現(xiàn)的功能較少昼牛,主要原則是基本上只防君子不防小人术瓮。
目前安全性層面康聂,Dubbo通過(guò)Token令牌防止用戶繞過(guò)注冊(cè)中心直連,然后在注冊(cè)中心上管理授權(quán)胞四。Dubbo還提供服務(wù)黑白名單恬汁,來(lái)控制服務(wù)所允許的調(diào)用方。
本文作者:蘭偉敏(點(diǎn)融黑幫)辜伟,主要從事Java后端開(kāi)發(fā)氓侧,愛(ài)好電影、旅行导狡、DOTA约巷,目前主要負(fù)責(zé)貸款端LOANAPP系統(tǒng)研發(fā)。