Dubbo面試題(總結(jié)最全面的面試題)
隨著服務(wù)化的進(jìn)一步發(fā)展,服務(wù)越來越多,服務(wù)之間的調(diào)用和依賴關(guān)系也越來越復(fù)雜,誕生了面向服務(wù)的架構(gòu)體系(SOA),也因此衍生出了一系列相應(yīng)的技術(shù),如對服務(wù)提供、服務(wù)調(diào)用、連接處理、通信協(xié)議、序列化方式、服務(wù)發(fā)現(xiàn)、服務(wù)路由、日志輸出等行為進(jìn)行封裝的服務(wù)框架。就這樣為分布式系統(tǒng)的服務(wù)治理框架就出現(xiàn)了,Dubbo 也就這樣產(chǎn)生了。
Dubbo 是什么?
Dubbo 是一款高性能、輕量級的開源 RPC 框架,提供服務(wù)自動注冊、自動發(fā)現(xiàn)等高效服務(wù)治理方案, 可以和 Spring 框架無縫集成。
Dubbo 的使用場景有哪些?
透明化的遠(yuǎn)程方法調(diào)用:就像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法,只需簡單配置,沒有任何API侵入。
軟負(fù)載均衡及容錯機(jī)制:可在內(nèi)網(wǎng)替代 F5 等硬件負(fù)載均衡器,降低成本,減少單點(diǎn)。
服務(wù)自動注冊與發(fā)現(xiàn):不再需要寫死服務(wù)提供方地址,注冊中心基于接口名查詢服務(wù)提供者的IP地址,并且能夠平滑添加或刪除服務(wù)提供者。
Dubbo 核心功能有哪些?
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ī)器。
Dubbo 核心組件有哪些?
Provider:暴露服務(wù)的服務(wù)提供方
Consumer:調(diào)用遠(yuǎn)程服務(wù)消費(fèi)方
Registry:服務(wù)注冊與發(fā)現(xiàn)注冊中心
Monitor:監(jiān)控中心和訪問調(diào)用統(tǒng)計
Container:服務(wù)運(yùn)行容器
Dubbo 服務(wù)器注冊與發(fā)現(xiàn)的流程?
服務(wù)容器Container負(fù)責(zé)啟動,加載,運(yùn)行服務(wù)提供者。
服務(wù)提供者Provider在啟動時,向注冊中心注冊自己提供的服務(wù)。
服務(wù)消費(fèi)者Consumer在啟動時,向注冊中心訂閱自己所需的服務(wù)。
注冊中心Registry返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費(fèi)者。
服務(wù)消費(fèi)者Consumer,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺調(diào)用。
服務(wù)消費(fèi)者Consumer和提供者Provider,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心Monitor。
架構(gòu)設(shè)計
Dubbo 的整體架構(gòu)設(shè)計有哪些分層?

