Dubbo——面试问题集(1~3)
1、默認(rèn)使用的是什么通信框架,還有別的選擇嗎?
Dubbo默認(rèn)使用netty,還支持mina, grizzy
配置方式:
<dubbo:protocol name=“dubbo” port=“9090” server=“netty” client=“netty” codec=“dubbo” serialization=“hessian2” charset=“UTF-8” threadpool=“fixed” threads=“100” queues=“0” iothreads=“9” buffer=“8192” accepts=“1000” payload=“8388608” />- Transporter: mina, netty, grizzy
- Serialization: dubbo, hessian2, java, json
- Dispatcher: all, direct, message, execution, connection
- ThreadPool: fixed, cached
Dubbo缺省協(xié)議采用單一長連接和NIO異步通訊,適合于小數(shù)據(jù)量大并發(fā)的服務(wù)調(diào)用,以及服務(wù)消費(fèi)者機(jī)器數(shù)遠(yuǎn)大于服務(wù)提供者機(jī)器數(shù)的情況。
Mina:
Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 組織一個較新的項(xiàng)目,它為開發(fā)高性能和高可用性的網(wǎng)絡(luò)應(yīng)用程序提供了非常便利的框架。當(dāng)前發(fā)行的 Mina 版本2.04支持基于 Java NIO 技術(shù)的 TCP/UDP 應(yīng)用程序開發(fā)、串口通訊程序,Mina 所支持的功能也在進(jìn)一步的擴(kuò)展中。目前,正在使用 Mina的應(yīng)用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、 Openfire等等。
Netty:
Netty是一款異步的事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用框架和工具,用于快速開發(fā)可維護(hù)的高性能、高擴(kuò)展性協(xié)議服務(wù)器和客戶端。也就是說,Netty是一個NIO客戶端/服務(wù)器框架,支持快速、簡單地開發(fā)網(wǎng)絡(luò)應(yīng)用,如協(xié)議服務(wù)器和客戶端。它極大簡化了網(wǎng)絡(luò)編程,如TCP和UDP套接字服務(wù)器。
Grizzly:
Grizzly是一種應(yīng)用程序框架,專門解決編寫成千上萬用戶訪問服務(wù)器時候產(chǎn)生的各種問題。使用JAVA NIO作為基礎(chǔ),并隱藏其編程的復(fù)雜性。容易使用的高性能的API。帶來非阻塞socketd到協(xié)議處理層。利用高性能的緩沖和緩沖管理使用高性能的線程池。
2、服務(wù)調(diào)用是阻塞的嗎?
Dubbo默認(rèn)為同步阻塞調(diào)用,但是也支持異步調(diào)用(有返回值、無返回值兩種)
異步無返回值:
所謂“無返回值”異步調(diào)用是指服務(wù)消費(fèi)方只管調(diào)用,但不關(guān)心調(diào)用結(jié)果,此時 Dubbo 會直接返回一個空的 RpcResult。若要使用異步特性,需要服務(wù)消費(fèi)方手動進(jìn)行配置。
異步有返回值:
返回一個Future
服務(wù)調(diào)用過程如下:
public class DubboInvoker<T> extends AbstractInvoker<T> {private final ExchangeClient[] clients;protected Result doInvoke(final Invocation invocation) throws Throwable {RpcInvocation inv = (RpcInvocation) invocation;final String methodName = RpcUtils.getMethodName(invocation);// 設(shè)置 path 和 version 到 attachment 中inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());inv.setAttachment(Constants.VERSION_KEY, version);ExchangeClient currentClient;if (clients.length == 1) {// 從 clients 數(shù)組中獲取 ExchangeClientcurrentClient = clients[0];} else {currentClient = clients[index.getAndIncrement() % clients.length];}try {// 獲取異步配置boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);// isOneway 為 true,表示“單向”通信boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);// 異步無返回值if (isOneway) {boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);// 發(fā)送請求currentClient.send(inv, isSent);// 設(shè)置上下文中的 future 字段為 nullRpcContext.getContext().setFuture(null);// 返回一個空的 RpcResultreturn new RpcResult();} // 異步有返回值else if (isAsync) {// 發(fā)送請求,并得到一個 ResponseFuture 實(shí)例ResponseFuture future = currentClient.request(inv, timeout);// 設(shè)置 future 到上下文中RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));// 暫時返回一個空結(jié)果return new RpcResult();} // 同步調(diào)用else {RpcContext.getContext().setFuture(null);// 發(fā)送請求,得到一個 ResponseFuture 實(shí)例,并調(diào)用該實(shí)例的 get 方法進(jìn)行等待return (Result) currentClient.request(inv, timeout).get();}} catch (TimeoutException e) {throw new RpcException(..., "Invoke remote method timeout....");} catch (RemotingException e) {throw new RpcException(..., "Failed to invoke remote method: ...");}}// 省略其他方法 }3、一般使用什么注冊中心?還有別的選擇嗎?
推薦使用zookeeper注冊中心,還有Multicast、Redis和Simple等。
3.1 zookeeper 注冊中心
Zookeeper 是 Apacahe Hadoop 的子項(xiàng)目,是一個樹型的目錄服務(wù),支持變更推送,適合作為 Dubbo 服務(wù)的注冊中心,工業(yè)強(qiáng)度較高,可用于生產(chǎn)環(huán)境,并推薦使用 [1]。
流程說明:
- 服務(wù)提供者啟動時: 向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的 URL 地址
- 服務(wù)消費(fèi)者啟動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 地址
- 監(jiān)控中心啟動時: 訂閱 /dubbo/com.foo.BarService 目錄下的所有提供者和消費(fèi)者 URL 地址。
支持以下功能:
- 當(dāng)提供者出現(xiàn)斷電等異常停機(jī)時,注冊中心能自動刪除提供者信息
- 當(dāng)注冊中心重啟時,能自動恢復(fù)注冊數(shù)據(jù),以及訂閱請求
- 當(dāng)會話過期時,能自動恢復(fù)注冊數(shù)據(jù),以及訂閱請求
- 當(dāng)設(shè)置 <dubbo:registry check=“false” /> 時,記錄失敗注冊和訂閱請求,后臺定時重試
- 可通過 <dubbo:registry username=“admin” password=“1234” /> 設(shè)置 zookeeper 登錄信息
- 可通過 <dubbo:registry group=“dubbo” /> 設(shè)置 zookeeper 的根節(jié)點(diǎn),不設(shè)置將使用無根樹
- 支持 * 號通配符 <dubbo:reference group="" version="" />,可訂閱服務(wù)的所有分組和所有版本的提供者
3.2 Multicast 注冊中心:
Multicast 注冊中心不需要啟動任何中心節(jié)點(diǎn),只要廣播地址一樣,就可以互相發(fā)現(xiàn)。
組播受網(wǎng)絡(luò)結(jié)構(gòu)限制,只適合小規(guī)模應(yīng)用或開發(fā)階段使用。組播地址段: 224.0.0.0 - 239.255.255.255
3.3 Redis 注冊中心
基于 Redis 實(shí)現(xiàn)的注冊中心。
使用 Redis 的 Key/Map 結(jié)構(gòu)存儲數(shù)據(jù)結(jié)構(gòu):
- 主 Key 為服務(wù)名和類型
- Map 中的 Key 為 URL 地址
- Map 中的 Value 為過期時間,用于判斷臟數(shù)據(jù),臟數(shù)據(jù)由監(jiān)控中心刪除 [3]
使用 Redis 的 Publish/Subscribe 事件通知數(shù)據(jù)變更:
- 通過事件的值區(qū)分事件類型:register, unregister, subscribe, unsubscribe
- 普通消費(fèi)者直接訂閱指定服務(wù)提供者的 Key,只會收到指定服務(wù)的 register, unregister 事件
- 監(jiān)控中心通過 psubscribe 功能訂閱 /dubbo/*,會收到所有服務(wù)的所有變更事件
調(diào)用過程:
服務(wù)提供方啟動時,向 Key:/dubbo/com.foo.BarService/providers 下,添加當(dāng)前提供者的地址
并向 Channel:/dubbo/com.foo.BarService/providers 發(fā)送 register 事件
服務(wù)消費(fèi)方啟動時,從 Channel:/dubbo/com.foo.BarService/providers 訂閱 register 和 unregister 事件
并向 Key:/dubbo/com.foo.BarService/consumers 下,添加當(dāng)前消費(fèi)者的地址
服務(wù)消費(fèi)方收到 register 和 unregister 事件后,從 Key:/dubbo/com.foo.BarService/providers 下獲取提供者地址列表
服務(wù)監(jiān)控中心啟動時,從 Channel:/dubbo/* 訂閱 register 和 unregister,以及 subscribe 和unsubsribe事件
服務(wù)監(jiān)控中心收到 register 和 unregister 事件后,從 Key:/dubbo/com.foo.BarService/providers 下獲取提供者地址列表
服務(wù)監(jiān)控中心收到 subscribe 和 unsubsribe 事件后,從 Key:/dubbo/com.foo.BarService/consumers 下獲取消費(fèi)者地址列表
可靠性聲明
阿里內(nèi)部并沒有采用 Redis 做為注冊中心,而是使用自己實(shí)現(xiàn)的基于數(shù)據(jù)庫的注冊中心,即:Redis 注冊中心并沒有在阿里內(nèi)部長時間運(yùn)行的可靠性保障,此 Redis 橋接實(shí)現(xiàn)只為開源版本提供,其可靠性依賴于 Redis 本身的可靠性。
3.4 Simple 注冊中心
Simple 注冊中心本身就是一個普通的 Dubbo 服務(wù),可以減少第三方依賴,使整體通訊方式一致。
配置
將 Simple 注冊中心暴露成 Dubbo 服務(wù):
引用 Simple Registry 服務(wù):
<dubbo:registry address="127.0.0.1:9090" />或者:
<dubbo:service interface="org.apache.dubbo.registry.RegistryService" group="simple" version="1.0.0" ... >或者:
<dubbo:registry address="127.0.0.1:9090" group="simple" version="1.0.0" />總結(jié)
以上是生活随笔為你收集整理的Dubbo——面试问题集(1~3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 银河麒麟操作系统日常测试
- 下一篇: Dubbo——面试问题集(4~14)