Dubbo——面试问题集(1~3)
1、默認使用的是什么通信框架,還有別的選擇嗎?
Dubbo默認使用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缺省協議采用單一長連接和NIO異步通訊,適合于小數據量大并發的服務調用,以及服務消費者機器數遠大于服務提供者機器數的情況。
Mina:
Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 組織一個較新的項目,它為開發高性能和高可用性的網絡應用程序提供了非常便利的框架。當前發行的 Mina 版本2.04支持基于 Java NIO 技術的 TCP/UDP 應用程序開發、串口通訊程序,Mina 所支持的功能也在進一步的擴展中。目前,正在使用 Mina的應用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、 Openfire等等。
Netty:
Netty是一款異步的事件驅動的網絡應用框架和工具,用于快速開發可維護的高性能、高擴展性協議服務器和客戶端。也就是說,Netty是一個NIO客戶端/服務器框架,支持快速、簡單地開發網絡應用,如協議服務器和客戶端。它極大簡化了網絡編程,如TCP和UDP套接字服務器。
Grizzly:
Grizzly是一種應用程序框架,專門解決編寫成千上萬用戶訪問服務器時候產生的各種問題。使用JAVA NIO作為基礎,并隱藏其編程的復雜性。容易使用的高性能的API。帶來非阻塞socketd到協議處理層。利用高性能的緩沖和緩沖管理使用高性能的線程池。
2、服務調用是阻塞的嗎?
Dubbo默認為同步阻塞調用,但是也支持異步調用(有返回值、無返回值兩種)
異步無返回值:
所謂“無返回值”異步調用是指服務消費方只管調用,但不關心調用結果,此時 Dubbo 會直接返回一個空的 RpcResult。若要使用異步特性,需要服務消費方手動進行配置。
異步有返回值:
返回一個Future
服務調用過程如下:
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);// 設置 path 和 version 到 attachment 中inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());inv.setAttachment(Constants.VERSION_KEY, version);ExchangeClient currentClient;if (clients.length == 1) {// 從 clients 數組中獲取 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);// 發送請求currentClient.send(inv, isSent);// 設置上下文中的 future 字段為 nullRpcContext.getContext().setFuture(null);// 返回一個空的 RpcResultreturn new RpcResult();} // 異步有返回值else if (isAsync) {// 發送請求,并得到一個 ResponseFuture 實例ResponseFuture future = currentClient.request(inv, timeout);// 設置 future 到上下文中RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));// 暫時返回一個空結果return new RpcResult();} // 同步調用else {RpcContext.getContext().setFuture(null);// 發送請求,得到一個 ResponseFuture 實例,并調用該實例的 get 方法進行等待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 的子項目,是一個樹型的目錄服務,支持變更推送,適合作為 Dubbo 服務的注冊中心,工業強度較高,可用于生產環境,并推薦使用 [1]。
流程說明:
- 服務提供者啟動時: 向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的 URL 地址
- 服務消費者啟動時: 訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 地址
- 監控中心啟動時: 訂閱 /dubbo/com.foo.BarService 目錄下的所有提供者和消費者 URL 地址。
支持以下功能:
- 當提供者出現斷電等異常停機時,注冊中心能自動刪除提供者信息
- 當注冊中心重啟時,能自動恢復注冊數據,以及訂閱請求
- 當會話過期時,能自動恢復注冊數據,以及訂閱請求
- 當設置 <dubbo:registry check=“false” /> 時,記錄失敗注冊和訂閱請求,后臺定時重試
- 可通過 <dubbo:registry username=“admin” password=“1234” /> 設置 zookeeper 登錄信息
- 可通過 <dubbo:registry group=“dubbo” /> 設置 zookeeper 的根節點,不設置將使用無根樹
- 支持 * 號通配符 <dubbo:reference group="" version="" />,可訂閱服務的所有分組和所有版本的提供者
3.2 Multicast 注冊中心:
Multicast 注冊中心不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。
組播受網絡結構限制,只適合小規模應用或開發階段使用。組播地址段: 224.0.0.0 - 239.255.255.255
3.3 Redis 注冊中心
基于 Redis 實現的注冊中心。
使用 Redis 的 Key/Map 結構存儲數據結構:
- 主 Key 為服務名和類型
- Map 中的 Key 為 URL 地址
- Map 中的 Value 為過期時間,用于判斷臟數據,臟數據由監控中心刪除 [3]
使用 Redis 的 Publish/Subscribe 事件通知數據變更:
- 通過事件的值區分事件類型:register, unregister, subscribe, unsubscribe
- 普通消費者直接訂閱指定服務提供者的 Key,只會收到指定服務的 register, unregister 事件
- 監控中心通過 psubscribe 功能訂閱 /dubbo/*,會收到所有服務的所有變更事件
調用過程:
服務提供方啟動時,向 Key:/dubbo/com.foo.BarService/providers 下,添加當前提供者的地址
并向 Channel:/dubbo/com.foo.BarService/providers 發送 register 事件
服務消費方啟動時,從 Channel:/dubbo/com.foo.BarService/providers 訂閱 register 和 unregister 事件
并向 Key:/dubbo/com.foo.BarService/consumers 下,添加當前消費者的地址
服務消費方收到 register 和 unregister 事件后,從 Key:/dubbo/com.foo.BarService/providers 下獲取提供者地址列表
服務監控中心啟動時,從 Channel:/dubbo/* 訂閱 register 和 unregister,以及 subscribe 和unsubsribe事件
服務監控中心收到 register 和 unregister 事件后,從 Key:/dubbo/com.foo.BarService/providers 下獲取提供者地址列表
服務監控中心收到 subscribe 和 unsubsribe 事件后,從 Key:/dubbo/com.foo.BarService/consumers 下獲取消費者地址列表
可靠性聲明
阿里內部并沒有采用 Redis 做為注冊中心,而是使用自己實現的基于數據庫的注冊中心,即:Redis 注冊中心并沒有在阿里內部長時間運行的可靠性保障,此 Redis 橋接實現只為開源版本提供,其可靠性依賴于 Redis 本身的可靠性。
3.4 Simple 注冊中心
Simple 注冊中心本身就是一個普通的 Dubbo 服務,可以減少第三方依賴,使整體通訊方式一致。
配置
將 Simple 注冊中心暴露成 Dubbo 服務:
引用 Simple Registry 服務:
<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" />總結
以上是生活随笔為你收集整理的Dubbo——面试问题集(1~3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 银河麒麟操作系统日常测试
- 下一篇: 华为Mate30系列连接电脑有多方便华为