国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

聊聊Dubbo - Dubbo可擴展機制實戰(zhàn)

techstay / 1277人閱讀

摘要:今天我想聊聊的另一個很棒的特性就是它的可擴展性。的擴展機制在的官網(wǎng)上,描述自己是一個高性能的框架。接下來的章節(jié)中我們會慢慢揭開擴展機制的神秘面紗。擴展擴展點的實現(xiàn)類。的定義在配置文件中可以看到文件中定義了個的擴展實現(xiàn)。

摘要: 在Dubbo的官網(wǎng)上,Dubbo描述自己是一個高性能的RPC框架。今天我想聊聊Dubbo的另一個很棒的特性, 就是它的可擴展性。

Dubbo的擴展機制

在Dubbo的官網(wǎng)上,Dubbo描述自己是一個高性能的RPC框架。今天我想聊聊Dubbo的另一個很棒的特性, 就是它的可擴展性。 如同羅馬不是一天建成的,任何系統(tǒng)都一定是從小系統(tǒng)不斷發(fā)展成為大系統(tǒng)的,想要從一開始就把系統(tǒng)設(shè)計的足夠完善是不可能的,相反的,我們應(yīng)該關(guān)注當下的需求,然后再不斷地對系統(tǒng)進行迭代。在代碼層面,要求我們適當?shù)膶﹃P(guān)注點進行抽象和隔離,在軟件不斷添加功能和特性時,依然能保持良好的結(jié)構(gòu)和可維護性,同時允許第三方開發(fā)者對其功能進行擴展。在某些時候,軟件設(shè)計者對擴展性的追求甚至超過了性能。
在談到軟件設(shè)計時,可擴展性一直被談起,那到底什么才是可擴展性,什么樣的框架才算有良好的可擴展性呢?它必須要做到以下兩點:

作為框架的維護者,在添加一個新功能時,只需要添加一些新代碼,而不用大量的修改現(xiàn)有的代碼,即符合開閉原則。
作為框架的使用者,在添加一個新功能時,不需要去修改框架的源碼,在自己的工程中添加代碼即可。
Dubbo很好的做到了上面兩點。這要得益于Dubbo的微內(nèi)核+插件的機制。接下來的章節(jié)中我們會慢慢揭開Dubbo擴展機制的神秘面紗。

可擴展的幾種解決方案

通常可擴展的實現(xiàn)有下面幾種:

Factory模式
IoC容器
OSGI容器
Dubbo作為一個框架,不希望強依賴其他的IoC容器,比如Spring,Guice。OSGI也是一個很重的實現(xiàn),不適合Dubbo。最終Dubbo的實現(xiàn)參考了Java原生的SPI機制,但對其進行了一些擴展,以滿足Dubbo的需求。

Java SPI機制

既然Dubbo的擴展機制是基于Java原生的SPI機制,那么我們就先來了解下Java SPI吧。了解了Java的SPI,也就是對Dubbo的擴展機制有一個基本的了解。如果對Java SPI比較了解的同學(xué),可以跳過。
Java SPI(Service Provider Interface)是JDK內(nèi)置的一種動態(tài)加載擴展點的實現(xiàn)。在ClassPath的META-INF/services目錄下放置一個與接口同名的文本文件,文件的內(nèi)容為接口的實現(xiàn)類,多個實現(xiàn)類用換行符分隔。JDK中使用java.util.ServiceLoader來加載具體的實現(xiàn)。 讓我們通過一個簡單的例子,來看看Java SPI是如何工作的。

定義一個接口IRepository用于實現(xiàn)數(shù)據(jù)儲存
interface IRepository { void save(String data); }
提供IRepository的實現(xiàn) IRepository有兩個實現(xiàn)。MysqlRepository和MongoRepository。
class MysqlRepository implements IRepository { public void save(String data) { System.out.println("Save " + data + " to Mysql"); } }
public class MongoRepository implements IRepository { public void save(String data) { System.out.println("Save " + data + " to Mongo"); } }

添加配置文件 在META-INF/services目錄添加一個文件,文件名和接口全名稱相同,所以文件是META-INF/services/com.demo.IRepository。文件內(nèi)容為:
com.demo.MongoRepository com.demo.MysqlRepository
通過ServiceLoader加載IRepository實現(xiàn)
ServiceLoader serviceLoader = ServiceLoader.load(IRepository.class); Iterator it = serviceLoader.iterator(); while (it != null && it.hasNext()){ IRepository demoService = it.next(); System.out.println("class:" + demoService.getClass().getName()); demoService.save("tom"); }
在上面的例子中,我們定義了一個擴展點和它的兩個實現(xiàn)。在ClassPath中添加了擴展的配置文件,最后使用ServiceLoader來加載所有的擴展點。

Dubbo的SPI機制

