dubbo server服務(wù)導(dǎo)出(暴露)過程探究

本文主要聊下dubbo的服務(wù)導(dǎo)出部分,即服務(wù)暴露,服務(wù)導(dǎo)出的核心接口是 Protocol 的 export方法泪幌;暴露的方式可以有很多種(tcp/http/rmi/webservice等)惊豺,也可以同時(shí)暴露多種方式,dubbo 基于接口 SPI 的擴(kuò)展非常靈活坚俗,完全看協(xié)議本身實(shí)現(xiàn)笨鸡;

服務(wù)端接口聲明及實(shí)現(xiàn)如下:

public interface DemoService {
    String sayHello(String name);
}
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    }
}
public class Provider {
    private static void main(String[] args) {
        DemoService demoService = new DemoServiceImpl();
        ApplicationConfig application = new ApplicationConfig();
        application.setName("demo");
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("127.0.0.1:2181");
        registry.setProtocol("zookeeper");
        ProtocolConfig protocol = new ProtocolConfig();
        protocol.setName("dubbo");
        protocol.setPort(20880);
        protocol.setServer("netty4");
        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>(); 
        service.setApplication(application);
        service.setRegistry(registry); 
        service.setProtocol(protocol); 
        service.setInterface(DemoService.class);
        service.setRef(demoService);
        service.export();
        System.in.read();
    }
}

由于 dubbo 最近在做比較大的版本變遷,但是其核心接口并沒變坦冠,所以這里以 2.6.x的版本為例講解形耗,由于我們選用的 server 實(shí)現(xiàn)是netty4,所以我們?cè)?netty 的 AbstractBootstrap.bind 方法加入一個(gè)斷點(diǎn)辙浑,得到的調(diào)用棧如下:

25. bind:264, AbstractBootstrap (io.netty.bootstrap)
24. doOpen:119, NettyServer (com.alibaba.dubbo.remoting.transport.netty4)
23. <init>:88, AbstractServer (com.alibaba.dubbo.remoting.transport)
22. <init>:81, NettyServer (com.alibaba.dubbo.remoting.transport.netty4)
21. bind:33, NettyTransporter (com.alibaba.dubbo.remoting.transport.netty4)
20. bind:-1, Transporter$Adaptive (com.alibaba.dubbo.remoting)
19. bind:60, Transporters (com.alibaba.dubbo.remoting)
18. bind:46, HeaderExchanger (com.alibaba.dubbo.remoting.exchange.support.header)
17. bind:72, Exchangers (com.alibaba.dubbo.remoting.exchange)
16. createServer:430, DubboProtocol (com.alibaba.dubbo.rpc.protocol.dubbo)
15. openServer:393, DubboProtocol (com.alibaba.dubbo.rpc.protocol.dubbo)
14. export:371, DubboProtocol (com.alibaba.dubbo.rpc.protocol.dubbo)
13. export:123, ProtocolFilterWrapper (com.alibaba.dubbo.rpc.protocol)
12. export:59, ProtocolListenerWrapper (com.alibaba.dubbo.rpc.protocol)
11. export:-1, Protocol$Adaptive (com.alibaba.dubbo.rpc)
10. doLocalExport:172, RegistryProtocol (com.alibaba.dubbo.registry.integration)
    9.4 - doRegister:140, ZookeeperRegistry (com.alibaba.dubbo.registry.zookeeper)
    9.3 - register:150, FailbackRegistry (com.alibaba.dubbo.registry.support)
    9.2 - register:129, RegistryProtocol (com.alibaba.dubbo.registry.integration)
9. export:135, RegistryProtocol (com.alibaba.dubbo.registry.integration)
8. export:120, ProtocolFilterWrapper (com.alibaba.dubbo.rpc.protocol)
7. export:56, ProtocolListenerWrapper (com.alibaba.dubbo.rpc.protocol)
6. export:-1, Protocol$Adaptive (com.alibaba.dubbo.rpc)
5. doExportUrlsFor1Protocol:514, ServiceConfig (com.alibaba.dubbo.config)
4. doExportUrls:359, ServiceConfig (com.alibaba.dubbo.config)
3. doExport:318, ServiceConfig (com.alibaba.dubbo.config)
2. export:216, ServiceConfig (com.alibaba.dubbo.config)
1. main:, Provider (com.alibaba.dubbo.demo.provider)

