您好,登錄后才能下訂單哦!
本篇內容主要講解“dubbo的重要知識點總結”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“dubbo的重要知識點總結”吧!
Provider: 暴露服務的提供方,可以通過jar或者容器的方式啟動服務
Consumer:調用遠程服務的服務消費方。
Registry: 服務注冊中心和發現中心。
Monitor: 統計服務的調用次數、調用時間
Container:服務運行的容器。
RPC通訊協議
dubbo:Dubbo缺省協議采用單一長連接和NIO異步通訊,適合于小數據量大并發的服務調用,以及服務消費者機器數遠大于服務提供者機器數的情況
rmi:RMI協議采用JDK標準的java.rmi.*實現,采用阻塞式短連接和JDK標準序列化方式
Hessian:Hessian協議用于集成Hessian的服務,Hessian底層采用Http通訊,采用Servlet暴露服務,Dubbo缺省內嵌Jetty作為服務器實現
http:采用Spring的HttpInvoker實現
Webservice:基于CXF的frontend-simple和transports-http實現
默認是zk,其他還有Redis、Multicast、Simple 注冊中心,但不推薦。
Spring 配置方式(XML文件)
Java API 配置方式(注解方式)
dubbo:service 服務配置(作為服務的提供者,暴露服務的配置)
dubbo:reference 引用配置(需要調用外部服務)
dubbo:protocol 協議配置(服務支持的協議配置,若需要支持多個協議,可以聲明多個<dubbo:protocol>標簽)
dubbo:application 應用配置(應用信息配置,包括當前應用名、應用負責人、應用版本、應用環境等)
dubbo:module 模塊配置(模塊信息配置,包括當前模塊名、模塊負責人、模塊版本等)
dubbo:registry 注冊中心配置(同時如果有多個不同的注冊中心,可以聲明多個 <dubbo:registry> 標簽,并在 <dubbo:service> 或 <dubbo:reference> 的 registry 屬性指定使用的注冊中心。)
dubbo:monitor 監控中心配置(有protocol、address兩個屬性,當protocol="registry",表示從注冊中心發現監控中心地址,當address="10.20.130.230:12080"表示直連監控中心地址)
dubbo:provider 提供方配置(服務提供者缺省值配置,該標簽為 <dubbo:service> 和 <dubbo:protocol> 標簽的缺省值設置。)
dubbo:consumer 消費方配置(服務消費者缺省值配置,該標簽為 <dubbo:reference> 標簽的缺省值設置。)
dubbo:method 方法配置(該標簽為 <dubbo:service> 或 <dubbo:reference> 的子標簽,用于控制到方法級。)
dubbo:argument 參數配置(該標簽為 <dubbo:method> 的子標簽,用于方法參數的特征描述)
在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超時時間,dubbo默認以consumer中配置的時間為準。
如下例子:
在provider.xml的配置:
<dubbo:service timeout="4000" retries="0" interface="com.dingding.tms.bms.service.BillingZfbCodOrderService" ref="billingZfbCodOrderService" registry="globalRegistry"/>
conusmer中的配置:
<dubbo:reference id="billingInterService" interface="com.dingding.tms.bms.service.BillingInterService" protocol="dubbo" check="false" registry="globalRegistry" timeout="3000"/>
最后這個service在調用時的超時時間就是3秒。
另外:
1.consumer會在超過3秒時得到一個調用超時的異常。
2.provider中代碼的執行不會因為超時而中斷,在執行完畢后,會得到一個dubbo的警告。
在dubbo的用戶手冊中,對配置有這樣的推薦用法:在Provider上盡量多配置Consumer端屬性
原因如下:
作服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等
在Provider配置后,Consumer不配置則會使用Provider的配置值,即Provider配置可以作為Consumer的缺省值。否則,Consumer會使用Consumer端的全局設置,這對于Provider不可控的,并且往往是不合理的
PS: 配置的覆蓋規則:
方法級配置級別優于接口級別,即小Scope優先
Consumer端配置 優于 Provider配置 優于 全局配置,最后是Dubbo Hard Code的配置值(見配置文檔)
在 Provider 可以配置的 Consumer 端屬性有:
timeout:方法調用超時
retries:失敗重試次數,缺省是2(表示加上第一次調用,會調用3次)
loadbalance:負載均衡算法(有多個Provider時,如何挑選Provider調用),缺省是隨機(random)。還可以有輪訓(roundrobin)、最不活躍優先(leastactive,指從Consumer端并發調用最好的Provider,可以減少的反應慢的Provider的調用,因為反應更容易累積并發的調用)
actives:消費者端,最大并發調用限制,即當Consumer對一個服務的并發調用到上限后,新調用會Wait直到超時。在方法上配置(dubbo:method )則并發限制針對方法,在接口上配置(dubbo:service),則并發限制針對服務。
Dubbo 缺省會在啟動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止 Spring 初始化完成,默認 check="true",可以通過 check="false" 關閉檢查。
推薦使用Hessian序列化,還有Duddo、FastJson、Java自帶序列化。
Dubbo 默認使用 Netty 框架,也是推薦的選擇,另外內容還集成有Mina、Grizzly
Failover Cluster 失敗自動切換,自動重試其它服務器(默認)
Failfast Cluster 快速失敗,立即報錯,只發起一次調用
Failsafe Cluster 失敗安全,出現異常時,直接忽略
Failback Cluster 失敗自動恢復,記錄失敗請求,定時重發
Forking Cluster 并行調用多個服務器,只要一個成功即返回
Broadcast Cluster 廣播逐個調用所有提供者,任意一個報錯則報錯
Random LoadBalance 隨機,按權重設置隨機概率(默認)
RoundRobin LoadBalance 輪詢,按公約后的權重設置輪詢比率
LeastActive LoadBalance 最少活躍調用數,相同活躍數的隨機
ConsistentHash LoadBalance 一致性 Hash,相同參數的請求總是發到同一提供者
可以配置環境點對點直連,繞過注冊中心,將以服務接口為單位,忽略注冊中心的提供者列表。
Dubbo 允許配置多協議,在不同服務上支持不同協議或者同一服務上同時支持多種協議。
不同服務不同協議:
<!-- 多協議配置 --> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:protocol name="rmi" port="20980" /> <!-- 使用dubbo協議暴露服務 --> <dubbo:service interface="com.ricky.dubbo.api.DemoService" ref="demoService" protocol="dubbo"/> <!-- 使用rmi協議暴露服務 --> <dubbo:service interface="com.ricky.dubbo.api.HelloService" ref="helloService" protocol="rmi"/>
同一服務多種協議
<!-- 多協議配置 --> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:protocol name="rmi" port="20980" /> <!-- 使用rmi協議暴露服務 --> <dubbo:service interface="com.ricky.dubbo.api.HelloService" ref="helloService" protocol="dubbo,rmi"/>
當一個接口有多種實現時,可以用 group 屬性來分組,服務提供方和消費方都指定同一個 group 即可。
提供端:
<dubbo:service interface="…" ref="…" group="實現1" /> <dubbo:service interface="…" ref="…" group="實現2" />
消費端:
<dubbo:reference id="…" interface="…" group="實現1" /> <dubbo:reference id="…" interface="…" group="實現2" />
可以用版本號(version)過渡,多個不同版本的服務注冊到注冊中心,版本號不同的服務相互間不引用。這個和服務分組的概念有一點類似。例如:
服務提供方:
<dubbo:service interface="com.foo.BarService" version="1.0.0" /> <dubbo:service interface="com.foo.BarService" version="2.0.0" />
服務消費方:
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" /> <dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
此外,消費者消費服任意版本的服務時:
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />
Dubbo 提供了聲明式緩存,用于加速熱門數據的訪問速度,以減少用戶加緩存的工作量,使用方式:
<dubbo:reference interface="com.foo.BarService" cache="threadlocal" />
Dubbo提供的三種緩存接口的入口,三種方式均繼承了 AbstractCacheFactory 接口,分別是:
1.threadlocal=com.alibaba.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory
2.lru=com.alibaba.dubbo.cache.support.lru.LruCacheFactory(LRU基于最近最少使用原則刪除多余緩存,保持最熱的數據被緩存;該類型的緩存是跨線程的;利用鏈表實現,新數據插入表頭、緩存命中數據移到表頭、鏈表滿時刪除表尾數據)
3.jcache=com.alibaba.dubbo.cache.support.jcache.JCacheFactory
Dubbo 缺省協議采用單一長連接,底層實現是 Netty 的 NIO 異步通訊機制;基于這種機制,Dubbo 實現了以下幾種調用方式:
同步調用
異步調用
參數回調
事件通知
同步調用是一種阻塞式的調用方式,即 Consumer 端代碼一直阻塞等待,直到 Provider 端返回為止;
通常,一個典型的同步調用過程如下:
Consumer 業務線程調用遠程接口,向 Provider 發送請求,同時當前線程處于阻塞狀態;
Provider 接到 Consumer 的請求后,開始處理請求,將結果返回給 Consumer;
Consumer 收到結果后,當前線程繼續往后執行。
這里有 2 個問題:
Consumer 業務線程是怎么進入阻塞狀態的?
Consumer 收到結果后,如何喚醒業務線程往后執行的?
其實,Dubbo 的底層 IO 操作都是異步的。Consumer 端發起調用后,得到一個 Future 對象。對于同步調用,業務線程通過Future#get(timeout),阻塞等待 Provider 端將結果返回;timeout則是 Consumer 端定義的超時時間。當結果返回后,會設置到此 Future,并喚醒阻塞的業務線程;當超時時間到結果還未返回時,業務線程將會異常返回。
基于 Dubbo 底層的異步 NIO 實現異步調用,對于 Provider 響應時間較長的場景是必須的,它能有效利用 Consumer 端的資源,相對于 Consumer 端使用多線程來說開銷較小。異步調用,對于 Provider 端不需要做特別的配置。
在 Consumer 端配置需要異步調用的方法,均需要使用 <dubbo:method/>標簽進行描述:
<dubbo:reference id="asyncService" interface="com.alibaba.dubbo.samples.async.api.AsyncService"> <dubbo:method name="goodbye" async="true"/> </dubbo:reference>
Dubbo Consumer 端發起調用后,同時通過RpcContext.getContext().getFuture()獲取跟返回結果關聯的Future對象,然后就可以開始處理其他任務;當需要這次異步調用的結果時,可以在任意時刻通過future.get(timeout)來獲取。
一些特殊場景下,為了盡快調用返回,可以設置是否等待消息發出:
sent="true" 等待消息發出,消息發送失敗將拋出異常;
sent="false" 不等待消息發出,將消息放入 IO 隊列,即刻返回。
默認為false。配置方式如下:
<dubbo:method name="goodbye" async="true" sent="true" />
如果你只是想異步,完全忽略返回值,可以配置 return="false",以減少 Future 對象的創建和管理成本:
<dubbo:method name="goodbye" async="true" return="false" />
此時,RpcContext.getContext().getFuture()將返回null。
參數回調有點類似于本地 Callback 機制,但 Callback 并不是 Dubbo 內部的類或接口,而是由 Provider 端自定義的;Dubbo 將基于長連接生成反向代理,從而實現從 Provider 端調用 Consumer 端的邏輯。
Provider 端定義 Service 和 Callback:
public interface CallbackService { void addListener(String key, CallbackListener listener); } public interface CallbackListener { void changed(String msg); }
Provider 端實現 service :
public class CallbackServiceImpl implements CallbackService { private final Map<String, CallbackListener> listeners = new ConcurrentHashMap<String, CallbackListener>(); public CallbackServiceImpl() { Thread t = new Thread(new Runnable() { public void run() { while (true) { try { for (Map.Entry<String, CallbackListener> entry : listeners.entrySet()) { try { entry.getValue().changed(getChanged(entry.getKey())); } catch (Throwable t) { listeners.remove(entry.getKey()); } } Thread.sleep(5000); // timely trigger change event } catch (Throwable t) { t.printStackTrace(); } } } }); t.setDaemon(true); t.start(); } public void addListener(String key, CallbackListener listener) { listeners.put(key, listener); listener.changed(getChanged(key)); // send notification for change } private String getChanged(String key) { return "Changed: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } }
在 Provider 端暴露服務:
<bean id="callbackService" class="com.alibaba.dubbo.samples.callback.impl.CallbackServiceImpl"/> <dubbo:service interface="com.alibaba.dubbo.samples.callback.api.CallbackService" ref="callbackService" connections="1" callbacks="1000"> <dubbo:method name="addListener"> <!-- index 表示參數索引,如下 index=1 ,表示第一個參數是 callback 回調參數 --> <dubbo:argument index="1" callback="true"/> <!--<dubbo:argument type="com.demo.CallbackListener" callback="true" />--> </dubbo:method> </dubbo:service>
Consumer 端實現 Callback 接口
CallbackService callbackService = ...; callbackService.addListener("foo.bar", new CallbackListener() { public void changed(String msg) { System.out.println("callback1:" + msg); } });
Callback 接口的實現類在 Consumer 端,當方法發生調用時,Consumer 端會自動 export 一個 Callback 服務。而 Provider 端在處理調用時,判斷如果參數是 Callback,則生成了一個 proxy,因此服務實現類里在調用 Callback 方法的時候,會被傳遞到 Consumer 端執行 Callback 實現類的代碼。
事件通知允許 Consumer 端在調用之前、調用之后或出現異常時,觸發 oninvoke、onreturn、onthrow 三個事件。
可以通過在配置 Consumer 時,指定事件需要通知的方法,如:
<bean id="demoCallback" class="com.alibaba.dubbo.samples.notify.impl.NotifyImpl" /> <dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.samples.notify.api.DemoService" version="1.0.0" group="cn"> <dubbo:method name="sayHello" onreturn="demoCallback.onreturn" onthrow="demoCallback.onthrow"/> </dubbo:reference>
其中,NotifyImpl 的代碼如下:
public class NotifyImpl implements Notify { public Map<Integer, String> ret = new HashMap<Integer, String>(); public void onreturn(String name, int id) { ret.put(id, name); System.out.println("onreturn: " + name); } public void onthrow(Throwable ex, String name, int id) { System.out.println("onthrow: " + name); } }
這里要強調一點,自定義 Notify 接口中的三個方法的參數規則如下:
oninvoke 方法參數與調用方法的參數相同;
onreturn方法第一個參數為調用方法的返回值,其余為調用方法的參數;
onthrow方法第一個參數為調用異常,其余為調用方法的參數。
上述配置中,sayHello方法為同步調用,因此事件通知方法的執行也是同步執行。可以配置 async=true 讓方法調用為異步,這時事件通知的方法也是異步執行的。特別強調一下, oninvoke 方法不管是否異步調用,都是同步執行的。
目前暫時不支持,后續可能采用基于 JTA/XA 規范實現
可以通過服務降級功能臨時屏蔽某個出錯的非關鍵服務,并定義降級后的返回策略。
向注冊中心寫入動態配置覆蓋規則:
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
其中:
mock=force:return+null 表示消費方對該服務的方法調用都直接返回 null 值,不發起遠程調用。用來屏蔽不重要的服務不可用時,對調用方的影響。
還可以改為 mock=fail:return+null 表示消費方對該服務的方法調用在失敗后,再返回 null 值,不拋異常。用來容忍不重要服務不穩定時對調用方的影響。
Dubbo 是通過 JDK 的 ShutdownHook 來完成優雅停機的,所以如果使用 kill -9 PID 等強制關閉指令,是不會執行優雅停機的,只有通過 kill PID 時,才會執行。
服務提供方:停止時,先標記為不接收新請求,新請求過來時直接報錯,讓客戶端重試其它機器。然后,檢測線程池中的線程是否正在運行,如果有,等待所有線程執行完成,除非超時,則強制關閉。
服務消費方:停止時,不再發起新的調用請求,所有新的調用在客戶端即報錯。然后,檢測有沒有請求的響應還沒有返回,等待響應返回,除非超時,則強制關閉。
服務失效踢出是基于 Zookeeper 的臨時節點原理。
zk 中的節點分為臨時節點和永久節點,節點的類型在創建時即被確定,并且不能改變。
ZooKeeper的臨時節點:該節點的生命周期依賴于創建它們的會話。一旦會話結束,臨時節點將被自動刪除,當然可以也可以手動刪除。另外,需要注意是,ZooKeeper的臨時節點不允許擁有子節點。
ZooKeeper的永久節點:該節點的生命周期不依賴于會話,并且只有在客戶端顯示執行刪除操作的時候,他們才能被刪除。
在分布式系統中,我們常常需要知道某個機器是否可用,傳統的開發中,可以通過Ping某個主機來實現,Ping得通說明對方是可用的,相反是不可用的。
在 ZK 中我們讓所有的機器都注冊一個臨時節點,要判斷一個節點是否可用,我們只需要判斷這個臨時節點在 ZK 中是否存在就可以了,不需要直接去連接需要檢查的機器,降低系統的復雜度。
讀操作建議使用 Failover 失敗自動切換,默認重試兩次其他服務器。
寫操作建議使用 Failfast 快速失敗,發一次調用失敗就立即報錯。
Dubbo 可以使用 Pinpoint 和 Apache Skywalking(Incubator) 實現分布式服務追蹤,當然還有其他很多方案。
管理控制臺主要包含:路由規則,動態配置,服務降級,訪問控制,權重調整,負載均衡,等管理功能。
到此,相信大家對“dubbo的重要知識點總結”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。