Dubbo介紹

1 架構(gòu)

Dubbo中的五個基礎(chǔ)組件,圖中的紫色線條代表了組件初始化的路徑(init)因宇,藍(lán)色虛線是異步通知流程(async)嗡官,藍(lán)色實線則是同步阻塞調(diào)用(sync)寿羞。

  • Registry:注冊中心

  • Provider:服務(wù)提供方

  • Consumer:向Provider發(fā)起遠(yuǎn)程調(diào)用的消費(fèi)者

  • Monitor:監(jiān)控中心,用來統(tǒng)計服務(wù)調(diào)用的頻率和響應(yīng)時間

  • Container:運(yùn)行服務(wù)的容器

image.png

服務(wù)發(fā)現(xiàn)的其中一個核心組件是注冊中心矫废,Provider 注冊地址到注冊中心盏缤,Consumer 從注冊中心讀取和訂閱 Provider 地址列表。那我們具體來看一下RPC調(diào)用的具體過程:

  1. start:服務(wù)容器啟動后初始化服務(wù)提供者

  2. register:服務(wù)提供者在啟動的過程中蓖扑,向注冊中心發(fā)起注冊唉铜,進(jìn)行地址的注冊

  3. subscribe:服務(wù)消費(fèi)者在啟動的同時,向注冊中心訂閱所需的服務(wù)律杠。采用的是Pub/Sub模式潭流,也就是發(fā)布訂閱模型

  4. notify:注冊中心將Provider地址列表推送給消費(fèi)者,對于服務(wù)下線之類的變更柜去,注冊中心會主動推送變更數(shù)據(jù)到Consumer(建立在長連接之上)

  5. invoke:服務(wù)消費(fèi)者發(fā)起遠(yuǎn)程調(diào)用灰嫉,這個過程會使用負(fù)載均衡算法挑選目標(biāo)服務(wù)器

  6. count:Consumer和Provider每隔一段時間將統(tǒng)計信息發(fā)送到監(jiān)控中心,平時這些信息就暫存于內(nèi)存當(dāng)中嗓奢。

2 思維導(dǎo)圖

image.png

3 常見面試題

3.1 Dubbo 的整體架構(gòu)設(shè)計有哪些分層?

接口服務(wù)層(Service):該層與業(yè)務(wù)邏輯相關(guān)讼撒,根據(jù) provider 和 consumer 的業(yè)務(wù)設(shè)計對應(yīng)的接口和實現(xiàn)

配置層(Config):對外配置接口,以 ServiceConfig 和 ReferenceConfig 為中心

服務(wù)代理層(Proxy):服務(wù)接口透明代理,生成服務(wù)的客戶端 Stub 和 服務(wù)端的 Skeleton根盒,以 ServiceProxy 為中心钳幅,擴(kuò)展接口為 ProxyFactory

服務(wù)注冊層(Registry):封裝服務(wù)地址的注冊和發(fā)現(xiàn),以服務(wù) URL 為中心炎滞,擴(kuò)展接口為 RegistryFactory敢艰、Registry、RegistryService

路由層(Cluster):封裝多個提供者的路由和負(fù)載均衡厂榛,并橋接注冊中心盖矫,以Invoker 為中心,擴(kuò)展接口為 Cluster击奶、Directory辈双、Router 和 LoadBlancce

監(jiān)控層(Monitor):RPC 調(diào)用次數(shù)和調(diào)用時間監(jiān)控,以 Statistics 為中心柜砾,擴(kuò)展接口為 MonitorFactory湃望、Monitor 和 MonitorService

遠(yuǎn)程調(diào)用層(Protocal):封裝 RPC 調(diào)用,以 Invocation 和 Result 為中心痰驱,擴(kuò)展接口為 Protocal证芭、Invoker 和 Exporter

信息交換層(Exchange):封裝請求響應(yīng)模式,同步轉(zhuǎn)異步担映。以 Request 和Response 為中心废士,擴(kuò)展接口為 Exchanger、ExchangeChannel蝇完、ExchangeClient 和 ExchangeServer

網(wǎng)絡(luò) 傳輸 層(Transport):抽象 mina 和 netty 為統(tǒng)一接口官硝,以 Message 為中心,擴(kuò)展接口為 Channel短蜕、Transporter氢架、Client、Server 和 Codec

數(shù)據(jù)序列化層(Serialize):可復(fù)用的一些工具朋魔,擴(kuò)展接口為 Serialization岖研、ObjectInput、ObjectOutput 和 ThreadPool

Dubbo 的核心功能警检,主要就是如下 3 個核心功能:

Remoting:網(wǎng)絡(luò)通信框架孙援,提供對多種NIO框架抽象封裝,包括 “同步轉(zhuǎn)異步”和“請求-響應(yīng)”模式的信息交換方式扇雕。

Cluster:服務(wù)框架赃磨,提供基于接口方法的透明遠(yuǎn)程過程調(diào)用,包括多 協(xié)議支持洼裤,以及軟負(fù)載均衡邻辉,失敗容錯溪王,地址路由,動態(tài)配置等集群 支持值骇。