Java SPI的使用很簡單。也做到了基本的加載擴展點的功能。但Java SPI有以下的不足:

需要遍歷所有的實現(xiàn),并實例化,然后我們在循環(huán)中才能找到我們需要的實現(xiàn)。
配置文件中只是簡單的列出了所有的擴展實現(xiàn),而沒有給他們命名。導(dǎo)致在程序中很難去準確的引用它們。
擴展如果依賴其他的擴展,做不到自動注入和裝配
不提供類似于Spring的AOP功能
擴展很難和其他的框架集成,比如擴展里面依賴了一個Spring bean,原生的Java SPI不支持
所以Java SPI應(yīng)付一些簡單的場景是可以的,但對于Dubbo,它的功能還是比較弱的。Dubbo對原生SPI機制進行了一些擴展。接下來,我們就更深入地了解下Dubbo的SPI機制。

Dubbo擴展點機制基本概念

在深入學(xué)習(xí)Dubbo的擴展機制之前,我們先明確Dubbo SPI中的一些基本概念。在接下來的內(nèi)容中,我們會多次用到這些術(shù)語。

擴展點(Extension Point)
是一個Java的接口。
擴展(Extension)
擴展點的實現(xiàn)類。
擴展實例(Extension Instance)
擴展點實現(xiàn)類的實例。
擴展自適應(yīng)實例(Extension Adaptive Instance)
第一次接觸這個概念時,可能不太好理解(我第一次也是這樣的...)。如果稱它為擴展代理類,可能更好理解些。擴展的自適應(yīng)實例其實就是一個Extension的代理,它實現(xiàn)了擴展點接口。在調(diào)用擴展點的接口方法時,會根據(jù)實際的參數(shù)來決定要使用哪個擴展。比如一個IRepository的擴展點,有一個save方法。有兩個實現(xiàn)MysqlRepository和MongoRepository。IRepository的自適應(yīng)實例在調(diào)用接口方法的時候,會根據(jù)save方法中的參數(shù),來決定要調(diào)用哪個IRepository的實現(xiàn)。如果方法參數(shù)中有repository=mysql,那么就調(diào)用MysqlRepository的save方法。如果repository=mongo,就調(diào)用MongoRepository的save方法。和面向?qū)ο蟮难舆t綁定很類似。為什么Dubbo會引入擴展自適應(yīng)實例的概念呢?

Dubbo中的配置有兩種,一種是固定的系統(tǒng)級別的配置,在Dubbo啟動之后就不會再改了。還有一種是運行時的配置,可能對于每一次的RPC,這些配置都不同。比如在xml文件中配置了超時時間是10秒鐘,這個配置在Dubbo啟動之后,就不會改變了。但針對某一次的RPC調(diào)用,可以設(shè)置它的超時時間是30秒鐘,以覆蓋系統(tǒng)級別的配置。對于Dubbo而言,每一次的RPC調(diào)用的參數(shù)都是未知的。只有在運行時,根據(jù)這些參數(shù)才能做出正確的決定。
很多時候,我們的類都是一個單例的,比如Spring的bean,在Spring bean都實例化時,如果它依賴某個擴展點,但是在bean實例化時,是不知道究竟該使用哪個具體的擴展實現(xiàn)的。這時候就需要一個代理模式了,它實現(xiàn)了擴展點接口,方法內(nèi)部可以根據(jù)運行時參數(shù),動態(tài)的選擇合適的擴展實現(xiàn)。而這個代理就是自適應(yīng)實例。 自適應(yīng)擴展實例在Dubbo中的使用非常廣泛,Dubbo中,每一個擴展都會有一個自適應(yīng)類,如果我們沒有提供,Dubbo會使用字節(jié)碼工具為我們自動生成一個。所以我們基本感覺不到自適應(yīng)類的存在。后面會有例子說明自適應(yīng)類是怎么工作的。
@SPI
@SPI注解作用于擴展點的接口上,表明該接口是一個擴展點。可以被Dubbo的ExtentionLoader加載。如果沒有此ExtensionLoader調(diào)用會異常。
@Adaptive
@Adaptive注解用在擴展接口的方法上。表示該方法是一個自適應(yīng)方法。Dubbo在為擴展點生成自適應(yīng)實例時,如果方法有@Adaptive注解,會為該方法生成對應(yīng)的代碼。方法內(nèi)部會根據(jù)方法的參數(shù),來決定使用哪個擴展。
ExtentionLoader
類似于Java SPI的ServiceLoader,負責擴展的加載和生命周期維護。
擴展別名
和Java SPI不同,Dubbo中的擴展都有一個別名,用于在應(yīng)用中引用它們。比如
random=com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance roundrobin=com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
其中的random,roundrobin就是對應(yīng)擴展的別名。這樣我們在配置文件中使用random或roundrobin就可以了。