接口服務(wù)層(Service):該層與業(yè)務(wù)邏輯相關(guān),根據(jù) provider 和 consumer 的業(yè)務(wù)設(shè)計對應(yīng)的接口和實(shí)現(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 Monitor 實(shí)現(xiàn)原理?
Consumer 端在發(fā)起調(diào)用之前會先走 filter 鏈;provider 端在接收到請求時也是先走 filter 鏈,然后才進(jìn)行真正的業(yè)務(wù)邏輯處理。默認(rèn)情況下,在 consumer 和 provider 的 filter 鏈中都會有 Monitorfilter。
MonitorFilter 向 DubboMonitor 發(fā)送數(shù)據(jù)
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
SimpleMonitorService 將這些聚合數(shù)據(jù)塞入 BlockingQueue queue 中(隊列大寫為 100000)
SimpleMonitorService 使用一個后臺線程(線程名為:DubboMonitorAsyncWriteLogThread)將 queue 中的數(shù)據(jù)寫入文件(該線程以死循環(huán)的形式來寫)
SimpleMonitorService 還會使用一個含有 1 個線程(線程名字:DubboMonitorTimer)的線程池每隔 5min 鐘,將文件中的統(tǒng)計數(shù)據(jù)畫成圖表
分布式框架
Dubbo 類似的分布式框架還有哪些?
比較著名的就是 Spring Cloud。
Dubbo 和 Spring Cloud 有什么關(guān)系?
Dubbo 是 SOA 時代的產(chǎn)物,它的關(guān)注點(diǎn)主要在于服務(wù)的調(diào)用,流量分發(fā)、流量監(jiān)控和熔斷。而 Spring Cloud 誕生于微服務(wù)架構(gòu)時代,考慮的是微服務(wù)治理的方方面面,另外由于依托了 Spring、Spring Boot 的優(yōu)勢之上,兩個框架在開始目標(biāo)就不一致,Dubbo 定位服務(wù)治理、Spring Cloud 是打造一個生態(tài)。
Dubbo 和 Spring Cloud 有什么哪些區(qū)別?
Dubbo 底層是使用 Netty 這樣的 NIO 框架,是基于 TCP 協(xié)議傳輸?shù)?,配合?Hession 序列化完成 RPC 通信。
Spring Cloud 是基于 Http 協(xié)議 Rest 接口調(diào)用遠(yuǎn)程過程的通信,相對來說 Http 請求會有更大的報文,占的帶寬也會更多。但是 REST 相比 RPC 更為靈活,服務(wù)提供方和調(diào)用方的依賴只依靠一紙契約,不存在代碼級別的強(qiáng)依賴,這在強(qiáng)調(diào)快速演化的微服務(wù)環(huán)境下,顯得更為合適,至于注重通信速度還是方便靈活性,具體情況具體考慮。
Dubbo 和 Dubbox 之間的區(qū)別?
Dubbox 是繼 Dubbo 停止維護(hù)后,當(dāng)當(dāng)網(wǎng)基于 Dubbo 做的一個擴(kuò)展項目,如加了服務(wù)可 Restful 調(diào)用,更新了開源組件等。
注冊中心
Dubbo 有哪些注冊中心?
Multicast 注冊中心:Multicast 注冊中心不需要任何中心節(jié)點(diǎn),只要廣播地址,就能進(jìn)行服務(wù)注冊和發(fā)現(xiàn),基于網(wǎng)絡(luò)中組播傳輸實(shí)現(xiàn)。
Zookeeper 注冊中心:基于分布式協(xié)調(diào)系統(tǒng) Zookeeper 實(shí)現(xiàn),采用 Zookeeper 的 watch 機(jī)制實(shí)現(xiàn)數(shù)據(jù)變更。
Redis 注冊中心:基于 Redis 實(shí)現(xiàn),采用 key/map 存儲,key 存儲服務(wù)名和類型,map 中 key 存儲服務(wù) url,value 服務(wù)過期時間?;?Redis 的發(fā)布/訂閱模式通知數(shù)據(jù)變更。
Simple 注冊中心。
推薦使用 Zookeeper 作為注冊中心
Dubbo 的注冊中心集群掛掉,發(fā)布者和訂閱者之間還能通信么?
可以通訊。啟動 Dubbo 時,消費(fèi)者會從 Zookeeper 拉取注冊的生產(chǎn)者的地址接口等數(shù)據(jù),緩存在本地。每次調(diào)用時,按照本地存儲的地址進(jìn)行調(diào)用。
集群
Dubbo集群提供了哪些負(fù)載均衡策略?
Random LoadBalance: 隨機(jī)選取提供者策略,有利于動態(tài)調(diào)整提供者權(quán)重。截面碰撞率高,調(diào)用次數(shù)越多,分布越均勻。
RoundRobin LoadBalance: 輪循選取提供者策略,平均分布,但是存在請求累積的問題。
LeastActive LoadBalance: 最少活躍調(diào)用策略,解決慢提供者接收更少的請求。
ConstantHash LoadBalance: 一致性 Hash 策略,使相同參數(shù)請求總是發(fā)到同一提供者,一臺機(jī)器宕機(jī),可以基于虛擬節(jié)點(diǎn),分?jǐn)傊疗渌峁┱?,避免引起提供者的劇烈變動?/span>
默認(rèn)為 Random 隨機(jī)調(diào)用。
Dubbo的集群容錯方案有哪些?
Failover Cluster:失敗自動切換,當(dāng)出現(xiàn)失敗,重試其它服務(wù)器。通常用于讀操作,但重試會帶來更長延遲。
Failfast Cluster:快速失敗,只發(fā)起一次調(diào)用,失敗立即報錯。通常用于非冪等性的寫操作,比如新增記錄。
Failsafe Cluster:失敗安全,出現(xiàn)異常時,直接忽略。通常用于寫入審計日志等操作。
Failback Cluster:失敗自動恢復(fù),后臺記錄失敗請求,定時重發(fā)。通常用于消息通知操作。
Forking Cluster:并行調(diào)用多個服務(wù)器,只要一個成功即返回。通常用于實(shí)時性要求較高的讀操作,但需要浪費(fèi)更多服務(wù)資源。可通過 forks=”2″ 來設(shè)置最大并行數(shù)。
Broadcast Cluster:廣播調(diào)用所有提供者,逐個調(diào)用,任意一臺報錯則報錯 。通常用于通知所有提供者更新緩存或日志等本地資源信息。
默認(rèn)的容錯方案是 Failover Cluster。
配置
Dubbo 配置文件是如何加載到 Spring 中的?
Spring 容器在啟動的時候,會讀取到 Spring 默認(rèn)的一些 schema 以及 Dubbo 自定義的 schema,每個 schema 都會對應(yīng)一個自己的 NamespaceHandler,NamespaceHandler 里面通過 BeanDefinitionParser 來解析配置信息并轉(zhuǎn)化為需要加載的 bean 對象!
說說核心的配置有哪些?
| 標(biāo)簽 | 用途 | 解釋 |
|---|---|---|
| <dubbo:service/> | 服務(wù)配置 | 用于暴露一個服務(wù),定義服務(wù)的元信息,一個服務(wù)可以用多個協(xié)議暴露,一個服務(wù)也可以注冊到多個注冊中心 |
| <dubbo:reference/> | 引用配置 | 用于創(chuàng)建一個遠(yuǎn)程服務(wù)代理,一個引用可以指向多個注冊中心 |
| <dubbo:protocol/> | 協(xié)議配置 | 用于配置提供服務(wù)的協(xié)議信息,協(xié)議由提供方指定,消費(fèi)方被動接受 |
| <dubbo:application/> | 應(yīng)用配置 | 用于配置當(dāng)前應(yīng)用信息,不管該應(yīng)用是提供者還是消費(fèi)者 |
| <dubbo:module/> | 模塊配置 | 用于配置當(dāng)前模塊信息,可選 |
| <dubbo:registry/> | 注冊中心配置 | 用于配置連接注冊中心相關(guān)信息 |
| <dubbo:monitor/> | 監(jiān)控中心配置 | 用于配置連接監(jiān)控中心相關(guān)信息,可選 |
| <dubbo:provider/> | 提供方配置 | 當(dāng) ProtocolConfig 和 ServiceConfig 某屬性沒有配置時,采用此缺省值,可選 |
| <dubbo:consumer/> | 消費(fèi)方配置 | 當(dāng) ReferenceConfig 某屬性沒有配置時,采用此缺省值,可選 |
| <dubbo:method/> | 方法配置 | 用于 ServiceConfig 和 ReferenceConfig 指定方法級的配置信息 |
| <dubbo:argument> | 參數(shù)配置 | 用于指定方法參數(shù)配置 |
如果是SpringBoot項目就只需要注解,或者開Application配置文件!??!
Dubbo 超時設(shè)置有哪些方式?
Dubbo 超時設(shè)置有兩種方式:
服務(wù)提供者端設(shè)置超時時間,在Dubbo的用戶文檔中,推薦如果能在服務(wù)端多配置就盡量多配置,因?yàn)榉?wù)提供者比消費(fèi)者更清楚自己提供的服務(wù)特性。
服務(wù)消費(fèi)者端設(shè)置超時時間,如果在消費(fèi)者端設(shè)置了超時時間,以消費(fèi)者端為主,即優(yōu)先級更高。因?yàn)榉?wù)調(diào)用方設(shè)置超時時間控制性更靈活。如果消費(fèi)方超時,服務(wù)端線程不會定制,會產(chǎn)生警告。
服務(wù)調(diào)用超時會怎么樣?
dubbo 在調(diào)用服務(wù)不成功時,默認(rèn)是會重試兩次。
通信協(xié)議
Dubbo 使用的是什么通信框架?
默認(rèn)使用 Netty 作為通訊框架。
Dubbo 支持哪些協(xié)議,它們的優(yōu)缺點(diǎn)有哪些?
Dubbo:單一長連接和 NIO 異步通訊,適合大并發(fā)小數(shù)據(jù)量的服務(wù)調(diào)用,以及消費(fèi)者遠(yuǎn)大于提供者。傳輸協(xié)議 TCP,異步 Hessian 序列化。Dubbo推薦使用dubbo協(xié)議。
RMI:采用 JDK 標(biāo)準(zhǔn)的 RMI 協(xié)議實(shí)現(xiàn),傳輸參數(shù)和返回參數(shù)對象需要實(shí)現(xiàn) Serializable 接口,使用 Java 標(biāo)準(zhǔn)序列化機(jī)制,使用阻塞式短連接,傳輸數(shù)據(jù)包大小混合,消費(fèi)者和提供者個數(shù)差不多,可傳文件,傳輸協(xié)議 TCP。多個短連接 TCP 協(xié)議傳輸,同步傳輸,適用常規(guī)的遠(yuǎn)程服務(wù)調(diào)用和 RMI 互操作。在依賴低版本的 Common-Collections 包,Java 序列化存在安全漏洞。
WebService:基于 WebService 的遠(yuǎn)程調(diào)用協(xié)議,集成 CXF 實(shí)現(xiàn),提供和原生 WebService 的互操作。多個短連接,基于 HTTP 傳輸,同步傳輸,適用系統(tǒng)集成和跨語言調(diào)用。
HTTP:基于 Http 表單提交的遠(yuǎn)程調(diào)用協(xié)議,使用 Spring 的 HttpInvoke 實(shí)現(xiàn)。多個短連接,傳輸協(xié)議 HTTP,傳入?yún)?shù)大小混合,提供者個數(shù)多于消費(fèi)者,需要給應(yīng)用程序和瀏覽器 JS 調(diào)用。
Hessian:集成 Hessian 服務(wù),基于 HTTP 通訊,采用 Servlet 暴露服務(wù),Dubbo 內(nèi)嵌 Jetty 作為服務(wù)器時默認(rèn)實(shí)現(xiàn),提供與 Hession 服務(wù)互操作。多個短連接,同步 HTTP 傳輸,Hessian 序列化,傳入?yún)?shù)較大,提供者大于消費(fèi)者,提供者壓力較大,可傳文件。
Memcache:基于 Memcache實(shí)現(xiàn)的 RPC 協(xié)議。
Redis:基于 Redis 實(shí)現(xiàn)的RPC協(xié)議。
設(shè)計模式
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();
復(fù)制代碼工廠模式
Provider 在 export 服務(wù)時,會調(diào)用 ServiceConfig 的 export 方法。ServiceConfig中有個字段:
private static final Protocol protocol =
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtensi
on();
復(fù)制代碼Dubbo 里有很多這種代碼。這也是一種工廠模式,只是實(shí)現(xiàn)類的獲取采用了 JDKSPI 的機(jī)制。這么實(shí)現(xiàn)的優(yōu)點(diǎn)是可擴(kuò)展性強(qiáng),想要擴(kuò)展實(shí)現(xiàn),只需要在 classpath下增加個文件就可以了,代碼零侵入。另外,像上面的 Adaptive 實(shí)現(xiàn),可以做到調(diào)用時動態(tài)決定調(diào)用哪個實(shí)現(xiàn),但是由于這種實(shí)現(xiàn)采用了動態(tài)代理,會造成代碼調(diào)試比較麻煩,需要分析出實(shí)際調(diào)用的實(shí)現(xiàn)類。
裝飾器模式
Dubbo 在啟動和調(diào)用階段都大量使用了裝飾器模式。以 Provider 提供的調(diào)用鏈為例,具體的調(diào)用鏈代碼是在 ProtocolFilterWrapper 的 buildInvokerChain 完成的,具體是將注解中含有 group=provider 的 Filter 實(shí)現(xiàn),按照 order 排序,最后的調(diào)用順序是:
EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter ->
ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter ->
ExceptionFilter
復(fù)制代碼更確切地說,這里是裝飾器和責(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 實(shí)現(xiàn)是典型的動態(tài)代理實(shí)現(xiàn)。Dubbo 需要靈活地控制實(shí)現(xiàn)類,即在調(diào)用階段動態(tài)地根據(jù)參數(shù)決定調(diào)用哪個實(shí)現(xiàn)類,所以采用先生成代理類的方法,能夠做到靈活的調(diào)用。生成代理類的代碼是 ExtensionLoader 的 createAdaptiveExtensionClassCode 方法。代理類主要邏輯是,獲取 URL 參數(shù)中指定參數(shù)的值作為獲取實(shí)現(xiàn)類的 key。
運(yùn)維管理
服務(wù)上線怎么兼容舊版本?
可以用版本號(version)過渡,多個不同版本的服務(wù)注冊到注冊中心,版本號不同的服務(wù)相互間不引用。這個和服務(wù)分組的概念有一點(diǎn)類似。
Dubbo telnet 命令能做什么?
dubbo 服務(wù)發(fā)布之后,我們可以利用 telnet 命令進(jìn)行調(diào)試、管理。Dubbo2.0.5 以上版本服務(wù)提供端口支持 telnet 命令
Dubbo 支持服務(wù)降級嗎?
以通過 dubbo:reference 中設(shè)置 mock=“return null”。mock 的值也可以修改為 true,然后再跟接口同一個路徑下實(shí)現(xiàn)一個 Mock 類,命名規(guī)則是 “接口名稱+Mock” 后綴。然后在 Mock 類里實(shí)現(xiàn)自己的降級邏輯
Dubbo 如何優(yōu)雅停機(jī)?
Dubbo 是通過 JDK 的 ShutdownHook 來完成優(yōu)雅停機(jī)的,所以如果使用kill -9 PID 等強(qiáng)制關(guān)閉指令,是不會執(zhí)行優(yōu)雅停機(jī)的,只有通過 kill PID 時,才會執(zhí)行。
SPI
Dubbo SPI 和 Java SPI 區(qū)別?
JDK SPI:
JDK 標(biāo)準(zhǔn)的 SPI 會一次性加載所有的擴(kuò)展實(shí)現(xiàn),如果有的擴(kuò)展很耗時,但也沒用上,很浪費(fèi)資源。所以只希望加載某個的實(shí)現(xiàn),就不現(xiàn)實(shí)了
DUBBO SPI:
1、對 Dubbo 進(jìn)行擴(kuò)展,不需要改動 Dubbo 的源碼
2、延遲加載,可以一次只加載自己想要加載的擴(kuò)展實(shí)現(xiàn)。
3、增加了對擴(kuò)展點(diǎn) IOC 和 AOP 的支持,一個擴(kuò)展點(diǎn)可以直接 setter 注入其它擴(kuò)展點(diǎn)。
4、Dubbo 的擴(kuò)展機(jī)制能很好的支持第三方 IoC 容器,默認(rèn)支持 Spring Bean。
其他
Dubbo 支持分布式事務(wù)嗎?
目前暫時不支持,可與通過 tcc-transaction 框架實(shí)現(xiàn)
介紹:tcc-transaction 是開源的 TCC 補(bǔ)償性分布式事務(wù)框架
TCC-Transaction 通過 Dubbo 隱式傳參的功能,避免自己對業(yè)務(wù)代碼的入侵。
Dubbo 可以對結(jié)果進(jìn)行緩存嗎?
為了提高數(shù)據(jù)訪問的速度。Dubbo 提供了聲明式緩存,以減少用戶加緩存的工作量<dubbo:reference cache=“true” />
其實(shí)比普通的配置文件就多了一個標(biāo)簽 cache=“true”
Dubbo 必須依賴的包有哪些?
Dubbo 必須依賴 JDK,其他為可選。
Dubbo 支持哪些序列化方式?
默認(rèn)使用 Hessian 序列化,還有 Duddo、FastJson、Java 自帶序列化。
Dubbo 在安全方面有哪些措施?
Dubbo 通過 Token 令牌防止用戶繞過注冊中心直連,然后在注冊中心上管理授權(quán)。
Dubbo 還提供服務(wù)黑白名單,來控制服務(wù)所允許的調(diào)用方。
服務(wù)調(diào)用是阻塞的嗎?
默認(rèn)是阻塞的,可以異步調(diào)用,沒有返回值的可以這么做。Dubbo 是基于 NIO 的非阻塞實(shí)現(xiàn)并行調(diào)用,客戶端不需要啟動多線程即可完成并行調(diào)用多個遠(yuǎn)程服務(wù),相對多線程開銷較小,異步調(diào)用會返回一個 Future 對象。
服務(wù)提供者能實(shí)現(xiàn)失效踢出是什么原理?
服務(wù)失效踢出基于 zookeeper 的臨時節(jié)點(diǎn)原理。
同一個服務(wù)多個注冊的情況下可以直連某一個服務(wù)嗎?
可以點(diǎn)對點(diǎn)直連,修改配置即可,也可以通過 telnet 直接某個服務(wù)。
Dubbo 服務(wù)降級,失敗重試怎么做?
可以通過 dubbo:reference 中設(shè)置 mock=“return null”。mock 的值也可以修改為 true,然后再跟接口同一個路徑下實(shí)現(xiàn)一個 Mock 類,命名規(guī)則是 “接口名稱+Mock” 后綴。然后在 Mock 類里實(shí)現(xiàn)自己的降級邏輯
Dubbo 使用過程中都遇到了些什么問題?
在注冊中心找不到對應(yīng)的服務(wù),檢查 service 實(shí)現(xiàn)類是否添加了@service 注解無法連接到注冊中心,檢查配置文件中的對應(yīng)的測試 ip 是否正確
RPC
為什么要有RPC
http接口是在接口不多、系統(tǒng)與系統(tǒng)交互較少的情況下,解決信息孤島初期常使用的一種通信手段;優(yōu)點(diǎn)就是簡單、直接、開發(fā)方便。利用現(xiàn)成的http協(xié)議進(jìn)行傳輸。但是如果是一個大型的網(wǎng)站,內(nèi)部子系統(tǒng)較多、接口非常多的情況下,RPC框架的好處就顯示出來了,首先就是長鏈接,不必每次通信都要像http一樣去3次握手什么的,減少了網(wǎng)絡(luò)開銷;其次就是RPC框架一般都有注冊中心,有豐富的監(jiān)控管理;發(fā)布、下線接口、動態(tài)擴(kuò)展等,對調(diào)用方來說是無感知、統(tǒng)一化的操作。第三個來說就是安全性。最后就是最近流行的服務(wù)化架構(gòu)、服務(wù)化治理,RPC框架是一個強(qiáng)力的支撐。
socket只是一個簡單的網(wǎng)絡(luò)通信方式,只是創(chuàng)建通信雙方的通信通道,而要實(shí)現(xiàn)rpc的功能,還需要對其進(jìn)行封裝,以實(shí)現(xiàn)更多的功能。
RPC一般配合netty框架、spring自定義注解來編寫輕量級框架,其實(shí)netty內(nèi)部是封裝了socket的,較新的jdk的IO一般是NIO,即非阻塞IO,在高并發(fā)網(wǎng)站中,RPC的優(yōu)勢會很明顯
什么是RPC
RPC(Remote Procedure Call Protocol)遠(yuǎn)程過程調(diào)用協(xié)議,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計算機(jī)程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。簡言之,RPC使得程序能夠像訪問本地系統(tǒng)資源一樣,去訪問遠(yuǎn)端系統(tǒng)資源。比較關(guān)鍵的一些方面包括:通訊協(xié)議、序列化、資源(接口)描述、服務(wù)框架、性能、語言支持等。

簡單的說,RPC就是從一臺機(jī)器(客戶端)上通過參數(shù)傳遞的方式調(diào)用另一臺機(jī)器(服務(wù)器)上的一個函數(shù)或方法(可以統(tǒng)稱為服務(wù))并得到返回的結(jié)果。
PRC架構(gòu)組件
一個基本的RPC架構(gòu)里面應(yīng)該至少包含以下4個組件:
1、客戶端(Client):服務(wù)調(diào)用方(服務(wù)消費(fèi)者)
2、客戶端存根(Client Stub):存放服務(wù)端地址信息,將客戶端的請求參數(shù)數(shù)據(jù)信息打包成網(wǎng)絡(luò)消息,再通過網(wǎng)絡(luò)傳輸發(fā)送給服務(wù)端
3、服務(wù)端存根(Server Stub):接收客戶端發(fā)送過來的請求消息并進(jìn)行解包,然后再調(diào)用本地服務(wù)進(jìn)行處理4、服務(wù)端(Server):服務(wù)的真正提供者

具體調(diào)用過程:
1、服務(wù)消費(fèi)者(client客戶端)通過調(diào)用本地服務(wù)的方式調(diào)用需要消費(fèi)的服務(wù);
2、客戶端存根(client stub)接收到調(diào)用請求后負(fù)責(zé)將方法、入?yún)⒌刃畔⑿蛄谢ńM裝)成能夠進(jìn)行網(wǎng)絡(luò)傳輸?shù)南Ⅲw;
3、客戶端存根(client stub)找到遠(yuǎn)程的服務(wù)地址,并且將消息通過網(wǎng)絡(luò)發(fā)送給服務(wù)端;
4、服務(wù)端存根(server stub)收到消息后進(jìn)行解碼(反序列化操作);
5、服務(wù)端存根(server stub)根據(jù)解碼結(jié)果調(diào)用本地的服務(wù)進(jìn)行相關(guān)處理;
6、本地服務(wù)執(zhí)行具體業(yè)務(wù)邏輯并將處理結(jié)果返回給服務(wù)端存根(server stub);
7、服務(wù)端存根(server stub)將返回結(jié)果重新打包成消息(序列化)并通過網(wǎng)絡(luò)發(fā)送至消費(fèi)方;
8、客戶端存根(client stub)接收到消息,并進(jìn)行解碼(反序列化);
9、服務(wù)消費(fèi)方得到最終結(jié)果;
而RPC框架的實(shí)現(xiàn)目標(biāo)則是將上面的第2-10步完好地封裝起來,也就是把調(diào)用、編碼/解碼的過程給封裝起來,讓用戶感覺上像調(diào)用本地服務(wù)一樣的調(diào)用遠(yuǎn)程服務(wù)。
RPC和SOA、SOAP、REST的區(qū)別
1、REST
可以看著是HTTP協(xié)議的一種直接應(yīng)用,默認(rèn)基于JSON作為傳輸格式,使用簡單,學(xué)習(xí)成本低效率高,但是安全性較低。
2、SOAP
SOAP是一種數(shù)據(jù)交換協(xié)議規(guī)范,是一種輕量的、簡單的、基于XML的協(xié)議的規(guī)范。而SOAP可以看著是一個重量級的協(xié)議,基于XML、SOAP在安全方面是通過使用XML-Security和XML-Signature兩個規(guī)范組成了WS-Security來實(shí)現(xiàn)安全控制的,當(dāng)前已經(jīng)得到了各個廠商的支持 。
它有什么優(yōu)點(diǎn)?簡單總結(jié)為:易用、靈活、跨語言、跨平臺。
3、SOA
面向服務(wù)架構(gòu),它可以根據(jù)需求通過網(wǎng)絡(luò)對松散耦合的粗粒度應(yīng)用組件進(jìn)行分布式部署、組合和使用。服務(wù)層是SOA的基礎(chǔ),可以直接被應(yīng)用調(diào)用,從而有效控制系統(tǒng)中與軟件代理交互的人為依賴性。
SOA是一種粗粒度、松耦合服務(wù)架構(gòu),服務(wù)之間通過簡單、精確定義接口進(jìn)行通訊,不涉及底層編程接口和通訊模型。SOA可以看作是B/S模型、XML(標(biāo)準(zhǔn)通用標(biāo)記語言的子集)/Web Service技術(shù)之后的自然延伸。
4、REST 和 SOAP、RPC 有何區(qū)別呢?
沒什么太大區(qū)別,他們的本質(zhì)都是提供可支持分布式的基礎(chǔ)服務(wù),最大的區(qū)別在于他們各自的的特點(diǎn)所帶來的不同應(yīng)用場景 。
RPC框架需要解決的問題?
1、如何確定客戶端和服務(wù)端之間的通信協(xié)議?
2、如何更高效地進(jìn)行網(wǎng)絡(luò)通信?
3、服務(wù)端提供的服務(wù)如何暴露給客戶端?
4、客戶端如何發(fā)現(xiàn)這些暴露的服務(wù)?
5、如何更高效地對請求對象和響應(yīng)結(jié)果進(jìn)行序列化和反序列化操作?
RPC的實(shí)現(xiàn)基礎(chǔ)?
1、需要有非常高效的網(wǎng)絡(luò)通信,比如一般選擇Netty作為網(wǎng)絡(luò)通信框架;
2、需要有比較高效的序列化框架,比如谷歌的Protobuf序列化框架;
3、可靠的尋址方式(主要是提供服務(wù)的發(fā)現(xiàn)),比如可以使用Zookeeper來注冊服務(wù)等等;
4、如果是帶會話(狀態(tài))的RPC調(diào)用,還需要有會話和狀態(tài)保持的功能;
RPC使用了哪些關(guān)鍵技術(shù)?
1、動態(tài)代理
生成Client Stub(客戶端存根)和Server Stub(服務(wù)端存根)的時候需要用到Java動態(tài)代理技術(shù),可以使用JDK提供的原生的動態(tài)代理機(jī)制,也可以使用開源的:CGLib代理,Javassist字節(jié)碼生成技術(shù)。
2、序列化和反序列化
在網(wǎng)絡(luò)中,所有的數(shù)據(jù)都將會被轉(zhuǎn)化為字節(jié)進(jìn)行傳送,所以為了能夠使參數(shù)對象在網(wǎng)絡(luò)中進(jìn)行傳輸,需要對這些參數(shù)進(jìn)行序列化和反序列化操作。
序列化:把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化,也就是編碼的過程。反序列化:把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化,也就是解碼的過程。目前比較高效的開源序列化框架:如Kryo、FastJson和Protobuf等。
反序列化:把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化,也就是解碼的過程。目前比較高效的開源序列化框架:如Kryo、FastJson和Protobuf等。
3、NIO通信
出于并發(fā)性能的考慮,傳統(tǒng)的阻塞式 IO 顯然不太合適,因此我們需要異步的 IO,即 NIO。Java 提供了 NIO 的解決方案,Java 7 也提供了更優(yōu)秀的 NIO.2 支持??梢赃x擇Netty或者M(jìn)INA來解決NIO數(shù)據(jù)傳輸?shù)膯栴}。
4、服務(wù)注冊中心
可選:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服務(wù)注冊與發(fā)現(xiàn)功能,解決單點(diǎn)故障以及分布式部署的問題(注冊中心)。
主流RPC框架有哪些
1、RMI
利用java.rmi包實(shí)現(xiàn),基于Java遠(yuǎn)程方法協(xié)議(Java Remote Method Protocol) 和java的原生序列化。
2、Hessian
是一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能?;贖TTP協(xié)議,采用二進(jìn)制編解碼。
3、protobuf-rpc-pro
是一個Java類庫,提供了基于 Google 的 Protocol Buffers 協(xié)議的遠(yuǎn)程方法調(diào)用的框架?;?Netty 底層的 NIO 技術(shù)。支持 TCP 重用/ keep-alive、SSL加密、RPC 調(diào)用取消操作、嵌入式日志等功能。
4、Thrift
是一種可伸縮的跨語言服務(wù)的軟件框架。它擁有功能強(qiáng)大的代碼生成引擎,無縫地支持C + +,C#,Java,Python和PHP和Ruby。thrift允許你定義一個描述文件,描述數(shù)據(jù)類型和服務(wù)接口。依據(jù)該文件,編譯器方便地生成RPC客戶端和服務(wù)器通信代碼。
最初由facebook開發(fā)用做系統(tǒng)內(nèi)個語言之間的RPC通信,2007年由facebook貢獻(xiàn)到apache基金 ,現(xiàn)在是apache下的opensource之一 。支持多種語言之間的RPC方式的通信:php語言client可以構(gòu)造一個對象,調(diào)用相應(yīng)的服務(wù)方法來調(diào)用java語言的服務(wù),跨越語言的C/S RPC調(diào)用。底層通訊基于SOCKET。
5、Avro
出自Hadoop之父Doug Cutting, 在Thrift已經(jīng)相當(dāng)流行的情況下推出Avro的目標(biāo)不僅是提供一套類似Thrift的通訊中間件,更是要建立一個新的,標(biāo)準(zhǔn)性的云計算的數(shù)據(jù)交換和存儲的Protocol。支持HTTP,TCP兩種協(xié)議。
6、Dubbo
Dubbo是 阿里巴巴公司開源的一個高性能優(yōu)秀的服務(wù)框架,使得應(yīng)用可通過高性能的 RPC 實(shí)現(xiàn)服務(wù)的輸出和輸入功能,可以和 Spring框架無縫集成。
RPC的實(shí)現(xiàn)原理架構(gòu)圖