Registry:服務(wù)注冊莹菱,基于注冊中心目錄服務(wù),使服務(wù)消費(fèi)方能動態(tài) 的查找服務(wù)提供方吱瘩,使地址透明道伟,使服務(wù)提供方可以平滑增加或減少 機(jī)器。

3.2 默認(rèn)使用的是什么通信框架使碾,還有別的選擇嗎?

默認(rèn)也推薦使用 netty 框架蜜徽,還有 mina。

3.3 服務(wù)調(diào)用是阻塞的嗎票摇?

默認(rèn)是同步等待結(jié)果阻塞的拘鞋,支持異步調(diào)用。 Dubbo是基于NIO的非阻塞實現(xiàn)并行調(diào)用矢门,客戶端不需要啟動多線程即可完成并行調(diào)用多個遠(yuǎn)程服務(wù)盆色,相對多線程開銷較小,異步調(diào)用會返回一個Future對象祟剔。 異步調(diào)用流程圖如下:


image.png

3.4 Dubbo默認(rèn)使用什么注冊中心隔躲,還有別的選擇嗎?

默認(rèn)采用 Zookeeper

推薦使用 Nacos 作為注冊中心物延,還有Zookeeper宣旱, Redis、Multicast叛薯、Simple 注冊中心浑吟,但不推薦。Zookeeper是強(qiáng)一致性案训,會出現(xiàn)服務(wù)不可用的情況买置。

3.5 Dubbo支持的序列化協(xié)議粪糙?

Dubbo 支持 hession强霎、Java 二進(jìn)制序列化、json蓉冈、SOAP 文本序列化多種序列化協(xié)議城舞。但是 hession 是其默認(rèn)的序列化協(xié)議

3.6 Dubbo支持的通信協(xié)議?Dubbo調(diào)用RPC有幾種協(xié)議可以用寞酿?

  1. Dubbo 協(xié)議

    默認(rèn)就是 Dubbo 協(xié)議家夺,單一長連接,進(jìn)行的是 NIO 異步通信伐弹,基于 hessian 作為序列化協(xié)議拉馋。使用的場景是:傳輸數(shù)據(jù)量小(每次請求在 100kb 以內(nèi)),但是并發(fā)量很高煌茴。以及消費(fèi)者遠(yuǎn)大于提供者随闺。

    為了要支持高并發(fā)場景,一般是服務(wù)提供者就幾臺機(jī)器蔓腐,但是服務(wù)消費(fèi)者有上百臺矩乐,可能每天調(diào)用量達(dá)到上億次!此時用長連接是最合適的回论,就是跟每個服務(wù)消費(fèi)者維持一個長連接就可以散罕,可能總共就 100 個連接。然后后面直接基于長連接 NIO 異步通信傀蓉,可以支撐高并發(fā)請求欧漱。

  2. rmi 協(xié)議

    采用JDK標(biāo)準(zhǔn)的rmi協(xié)議實現(xiàn),傳輸參數(shù)和返回參數(shù)對象需要實現(xiàn)Serializable接口僚害,使用java標(biāo)準(zhǔn)序列化機(jī)制硫椰,傳輸數(shù)據(jù)包大小混合,消費(fèi)者和提供者個數(shù)差不多萨蚕,可傳文件靶草,傳輸協(xié)議TCP。

    Java 二進(jìn)制序列化岳遥,多個短連接奕翔,適合消費(fèi)者和提供者數(shù)量差不多的情況,適用于文件的傳輸浩蓉,一般較少用派继。

  3. hessian 協(xié)議

    hessian 序列化協(xié)議,多個短連接捻艳,適用于提供者數(shù)量比消費(fèi)者數(shù)量還多的情況驾窟,適用于文件的傳輸,一般較少用认轨。

    集成Hessian服務(wù)绅络,基于HTTP通訊,采用Servlet暴露服務(wù)嘁字,Dubbo內(nèi)嵌Jetty作為服務(wù)器時默認(rèn)實現(xiàn)恩急,提供與Hession服務(wù)互操作。

  4. http 協(xié)議

    json 序列化纪蜒。

    基于Http表單提交的遠(yuǎn)程調(diào)用協(xié)議衷恭,使用Spring的HttpInvoke實現(xiàn)。多個短連接纯续,傳輸協(xié)議HTTP随珠,傳入?yún)?shù)大小混合灭袁,提供者個數(shù)多于消費(fèi)者,需要給應(yīng)用程序和瀏覽器JS調(diào)用窗看;

  5. webservice

    SOAP 文本序列化简卧。

    基于WebService的遠(yuǎn)程調(diào)用協(xié)議,集成CXF實現(xiàn)烤芦,提供和原生WebService的互操作举娩。多個短連接,基于HTTP傳輸构罗,同步傳輸铜涉,適用系統(tǒng)集成和跨語言調(diào)用;

  6. memcache

    基于memcached實現(xiàn)的RPC協(xié)議

  7. redis

    基于redis實現(xiàn)的RPC協(xié)議

  8. thrift 協(xié)議

    當(dāng)前 Dubbo 支持的 thrift 協(xié)議是對 thrift 原生協(xié)議 [2] 的擴(kuò)展遂唧,在原生協(xié)議的基礎(chǔ)上添加了一些額外的頭信息芙代,比如 service name,magic number 等盖彭。

  9. RESTful

    基于標(biāo)準(zhǔn)的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的簡寫)實現(xiàn)的REST調(diào)用支持纹烹。