一些路徑
和Java SPI從/META-INF/services目錄加載擴展配置類似,Dubbo也會從以下路徑去加載擴展配置文件:
META-INF/dubbo/internal
META-INF/dubbo
META-INF/services

Dubbo的LoadBalance擴展點解讀

在了解了Dubbo的一些基本概念后,讓我們一起來看一個Dubbo中實際的擴展點,對這些概念有一個更直觀的認識。
我們選擇的是Dubbo中的LoadBalance擴展點。Dubbo中的一個服務(wù),通常有多個Provider,consumer調(diào)用服務(wù)時,需要在多個Provider中選擇一個。這就是一個LoadBalance。我們一起來看看在Dubbo中,LoadBalance是如何成為一個擴展點的。

LoadBalance接口
@SPI(RandomLoadBalance.NAME) public interface LoadBalance { @Adaptive("loadbalance") Invoker select(List> invokers, URL url, Invocation invocation) throws RpcException; }
LoadBalance接口只有一個select方法。select方法從多個invoker中選擇其中一個。上面代碼中和Dubbo SPI相關(guān)的元素有:

@SPI(RandomLoadBalance.NAME) @SPI作用于LoadBalance接口,表示接口LoadBalance是一個擴展點。如果沒有@SPI注解,試圖去加載擴展時,會拋出異常。@SPI注解有一個參數(shù),該參數(shù)表示該擴展點的默認實現(xiàn)的別名。如果沒有顯示的指定擴展,就使用默認實現(xiàn)。RandomLoadBalance.NAME是一個常量,值是"random",是一個隨機負載均衡的實現(xiàn)。 random的定義在配置文件META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.LoadBalance中:
random=com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance roundrobin=com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance leastactive=com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance consistenthash=com.alibaba.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance
可以看到文件中定義了4個LoadBalance的擴展實現(xiàn)。由于負載均衡的實現(xiàn)不是本次的內(nèi)容,這里就不過多說明。只用知道Dubbo提供了4種負載均衡的實現(xiàn),我們可以通過xml文件,properties文件,JVM參數(shù)顯式的指定一個實現(xiàn)。如果沒有,默認使用隨機。

@Adaptive("loadbalance") @Adaptive注解修飾select方法,表明方法select方法是一個可自適應(yīng)的方法。Dubbo會自動生成該方法對應(yīng)的代碼。當調(diào)用select方法時,會根據(jù)具體的方法參數(shù)來決定調(diào)用哪個擴展實現(xiàn)的select方法。@Adaptive注解的參數(shù)loadbalance表示方法參數(shù)中的loadbalance的值作為實際要調(diào)用的擴展實例。 但奇怪的是,我們發(fā)現(xiàn)select的方法中并沒有l(wèi)oadbalance參數(shù),那怎么獲取loadbalance的值呢?select方法中還有一個URL類型的參數(shù),Dubbo就是從URL中獲取loadbalance的值的。這里涉及到Dubbo的URL總線模式,簡單說,URL中包含了RPC調(diào)用中的所有參數(shù)。URL類中有一個Map parameters字段,parameters中就包含了loadbalance。
獲取LoadBalance擴展
Dubbo中獲取LoadBalance的代碼如下:
LoadBalance lb = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
使用ExtensionLoader.getExtensionLoader(LoadBalance.class)方法獲取一個ExtensionLoader的實例,然后調(diào)用getExtension,傳入一個擴展的別名來獲取對應(yīng)的擴展實例。

自定義一個LoadBalance擴展