也就是說兩臺服務(wù)器A,B,一個應(yīng)用部署在A服務(wù)器上,想要調(diào)用B服務(wù)器上應(yīng)用提供的函數(shù)/方法,由于不在一個內(nèi)存空間,不能直接調(diào)用,需要通過網(wǎng)絡(luò)來表達(dá)調(diào)用的語義和傳達(dá)調(diào)用的數(shù)據(jù)。
比如說,A服務(wù)器想調(diào)用B服務(wù)器上的一個方法:
1、建立通信
首先要解決通訊的問題:即A機(jī)器想要調(diào)用B機(jī)器,首先得建立起通信連接。
主要是通過在客戶端和服務(wù)器之間建立TCP連接,遠(yuǎn)程過程調(diào)用的所有交換的數(shù)據(jù)都在這個連接里傳輸。連接可以是按需連接,調(diào)用結(jié)束后就斷掉,也可以是長連接,多個遠(yuǎn)程過程調(diào)用共享同一個連接。
通常這個連接可以是按需連接(需要調(diào)用的時候就先建立連接,調(diào)用結(jié)束后就立馬斷掉),也可以是長連接(客戶端和服務(wù)器建立起連接之后保持長期持有,不管此時有無數(shù)據(jù)包的發(fā)送,可以配合心跳檢測機(jī)制定期檢測建立的連接是否存活有效),多個遠(yuǎn)程過程調(diào)用共享同一個連接。
2、服務(wù)尋址
要解決尋址的問題,也就是說,A服務(wù)器上的應(yīng)用怎么告訴底層的RPC框架,如何連接到B服務(wù)器(如主機(jī)或IP地址)以及特定的端口,方法的名稱名稱是什么。
通常情況下我們需要提供B機(jī)器(主機(jī)名或IP地址)以及特定的端口,然后指定調(diào)用的方法或者函數(shù)的名稱以及入?yún)⒊鰠⒌刃畔ⅲ@樣才能完成服務(wù)的一個調(diào)用。
可靠的尋址方式(主要是提供服務(wù)的發(fā)現(xiàn))是RPC的實(shí)現(xiàn)基石,比如可以采用Redis或者Zookeeper來注冊服務(wù)等等。
2.1、從服務(wù)提供者的角度看:
當(dāng)服務(wù)提供者啟動的時候,需要將自己提供的服務(wù)注冊到指定的注冊中心,以便服務(wù)消費(fèi)者能夠通過服務(wù)注冊中心進(jìn)行查找;
當(dāng)服務(wù)提供者由于各種原因致使提供的服務(wù)停止時,需要向注冊中心注銷停止的服務(wù);
服務(wù)的提供者需要定期向服務(wù)注冊中心發(fā)送心跳檢測,服務(wù)注冊中心如果一段時間未收到來自服務(wù)提供者的心跳后,認(rèn)為該服務(wù)提供者已經(jīng)停止服務(wù),則將該服務(wù)從注冊中心上去掉。
2.2、從調(diào)用者的角度看:
服務(wù)的調(diào)用者啟動的時候根據(jù)自己訂閱的服務(wù)向服務(wù)注冊中心查找服務(wù)提供者的地址等信息;
當(dāng)服務(wù)調(diào)用者消費(fèi)的服務(wù)上線或者下線的時候,注冊中心會告知該服務(wù)的調(diào)用者;
服務(wù)調(diào)用者下線的時候,則取消訂閱。
3、網(wǎng)絡(luò)傳輸
3.1、序列化
當(dāng)A機(jī)器上的應(yīng)用發(fā)起一個RPC調(diào)用時,調(diào)用方法和其入?yún)⒌刃畔⑿枰ㄟ^底層的網(wǎng)絡(luò)協(xié)議如TCP傳輸?shù)紹機(jī)器,由于網(wǎng)絡(luò)協(xié)議是基于二進(jìn)制的,所有我們傳輸?shù)膮?shù)數(shù)據(jù)都需要先進(jìn)行序列化(Serialize)或者編組(marshal)成二進(jìn)制的形式才能在網(wǎng)絡(luò)中進(jìn)行傳輸。然后通過尋址操作和網(wǎng)絡(luò)傳輸將序列化或者編組之后的二進(jìn)制數(shù)據(jù)發(fā)送給B機(jī)器。
3.2、反序列化
當(dāng)B機(jī)器接收到A機(jī)器的應(yīng)用發(fā)來的請求之后,又需要對接收到的參數(shù)等信息進(jìn)行反序列化操作(序列化的逆操作),即將二進(jìn)制信息恢復(fù)為內(nèi)存中的表達(dá)方式,然后再找到對應(yīng)的方法(尋址的一部分)進(jìn)行本地調(diào)用(一般是通過生成代理Proxy去調(diào)用, 通常會有JDK動態(tài)代理、CGLIB動態(tài)代理、Javassist生成字節(jié)碼技術(shù)等),之后得到調(diào)用的返回值。
4、服務(wù)調(diào)用
B機(jī)器進(jìn)行本地調(diào)用(通過代理Proxy和反射調(diào)用)之后得到了返回值,此時還需要再把返回值發(fā)送回A機(jī)器,同樣也需要經(jīng)過序列化操作,然后再經(jīng)過網(wǎng)絡(luò)傳輸將二進(jìn)制數(shù)據(jù)發(fā)送回A機(jī)器,而當(dāng)A機(jī)器接收到這些返回值之后,則再次進(jìn)行反序列化操作,恢復(fù)為內(nèi)存中的表達(dá)方式,最后再交給A機(jī)器上的應(yīng)用進(jìn)行相關(guān)處理(一般是業(yè)務(wù)邏輯處理操作)。
通常,經(jīng)過以上四個步驟之后,一次完整的RPC調(diào)用算是完成了,另外可能因?yàn)榫W(wǎng)絡(luò)抖動等原因需要重試等。
來源:https://juejin.cn/post/6844904127076499463
推薦閱讀:
世界的真實(shí)格局分析,地球人類社會底層運(yùn)行原理
不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設(shè)PPT)
企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案
論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?
企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!
【中臺實(shí)踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf
華為如何實(shí)施數(shù)字化轉(zhuǎn)型(附PPT)