3.7 服務(wù)提供者能實現(xiàn)失效踢出是什么原理?

服務(wù)失效踢出基于 zookeeper 的臨時節(jié)點(diǎn)原理召边。

3.8 如何解決服務(wù)調(diào)用鏈過長的問題铺呵?

可以結(jié)合 zipkin 實現(xiàn)分布式服務(wù)追蹤。

3.9 說說核心的配置有哪些隧熙?

image.png

在 Provider 上可以配置的 Consumer 端的屬性有哪些片挂?

  • timeout:方法調(diào)用超時

  • retries:失敗重試次數(shù),默認(rèn)重試2次

  • loadbalance:負(fù)載均衡算法贞盯,默認(rèn)隨機(jī)

  • actives:消費(fèi)者端音念,最大并發(fā)調(diào)用限制

3.10 同一個服務(wù)多個注冊的情況下可以直連某一個服務(wù)嗎?

可以點(diǎn)對點(diǎn)直連躏敢,修改配置即可闷愤,也可以通過 telnet 直接某個服務(wù)。

3.11 Dubbo 集群容錯有幾種方案件余?

image.png

3.12 Dubbo 服務(wù)降級讥脐,失敗重試怎么做?

  • Dubbo 2.2.0 以上版本支持蛾扇。

  • Dubbo提供了mock配置攘烛,可以很好的實現(xiàn)Dubbo服務(wù)降級魏滚。mock只在出現(xiàn)非業(yè)務(wù)異常(比如超時镀首,網(wǎng)絡(luò)異常等)時執(zhí)行。

  • mock的配置支持兩種

    Mock Class降級處理:boolean值鼠次,默認(rèn)的為false更哄。如果配置為true芋齿,則缺省使用mock類名,即類名+Mock后綴成翩;

    Mock Null降級處理:配置"return null"觅捆,可以很簡單的忽略掉異常。

3.13 Dubbo Monitor 實現(xiàn)原理麻敌?

Consumer 端在發(fā)起調(diào)用之前會先走 filter 鏈栅炒;provider 端在接收到請求時也是先走 filter 鏈,然后才進(jìn)行真正的業(yè)務(wù)邏輯處理术羔。默認(rèn)情況下赢赊,在 consumer 和 provider 的 filter 鏈中都會有 Monitorfilter。

  1. MonitorFilter 向 DubboMonitor 發(fā)送數(shù)據(jù)

  2. DubboMonitor 將數(shù)據(jù)進(jìn)行聚合后(默認(rèn)聚合 1min 中的統(tǒng)計數(shù)據(jù))暫存到ConcurrentMap<Statistics, AtomicReference> statisticsMap级历,然后使用一個含有 3 個線程(線程名字:DubboMonitorSendTimer)的線程池每隔 1min 鐘释移,調(diào)用 SimpleMonitorService 遍歷發(fā)送 statisticsMap 中的統(tǒng)計數(shù)據(jù),每發(fā)送完畢一個寥殖,就重置當(dāng)前的 Statistics 的 AtomicReference

  3. SimpleMonitorService 將這些聚合數(shù)據(jù)塞入 BlockingQueue queue 中(隊列大寫為 100000)

  4. SimpleMonitorService 使用一個后臺線程(線程名為:DubboMonitorAsyncWriteLogThread)將 queue 中的數(shù)據(jù)寫入文件(該線程以死循環(huán)的形式來寫)

  5. SimpleMonitorService 還會使用一個含有 1 個線程(線程名字:DubboMonitorTimer)的線程池每隔 5min 鐘玩讳,將文件中的統(tǒng)計數(shù)據(jù)畫成圖表

3.14 Dubbo 用到哪些設(shè)計模式?

Dubbo 框架在初始化和通信過程中使用了多種設(shè)計模式嚼贡,可靈活控制類加載熏纯、權(quán)限控制等功能。 工廠模式 Provider 在 export 服務(wù)時粤策,會調(diào)用 ServiceConfig 的 export 方法豆巨。ServiceConfig中有個字段:

private static final Protocol protocol =
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtensi
on();

Dubbo 里有很多這種代碼。這也是一種工廠模式掐场,只是實現(xiàn)類的獲取采用了 JDKSPI 的機(jī)制往扔。這么實現(xiàn)的優(yōu)點(diǎn)是可擴(kuò)展性強(qiáng),想要擴(kuò)展實現(xiàn)熊户,只需要在 classpath下增加個文件就可以了萍膛,代碼零侵入。另外嚷堡,像上面的 Adaptive 實現(xiàn)蝗罗,可以做到調(diào)用時動態(tài)決定調(diào)用哪個實現(xiàn),但是由于這種實現(xiàn)采用了動態(tài)代理蝌戒,會造成代碼調(diào)試比較麻煩串塑,需要分析出實際調(diào)用的實現(xiàn)類。

裝飾器模式