服務(wù)暴露主要分兩個(gè)步驟激涤,一個(gè)是本地服務(wù)暴露,一個(gè)是服務(wù)注冊(cè)判呕,上面的調(diào)用棧主要體現(xiàn)的是本地暴露倦踢,支線 9.2 是服務(wù)注冊(cè)邏輯,下面從棧底依次向上進(jìn)行拆解:
1侠草、 入口函數(shù)main函數(shù)

2-3辱挥、 ServiceConfig 是服務(wù)配置類,承擔(dān)配置的解析边涕、校驗(yàn)晤碘、組裝及服務(wù)暴露的調(diào)用入口,防止重復(fù)導(dǎo)出等

4功蜓、 ServiceConfig.doExportUrls 如果是多協(xié)議則循環(huán)導(dǎo)出

5园爷、 doExportUrlsFor1Protocol 顧名思義,是對(duì)一個(gè)協(xié)議進(jìn)行暴露導(dǎo)出式撼,這里有很多的代碼是對(duì) URL 及其參數(shù)部分進(jìn)了組裝童社,然后還會(huì)進(jìn)行 injvm 的導(dǎo)出,然后進(jìn)行 ProtocolProtocol 導(dǎo)出著隆,這里看起來可能會(huì)有些疑惑扰楼,為什么都是用 protocol.export 進(jìn)行導(dǎo)出的,但是導(dǎo)出的結(jié)果卻不一樣美浦,這里就是 SPI 自適應(yīng)的能力了弦赖,具體來書就是 protocol.export 會(huì)根據(jù)傳入?yún)?shù)的 url 進(jìn)行查找合適的實(shí)現(xiàn)類進(jìn)行 export;本地導(dǎo)出的時(shí)候?qū)?url的protocol設(shè)置為 injvm抵代,注冊(cè)中心導(dǎo)出的時(shí)候?qū)rotocol設(shè)置為 registry就會(huì)分別找到各自的實(shí)現(xiàn)類進(jìn)行導(dǎo)出腾节,這里牽涉到 SPI 的自適應(yīng) @Adaptive 注解的實(shí)現(xiàn),就不展開講了;

6案腺、 Protocol$Adaptive 就是 SPI 自適應(yīng)的實(shí)現(xiàn)庆冕,它是采用代碼生成的方式實(shí)現(xiàn)的,所以這里看不到源碼

7劈榨、 ProtocolListenerWrapper 是 Protocol 的 SPI Wrapper 增強(qiáng)類访递,他會(huì)被自動(dòng)裝飾在 Protocol 實(shí)現(xiàn)類上,這還是 SPI 的功能同辣;在這里因?yàn)槭亲?cè)中心導(dǎo)出邏輯會(huì)直接跳過過濾器鏈的組裝邏輯拷姿,可以查看 ProtocolListenerWrapper.export 方法

8、 ProtocolFilterWrapper 也是 Protocol 的 SPI Wrapper 增強(qiáng)類旱函,他的主要作用是創(chuàng)建過濾器鏈响巢,如果你看過客戶端調(diào)用的那篇文章,這里類也出現(xiàn)過棒妨,總的來說就是為服務(wù)端及客戶端構(gòu)建過濾器鏈踪古;在這里因?yàn)槭亲?cè)中心導(dǎo)出邏輯會(huì)直接跳過過濾器鏈的組裝邏輯,詳情可查看 ProtocolFilterWrapper.export 方法

9券腔、 RegistryProtocol 是注冊(cè)中心導(dǎo)出核心類伏穆, 內(nèi)部封裝了注冊(cè)服務(wù)的通用邏輯,內(nèi)部通過相應(yīng)的 registry 接口適配不同的注冊(cè)中心纷纫;9.2 - 9.4 是注冊(cè)服務(wù)的邏輯枕扫;

10、 RegistryProtocol.doLocalExport 這個(gè)方法有點(diǎn)眼熟辱魁,在 ServiceConfig 中也有一個(gè) exportLocal 的方法是用來導(dǎo)出 injvm Protocol的烟瞧,但是 RegistryProtocol.doLocalExport 的作用是用來導(dǎo)出真實(shí)的應(yīng)用協(xié)議的在這里即是 DubboProtocol

11-13、 又是熟悉的一套 SPI 自適應(yīng)導(dǎo)出協(xié)議商叹,這里url的protocol已經(jīng)是 dubbo 了燕刻,ProtocolListenerWrapper和ProtocolFilterWrapper分別進(jìn)行增強(qiáng)加入監(jiān)聽和過濾器鏈,這里會(huì)進(jìn)行構(gòu)造過濾器鏈的邏輯