本節(jié)中,我們通過一個簡單的例子,來自己實現(xiàn)一個LoadBalance,并把它集成到Dubbo中。我會列出一些關(guān)鍵的步驟和代碼,也可以從這個地址(https://github.com/vangoleo/d...。

實現(xiàn)LoadBalance接口
首先,編寫一個自己實現(xiàn)的LoadBalance,因為是為了演示Dubbo的擴展機制,而不是LoadBalance的實現(xiàn),所以這里LoadBalance的實現(xiàn)非常簡單,選擇第一個invoker,并在控制臺輸出一條日志。
package com.dubbo.spi.demo.consumer; public class DemoLoadBalance implements LoadBalance { @Override public Invoker select(List> invokers, URL url, Invocation invocation) throws RpcException { System.out.println("DemoLoadBalance: Select the first invoker..."); return invokers.get(0); } }

添加擴展配置文件
添加文件:META-INF/dubbo/com.alibaba.dubbo.rpc.cluster.LoadBalance。文件內(nèi)容如下:
demo=com.dubbo.spi.demo.consumer.DemoLoadBalance

配置使用自定義LoadBalance
通過上面的兩步,已經(jīng)添加了一個名字為demo的LoadBalance實現(xiàn),并在配置文件中進行了相應(yīng)的配置。接下來,需要顯式的告訴Dubbo使用demo的負載均衡實現(xiàn)。如果是通過spring的方式使用Dubbo,可以在xml文件中進行設(shè)置。

在consumer端的dubbo:reference中配置

啟動Dubbo
啟動Dubbo,調(diào)用一次IHelloService,可以看到控制臺會輸出一條DemoLoadBalance: Select the first invoker...日志。說明Dubbo的確是使用了我們自定義的LoadBalance。
總結(jié)
到此,我們從Java SPI開始,了解了Dubbo SPI 的基本概念,并結(jié)合了Dubbo中的LoadBalance加深了理解。最后,我們還實踐了一下,創(chuàng)建了一個自定義LoadBalance,并集成到Dubbo中。相信通過這里理論和實踐的結(jié)合,大家對Dubbo的可擴展有更深入的理解。

總結(jié)一下,Dubbo SPI有以下的特點:
? 對Dubbo進行擴展,不需要改動Dubbo的源碼
? 自定義的Dubbo的擴展點實現(xiàn),是一個普通的Java類,Dubbo沒有引入任何Dubbo特有的元素,對代碼侵入性幾乎為零。
? 將擴展注冊到Dubbo中,只需要在ClassPath中添加配置文件。使用簡單。而且不會對現(xiàn)有代碼造成影響。符合開閉原則。
? Dubbo的擴展機制支持IoC,AoP等高級功能
? Dubbo的擴展機制能很好的支持第三方IoC容器,默認支持Spring Bean,可自己擴展來支持其他容器,比如Google的Guice。
? 切換擴展點的實現(xiàn),只需要在配置文件中修改具體的實現(xiàn),不需要改代碼。使用方便。

原文鏈接

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69634.html

相關(guān)文章

  • 聊聊Dubbo - Dubbo擴展機制源碼解析

    摘要:什么是類那什么樣類的才是擴展機制中的類呢類是一個有復(fù)制構(gòu)造函數(shù)的類,也是典型的裝飾者模式。代碼如下有一個參數(shù)是的復(fù)制構(gòu)造函數(shù)有一個構(gòu)造函數(shù),參數(shù)是擴展點,所以它是一個擴展機制中的類。 摘要:?在Dubbo可擴展機制實戰(zhàn)中,我們了解了Dubbo擴展機制的一些概念,初探了Dubbo中LoadBalance的實現(xiàn),并自己實現(xiàn)了一個LoadBalance。是不是覺得Dubbo的擴展機制很不錯呀...

    lmxdawn 評論0 收藏0
  • 聊聊 Apache Dubbo

    摘要:架構(gòu)中有兩個主要角色服務(wù)提供者和服務(wù)使用者。服務(wù)提供者在啟動時,向注冊中心注冊自己提供的服務(wù)。負載平衡旨在優(yōu)化資源使用,最大化吞吐量,最小化響應(yīng)時間,并避免任何單個資源的過載。 本文來自于我的個人主頁:Apache Dubbo,轉(zhuǎn)載請保留鏈接 ;) 在2011年10月27日,阿里巴巴開源了自己的SOA服務(wù)化治理方案的核心框架Dubbo,服務(wù)治理和SOA的設(shè)計理念開始逐漸在國內(nèi)軟件行業(yè)中...

    XFLY 評論0 收藏0
  • Dubbo開源現(xiàn)狀與未來規(guī)劃

    摘要:今天的話題是與的開源現(xiàn)狀和未來規(guī)劃,我們知道,過去一段時間疏于維護,去年阿里高調(diào)宣布重啟開源之后,社區(qū)里問的最多的問題是,這次開源與上次有什么一樣,還有就是和是什么關(guān)系希望通過這次的分享能夠解答這些問題。 摘要: Dubbo 在過去一段時間疏于維護,去年阿里高調(diào)宣布重啟 Dubbo 開源之后,社區(qū)里問的最多的問題是,這次開源與上次有什么一樣,還有就是 Dubbo 和 Spring Bo...

    zhoutao 評論0 收藏0
  • 你還不知“dubbo”是個什么東西嗎???

    摘要:服務(wù)提供者在啟動時,向注冊中心注冊自己提供的服務(wù)。注冊中心返回服務(wù)提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者。 先來了解一下這些年架構(gòu)的變化,下面的故事是我編的。。。。 傳統(tǒng)架構(gòu):很多年前,剛學(xué)完JavaWeb開發(fā)的我憑借一人之力就開發(fā)了一個網(wǎng)站,網(wǎng)站 所有的功能和應(yīng)用都集中在一起,方便了我的開發(fā)同時也節(jié)省了成本。但是后來我的網(wǎng)站訪問流量突然加大,我通...

    keithxiaoy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<