Dubbo 在啟動和調(diào)用階段都大量使用了裝飾器模式北苟。以 Provider 提供的調(diào)用鏈為例桩匪,具體的調(diào)用鏈代碼是在 ProtocolFilterWrapper 的 buildInvokerChain 完成的,具體是將注解中含有 group=provider 的 Filter 實現(xiàn)友鼻,按照 order 排序傻昙,最后的調(diào)用順序是:

EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter ->
ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter ->
ExceptionFilter

更確切地說闺骚,這里是裝飾器和責(zé)任鏈模式的混合使用。例如妆档,EchoFilter 的作用是判斷是否是回聲測試請求僻爽,是的話直接返回內(nèi)容,這是一種責(zé)任鏈的體現(xiàn)贾惦。而像ClassLoaderFilter 則只是在主功能上添加了功能荐绝,更改當(dāng)前線程的 ClassLoader朱灿,這是典型的裝飾器模式。

觀察者模式

Dubbo 的 Provider 啟動時,需要與注冊中心交互褪子,先注冊自己的服務(wù)易核,再訂閱自己的服務(wù)嗅蔬,訂閱時蜘渣,采用了觀察者模式,開啟一個 listener杰刽。注冊中心會每 5 秒定時檢查是否有服務(wù)更新菠发,如果有更新,向該服務(wù)的提供者發(fā)送一個 notify 消息贺嫂,provider 接受到 notify 消息后滓鸠,運(yùn)行 NotifyListener 的 notify 方法,執(zhí)行監(jiān)聽器方法第喳。

動態(tài)代理模式

Dubbo 擴(kuò)展 JDK SPI 的類 ExtensionLoader 的 Adaptive 實現(xiàn)是典型的動態(tài)代理實現(xiàn)糜俗。Dubbo 需要靈活地控制實現(xiàn)類,即在調(diào)用階段動態(tài)地根據(jù)參數(shù)決定調(diào)用哪個實現(xiàn)類曲饱,所以采用先生成代理類的方法悠抹,能夠做到靈活的調(diào)用。生成代理類的代碼是 ExtensionLoader 的 createAdaptiveExtensionClassCode 方法扩淀。代理類主要邏輯是楔敌,獲取 URL 參數(shù)中指定參數(shù)的值作為獲取實現(xiàn)類的 key。

3.15 Dubbo 配置文件是如何加載到 Spring 中的驻谆?

Spring 容器在啟動的時候卵凑,會讀取到 Spring 默認(rèn)的一些 schema 以及 Dubbo 自定義的 schema,每個 schema 都會對應(yīng)一個自己的 NamespaceHandler胜臊,NamespaceHandler 里面通過 BeanDefinitionParser 來解析配置信息并轉(zhuǎn)化為需要加載的 bean 對象勺卢!

3.16 Dubbo SPI 和 Java SPI 區(qū)別?

JDK SPI: JDK 標(biāo)準(zhǔn)的 SPI 會一次性加載所有的擴(kuò)展實現(xiàn)象对,如果有的擴(kuò)展吃實話很耗時黑忱,但也沒用上,很浪費(fèi)資源。所以只希望加載某個的實現(xiàn)杨何,就不現(xiàn)實了

DUBBO SPI:

1、對 Dubbo 進(jìn)行擴(kuò)展沥邻,不需要改動 Dubbo 的源碼

2危虱、延遲加載,可以一次只加載自己想要加載的擴(kuò)展實現(xiàn)唐全。

3埃跷、增加了對擴(kuò)展點(diǎn) IOC 和 AOP 的支持,一個擴(kuò)展點(diǎn)可以直接 setter 注入其它擴(kuò)展點(diǎn)邮利。

4弥雹、Dubbo 的擴(kuò)展機(jī)制能很好的支持第三方 IoC 容器,默認(rèn)支持 Spring Bean延届。

3.17 Dubbo 支持分布式事務(wù)嗎剪勿?

目前暫時不支持,可與通過 tcc-transaction 框架實現(xiàn)

tcc-transaction 是開源的 TCC 補(bǔ)償性分布式事務(wù)框架 TCC-Transaction 通過 Dubbo 隱式傳參的功能方庭,避免自己對業(yè)務(wù)代碼的入侵厕吉。

3.18 Dubbo 可以對結(jié)果進(jìn)行緩存嗎?

為了提高數(shù)據(jù)訪問的速度械念。Dubbo 提供了聲明式緩存头朱,以減少用戶加緩存的工作量<dubbo:reference cache="true" /> 其實比普通的配置文件就多了一個標(biāo)簽 cache="true"

3.19 服務(wù)上線怎么兼容舊版本?

可以用版本號(version)過渡龄减,多個不同版本的服務(wù)注冊到注冊中心项钮,版本號不同的服務(wù)相互間不引用。這個和服務(wù)分組的概念有一點(diǎn)類似希停。

3.20 Dubbo 必須依賴的包有哪些烁巫?

Dubbo 必須依賴 JDK,其他為可選宠能。

3.21 Dubbo telnet 命令能做什么程拭?

dubbo 服務(wù)發(fā)布之后,我們可以利用 telnet 命令進(jìn)行調(diào)試棍潘、管理恃鞋。Dubbo2.0.5 以上版本服務(wù)提供端口支持 telnet 命令 連接服務(wù) telnet localhost 20880 //鍵入回車進(jìn)入 Dubbo 命令模式。 查看服務(wù)列表