14剖笙、 進(jìn)行 DubboProtocol 的導(dǎo)出邏輯,將 Invoker 及過濾器組成的鏈表頭包裝成一個(gè) exporter 進(jìn)行緩存请唱,等真實(shí)業(yè)務(wù)網(wǎng)絡(luò)請(qǐng)求到來時(shí)弥咪,可以在緩存中找到真實(shí)的 Invoker 鏈進(jìn)行調(diào)用

15、 DubboProtocol.openServer 開始暴露網(wǎng)絡(luò)接口十绑,即網(wǎng)絡(luò)監(jiān)聽聚至,由于端口只能監(jiān)聽一次,如果有多個(gè)接口暴露在一個(gè)端口上這里會(huì)進(jìn)行端口復(fù)用本橙,即監(jiān)聽完成后緩存起來扳躬,下次判斷 host:port 是否已緩存監(jiān)聽,如果已監(jiān)聽則復(fù)用

16、 DubboProtocol.createServer 創(chuàng)建server監(jiān)聽邏輯贷币,最終調(diào)用 Exchangers.bind 開啟一個(gè)網(wǎng)絡(luò)端口击胜;值得一提的是 DubboProtocol 中創(chuàng)建了一個(gè) ExchangeHandlerAdapter 類型的 requestHandler 來進(jìn)行網(wǎng)絡(luò)請(qǐng)求處理,他的主要作用是將網(wǎng)絡(luò)請(qǐng)求參數(shù)到 exporter 緩存中找到對(duì)應(yīng)的 Invoker 進(jìn)行調(diào)用然后返回役纹;

17-18偶摔、 Exchangers 是 Exchanger 的工廠來類,通過 SPI 找到 Exchanger 的實(shí)現(xiàn)類 HeaderExchanger 進(jìn)行具體實(shí)現(xiàn)

19-21促脉、 Transporters 是 Transporter 的工廠類辰斋,通過 SPI 找到 Transporter 的實(shí)現(xiàn)類 NettyTransporter 進(jìn)行端口監(jiān)聽,細(xì)心的同學(xué)可能發(fā)現(xiàn)了 這里有一個(gè) Transporter$Adaptive.bind 而 Exchanger 沒有瘸味,這是因?yàn)樗麄儷@取實(shí)現(xiàn)類時(shí)的調(diào)用方式不太一樣宫仗,個(gè)人認(rèn)為更應(yīng)該使用 Adaptive 類進(jìn)行操作,也可能是 Exchanger 的用處比較少旁仿,擴(kuò)展的可能性不大吧锰什,其實(shí)現(xiàn)類默認(rèn)也只有一個(gè),而 Transporter 的實(shí)現(xiàn)類就多了丁逝,擴(kuò)展的可能性也非常大

22-25汁胆、 調(diào)用最終的 nettyServer 實(shí)現(xiàn)進(jìn)行端口監(jiān)聽;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末霜幼,一起剝皮案震驚了整個(gè)濱河市嫩码,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罪既,老刑警劉巖铸题,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異琢感,居然都是意外死亡丢间,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門驹针,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烘挫,“玉大人,你說我怎么就攤上這事柬甥∫” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵苛蒲,是天一觀的道長(zhǎng)卤橄。 經(jīng)常有香客問我,道長(zhǎng)臂外,這世上最難降的妖魔是什么窟扑? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任喇颁,我火速辦了婚禮,結(jié)果婚禮上嚎货,老公的妹妹穿的比我還像新娘橘霎。我一直安慰自己,他們只是感情好厂抖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布茎毁。 她就那樣靜靜地躺著,像睡著了一般忱辅。 火紅的嫁衣襯著肌膚如雪七蜘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天墙懂,我揣著相機(jī)與錄音橡卤,去河邊找鬼。 笑死损搬,一個(gè)胖子當(dāng)著我的面吹牛碧库,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巧勤,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼嵌灰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了颅悉?” 一聲冷哼從身側(cè)響起沽瞭,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剩瓶,沒想到半個(gè)月后驹溃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡延曙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年豌鹤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枝缔。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡布疙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出魂仍,到底是詐尸還是另有隱情拐辽,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布擦酌,位于F島的核電站,受9級(jí)特大地震影響菠劝,放射性物質(zhì)發(fā)生泄漏赊舶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笼平。 院中可真熱鬧园骆,春花似錦、人聲如沸寓调。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夺英。三九已至晌涕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痛悯,已是汗流浹背余黎。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留载萌,地道東北人惧财。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扭仁,于是被迫代替她去往敵國(guó)和親垮衷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容