dubbo>ls
com.test.TestService
dubbo>ls com.test.TestService
create
delete
query

· ls (list services and methods)
· ls : 顯示服務(wù)列表亦歉。
· ls -l : 顯示服務(wù)詳細(xì)信息列表恤浪。
· ls XxxService:顯示服務(wù)的方法列表。
· ls -l XxxService:顯示服務(wù)的方法詳細(xì)信息列表肴楷。

3.22 Dubbo 如何優(yōu)雅停機(jī)水由?

Dubbo 是通過 JDK 的 ShutdownHook 來完成優(yōu)雅停機(jī)的,所以如果使用kill -9 PID 等強(qiáng)制關(guān)閉指令赛蔫,是不會執(zhí)行優(yōu)雅停機(jī)的砂客,只有通過 kill PID 時泥张,才會執(zhí)行。

3.23 Dubbo 和 Dubbox 之間的區(qū)別鞠值?

Dubbox 是繼 Dubbo 停止維護(hù)后媚创,當(dāng)當(dāng)網(wǎng)基于 Dubbo 做的一個擴(kuò)展項目,如加了服務(wù)可 Restful 調(diào)用彤恶,更新了開源組件等钞钙。

3.24 Dubbo和SpringCloud的區(qū)別?springcloud和Dubbo的對比声离?你覺得用 Dubbo 好還是 Spring Cloud 好芒炼?

1)通信方式不同

Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式术徊。 由于Dubbo底層是使用Netty這樣的NIO框架本刽,是基于TCP協(xié)議傳輸?shù)模浜弦訦ession序列化完成RPC赠涮。 SpringCloud是基于Http協(xié)議+rest接口調(diào)用遠(yuǎn)程過程的盅安,相對來說,Http請求會有更大的報文世囊,占的帶寬也會更多别瞭。

2)組成部分不同

image.png

3)社區(qū)活躍度

Dubbo的更新數(shù)度慢,更新頻率低 相比于 Dubbo株憾,spring Cloud是一個正在持續(xù)維護(hù)的蝙寨、社區(qū)更加火熱的開源項目,這就可以保證使用它構(gòu)建的系統(tǒng)持續(xù)地得到開源力量的支持嗤瞎。

3.25 Dubbo啟動時如果依賴的服務(wù)不可用會怎樣墙歪?

Dubbo缺省會在啟動時檢查依賴的服務(wù)是否可用,不可用時會拋出異常贝奇,阻止Spring初始化完成虹菲,默認(rèn)check=“true”,可以通過 check=“false” 關(guān)閉檢查掉瞳。

3.26 Dubbo的重試機(jī)制

Dubbo在調(diào)用服務(wù)不成功時毕源,默認(rèn)會重試2次。加上初始一次陕习,總共調(diào)用提供者3次 Dubbo的路由機(jī)制霎褐,會把超時的請求路由到其他機(jī)器上,而不是本次嘗試该镣,所以Dubbo的重試機(jī)制也能一定程度的保證服務(wù)的治理冻璃。 如果不合理的配置重試次數(shù),當(dāng)失敗時會進(jìn)行重試多次,這樣在某個時間點(diǎn)出現(xiàn)性能問題省艳,調(diào)用方再連續(xù)重復(fù)調(diào)用娘纷,系統(tǒng)請求變?yōu)檎V档膔etries倍,系統(tǒng)壓力會大增跋炕,容易引起服務(wù)雪崩赖晶,需要根據(jù)業(yè)務(wù)情況規(guī)劃好如何進(jìn)行異常處理,何時進(jìn)行重試枣购。

<dubbo:reference id="xx" interface="xx"  retries="2" timeout="3000"/>
  1. timeout=“3000” 嬉探,服務(wù)調(diào)用的超時時間擦耀,調(diào)用服務(wù)的過程中如果達(dá)到3秒就會報超時異常棉圈,超時異常后客戶端會進(jìn)行嘗試設(shè)定的“retries”次調(diào)用。有一個需要注意的地方眷蜓,timeout只有在超時異常才有效分瘾,如果是其他異常導(dǎo)致dubbo服務(wù)調(diào)用拋異常,會立即進(jìn)入下一次嘗試吁系。

  2. retries=“2” 德召,即重試兩次,如果失敗就拋出異常汽纤。

3.27 Dubbo有哪幾種負(fù)載均衡策略上岗,默認(rèn)是哪種?Dubbo的負(fù)載均衡原理蕴坪?

Random LoadBalance:隨機(jī)肴掷,按權(quán)重設(shè)置隨機(jī)概率。默認(rèn) RoundRobin LoadBalance:輪詢背传,按公約后的權(quán)重設(shè)置輪詢比率呆瞻。 LeastActive LoadBalance:最少活躍調(diào)用數(shù),相同活躍數(shù)的隨機(jī)径玖。 ConsistentHash LoadBalance:一致性Hash,相同參數(shù)的請求總是發(fā)到同一提供者痴脾。

3.28 底層是怎么實現(xiàn)的?

Dubb的底層通信是利用netty來實現(xiàn)的梳星。

3.29 Dubbo的線程模型

Dubbo線程模型包括線程模型策略和Dubbo線程池策略兩個方面赞赖。

線程模型策略

Dubbo默認(rèn)的底層網(wǎng)絡(luò)通信使用的是Netty,服務(wù)提供方NettyServer使用兩級線程池冤灾,其中EventLoopGroup(boss)主要用來接收客戶端的鏈接請求薯定,并把完成TCP三次握手的連接分發(fā)給EventLoopGroup(worker)來處理,注意把boss和worker線程組稱為I/O線程瞳购,前者處理IO連接事件话侄,后者處理IO讀寫事件。

Dubbo中根據(jù)請求的消息類是直接被I/O線程處理還是被業(yè)務(wù)線程池處理,Dubbo提供了下面幾種線程模型:

  • all(AllDispatcher類):所有消息都派發(fā)到業(yè)務(wù)線程池年堆,這些消息包括請求吞杭、響應(yīng)、連接事件变丧、斷開事件等芽狗,響應(yīng)消息會優(yōu)先使用對于請求所使用的線程池。默認(rèn)的策略

  • direct(DirectDispatcher類):所有消息都不派發(fā)到業(yè)務(wù)線程池痒蓬,全部在IO線程上直接執(zhí)行童擎。

  • message(MessageOnlyDispatcher類):只有請求響應(yīng)消息派發(fā)到業(yè)務(wù)線程池,其他消息如連接事件攻晒、斷開事件顾复、心跳事件等,直接在I/O線程上執(zhí)行鲁捏。

  • execution(ExecutionDispatcher類):只把請求類消息派發(fā)到業(yè)務(wù)線程池處理芯砸,但是響應(yīng)、連接事件给梅、斷開事件假丧、心跳事件等消息直接在I/O線程上執(zhí)行。

  • connection(ConnectionOrderedDispatcher類):在I/O線程上將連接事件动羽、斷開事件放入隊列包帚,有序地逐個執(zhí)行,其他消息派發(fā)到業(yè)務(wù)線程池處理运吓。

image.png

AllChannelHandler是默認(rèn)的策略:

image.png

下面以DirectDispatcher類進(jìn)行分析:

public class DirectChannelHandler extends WrappedChannelHandler {

 public DirectChannelHandler(ChannelHandler handler, URL url) {
 super(handler, url);
 }

 @Override
 public void received(Channel channel, Object message) throws RemotingException {
 ExecutorService executor = getPreferredExecutorService(message);
 if (executor instanceof ThreadlessExecutor) {
 try {
 executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
 } catch (Throwable t) {
 throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
 }
 } else {
 handler.received(channel, message);
 }
 }
}

DirectDispatcher類重寫了received方法渴邦,注意 ThreadlessExecutor 被應(yīng)用在調(diào)用 future.get() 之前,先調(diào)用 ThreadlessExecutor.wait()羽德,wait 會使業(yè)務(wù)線程在一個阻塞隊列上等待几莽,直到隊列中被加入元素。很明顯宅静,provider側(cè)調(diào)用getPreferredExecutorService(message)返回的不是ThreadlessExecutor章蚣,所以會在當(dāng)前IO線程執(zhí)行執(zhí)行。

其他事件姨夹,比如連接纤垂、異常、斷開等磷账,都是在WrappedChannelHandler中默認(rèn)實現(xiàn):執(zhí)行在當(dāng)前IO線程中執(zhí)行的峭沦,代碼如下:

@Override
public void connected(Channel channel) throws RemotingException {
 handler.connected(channel);
}

@Override
public void disconnected(Channel channel) throws RemotingException {
 handler.disconnected(channel);
}

@Override
public void sent(Channel channel, Object message) throws RemotingException {
 handler.sent(channel, message);
}

@Override
public void received(Channel channel, Object message) throws RemotingException {
 handler.received(channel, message);
}

@Override
public void caught(Channel channel, Throwable exception) throws RemotingException {
 handler.caught(channel, exception);
}

Dubbo線程池策略

Dubbo處理流程,為了盡量早地釋放Netty的I/O線程逃糟,某些線程模型會把請求投遞到線程池進(jìn)行異步處理吼鱼,那么這里所謂的線程池是什么樣的線程池呢蓬豁?

其實這里的線程池ThreadPool也是一個擴(kuò)展接口SPI,Dubbo提供了該擴(kuò)展接口的一些實現(xiàn)菇肃,具體如下:

  • FixedThreadPool:創(chuàng)建一個具有固定個數(shù)線程的線程池地粪。默認(rèn)的線程池策略

  • LimitedThreadPool:創(chuàng)建一個線程池,這個線程池中的線程個數(shù)隨著需要量動態(tài)增加琐谤,但是數(shù)量不超過配置的閾值蟆技。另外,空閑線程不會被回收斗忌,會一直存在质礼。

  • EagerThreadPool:創(chuàng)建一個線程池,在這個線程池中织阳,當(dāng)所有核心線程都處于忙碌狀態(tài)時眶蕉,將創(chuàng)建新的線程來執(zhí)行新任務(wù),而不是把任務(wù)放入線程池阻塞隊列陈哑。

  • CachedThreadPool:創(chuàng)建一個自適應(yīng)線程池妻坝,當(dāng)線程空閑1分鐘時伸眶,線程會被回收惊窖;當(dāng)有新請求到來時,會創(chuàng)建新線程厘贼。

知道了這些線程池之后界酒,那么是什么時候進(jìn)行SPI加載對應(yīng)的線程池實現(xiàn)呢?具體是在Dubbo 線程模型獲取對應(yīng)線程池時進(jìn)行SPI加載的嘴秸,具體邏輯在方法 org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository#createExecutor中:

private ExecutorService createExecutor(URL url) {
 return (ExecutorService) extensionAccessor.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
 }

@SPI(value = "fixed", scope = ExtensionScope.FRAMEWORK)
public interface ThreadPool {

 /**
 * Thread pool
 *
 * @param url URL contains thread parameter
 * @return thread pool
 */
 @Adaptive({THREADPOOL_KEY})
 Executor getExecutor(URL url);

}

從代碼來看毁欣,默認(rèn)的線程池策略是fixed模式的線程池,其coreSize默認(rèn)為200岳掐,隊列大小為0凭疮,其代碼如下:

/**

 * Creates a thread pool that reuses a fixed number of threads
 *

 * @see java.util.concurrent.Executors#newFixedThreadPool(int)
 */
 public class FixedThreadPool implements ThreadPool {

 @Override
 public Executor getExecutor(URL url) {
 String name = url.getParameter(THREAD_NAME_KEY, (String) url.getAttribute(THREAD_NAME_KEY, DEFAULT_THREAD_NAME));
 int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
 int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
 return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
 queues == 0 ? new SynchronousQueue<Runnable>() :
 (queues < 0 ? new LinkedBlockingQueue<Runnable>()
 : new LinkedBlockingQueue<Runnable>(queues)),
 new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
 }

}

3.30 Dubbo 超時時間怎樣設(shè)置?

Dubbo 超時時間設(shè)置有兩種方式:

服務(wù)提供者端設(shè)置超時時間,在 Dubbo 的用戶文檔中串述,推薦如果能在服務(wù) 端多配置就盡量多配置执解,因為服務(wù)提供者比消費(fèi)者更清楚自己提供的服務(wù)特性。

服務(wù)消費(fèi)者端設(shè)置超時時間纲酗,如果在消費(fèi)者端設(shè)置了超時時間衰腌,以消費(fèi)者端 為主,即優(yōu)先級更高觅赊。因為服務(wù)調(diào)用方設(shè)置超時時間控制性更靈活右蕊。如果消 費(fèi)方超時,服務(wù)端線程不會定制吮螺,會產(chǎn)生警告饶囚。

3.31 RPC vs REST

服務(wù)提供方與調(diào)用方接口依賴方式太強(qiáng):我們?yōu)槊總€微服務(wù)定義了各自的service抽象接口帕翻,并通過持續(xù)集成發(fā)布到私有倉庫中,調(diào)用方應(yīng)用對微服務(wù)提供的抽象接口存在強(qiáng)依賴關(guān)系萝风,因此不論開發(fā)熊咽、測試、集成環(huán)境都需要嚴(yán)格的管理版本依賴闹丐,才不會出現(xiàn)服務(wù)方與調(diào)用方的不一致導(dǎo)致應(yīng)用無法編譯成功等一系列問題横殴,以及這也會直接影響本地開發(fā)的環(huán)境要求,往往一個依賴很多服務(wù)的上層應(yīng)用卿拴,每天都要更新很多代碼并install之后才能進(jìn)行后續(xù)的開發(fā)衫仑。若沒有嚴(yán)格的版本管理制度或開發(fā)一些自動化工具,這樣的依賴關(guān)系會成為開發(fā)團(tuán)隊的一大噩夢堕花。而REST接口相比RPC更為輕量化文狱,服務(wù)提供方和調(diào)用方的依賴只是依靠一紙契約,不存在代碼級別的強(qiáng)依賴缘挽,當(dāng)然REST接口也有痛點(diǎn)瞄崇,因為接口定義過輕,很容易導(dǎo)致定義文檔與實際實現(xiàn)不一致導(dǎo)致服務(wù)集成時的問題壕曼,但是該問題很好解決苏研,只需要通過每個服務(wù)整合swagger,讓每個服務(wù)的代碼與文檔一體化腮郊,就能解決摹蘑。所以在分布式環(huán)境下,REST方式的服務(wù)依賴要比RPC方式的依賴更為靈活轧飞。

服務(wù)對平臺敏感衅鹿,難以簡單復(fù)用:通常我們在提供對外服務(wù)時,都會以REST的方式提供出去过咬,這樣可以實現(xiàn)跨平臺的特點(diǎn)大渤,任何一個語言的調(diào)用方都可以根據(jù)接口定義來實現(xiàn)。那么在Dubbo中我們要提供REST接口時掸绞,不得不實現(xiàn)一層代理泵三,用來將RPC接口轉(zhuǎn)換成REST接口進(jìn)行對外發(fā)布。若我們每個服務(wù)本身就以REST接口方式存在集漾,當(dāng)要對外提供服務(wù)時切黔,主要在API網(wǎng)關(guān)中配置映射關(guān)系和權(quán)限控制就可實現(xiàn)服務(wù)的復(fù)用了。

Dubbo實現(xiàn)了服務(wù)治理的基礎(chǔ)具篇,但是要完成一個完備的微服務(wù)架構(gòu)纬霞,還需要在各環(huán)節(jié)去擴(kuò)展和完善以保證集群的健康,以減輕開發(fā)驱显、測試以及運(yùn)維各個環(huán)節(jié)上增加出來的壓力诗芜,這樣才能讓各環(huán)節(jié)人員真正的專注于業(yè)務(wù)邏輯瞳抓。而Spring Cloud依然發(fā)揚(yáng)了Spring Source整合一切的作風(fēng),以標(biāo)準(zhǔn)化的姿態(tài)將一些微服務(wù)架構(gòu)的成熟產(chǎn)品與框架揉為一體伏恐,并繼承了Spring Boot簡單配置孩哑、快速開發(fā)、輕松部署的特點(diǎn)翠桦,讓原本復(fù)雜的架構(gòu)工作變得相對容易上手一些横蜒。所以,如果選擇Dubbo請務(wù)必在各個環(huán)節(jié)做好整套解決方案的準(zhǔn)備销凑,不然很可能隨著服務(wù)數(shù)量的增長丛晌,整個團(tuán)隊都將疲于應(yīng)付各種架構(gòu)上不足引起的困難。而如果選擇Spring Cloud斗幼,相對來說每個環(huán)節(jié)都已經(jīng)有了對應(yīng)的組件支持澎蛛,可能有些也不一定能滿足你所有的需求,但是其活躍的社區(qū)與高速的迭代進(jìn)度也會是你可以依靠的強(qiáng)大后盾蜕窿。

Dubbox: 相對于Dubbo支持了REST谋逻,估計是很多公司選擇Dubbox的一個重要原因之一,但如果使用Dubbo的RPC調(diào)用方式桐经,服務(wù)間仍然會存在API強(qiáng)依賴毁兆,各有利弊,懂的取舍吧次询。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荧恍,一起剝皮案震驚了整個濱河市瓷叫,隨后出現(xiàn)的幾起案子屯吊,更是在濱河造成了極大的恐慌,老刑警劉巖摹菠,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盒卸,死亡現(xiàn)場離奇詭異,居然都是意外死亡次氨,警方通過查閱死者的電腦和手機(jī)蔽介,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煮寡,“玉大人虹蓄,你說我怎么就攤上這事⌒宜海” “怎么了薇组?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坐儿。 經(jīng)常有香客問我律胀,道長宋光,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任炭菌,我火速辦了婚禮罪佳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘黑低。我一直安慰自己赘艳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布克握。 她就那樣靜靜地躺著第练,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玛荞。 梳的紋絲不亂的頭發(fā)上娇掏,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音勋眯,去河邊找鬼婴梧。 笑死,一個胖子當(dāng)著我的面吹牛客蹋,可吹牛的內(nèi)容都是我干的塞蹭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼讶坯,長吁一口氣:“原來是場噩夢啊……” “哼番电!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起辆琅,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤漱办,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后婉烟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娩井,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年似袁,在試婚紗的時候發(fā)現(xiàn)自己被綠了洞辣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡昙衅,死狀恐怖扬霜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情而涉,我是刑警寧澤著瓶,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站婴谱,受9級特大地震影響蟹但,放射性物質(zhì)發(fā)生泄漏躯泰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一华糖、第九天 我趴在偏房一處隱蔽的房頂上張望麦向。 院中可真熱鬧,春花似錦客叉、人聲如沸诵竭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卵慰。三九已至,卻和暖如春佛呻,著一層夾襖步出監(jiān)牢的瞬間裳朋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工吓著, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鲤嫡,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓绑莺,卻偏偏與公主長得像暖眼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子纺裁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一.介紹 官網(wǎng) 分布式服務(wù)架構(gòu) 當(dāng)垂直應(yīng)用越來越多诫肠,應(yīng)用之間交互不可避免,將核心業(yè)務(wù)抽取出來欺缘,作為獨(dú)立的服務(wù)栋豫,逐漸...
    源來是你啊閱讀 305評論 0 0
  • 筆者初識Dubbo的時候,只知道它是一個RPC框架,那么什么是RPC呢浪南? 1. RPC是什么 維基百科是這么定義R...
    逍遙白亦閱讀 336評論 0 2
  • 一笼才、系統(tǒng)架構(gòu)演變首先說一下系統(tǒng)應(yīng)用的發(fā)展演化過程。也是我整個工作過程中經(jīng)歷的過程络凿。1.單機(jī)應(yīng)用特點(diǎn):當(dāng)網(wǎng)站流量很小...
    微子Lee閱讀 2,197評論 0 7
  • 內(nèi)容簡介此篇文章是介紹Dubbo以及它的簡單使用,會列舉運(yùn)用spring boot + dubbo搭建項目運(yùn)用du...
    Little_Dragon_閱讀 838評論 0 3
  • 1. Dubbo是什么昂羡? Dubbo是一個分布式服務(wù)框架絮记,致力于提供高性能和透明化的RPC遠(yuǎn)程服務(wù)調(diào)用方案,以及S...
    文渡閱讀 127評論 1 1