再談Dubbo

最近工作中由于涉及到微服務(wù)這塊无宿,所以把Dubbo又重新回顧了一遍,現(xiàn)在做個總結(jié)赂弓。

為什么使用RPC框架绑榴?

一個老生常談的問題,為什么使用RPC框架盈魁?如果你的系統(tǒng)是單機系統(tǒng)彭沼,完全可以不用考慮這個問題,但是這些年微服務(wù)盛行备埃,SOAP姓惑,企業(yè)級總線這些過于重量級,大廠都不一定能玩得轉(zhuǎn)的玩意按脚,所以何況是中小企業(yè)于毙。所以退而求其次選擇RESTful或者輕量級RPC框架,Dubbo之所以能在國內(nèi)脫穎而出辅搬,肯定是有它的原因唯沮,在這里我們就不詳細說了。

Dubbo能為我們做什么堪遂?

其實應(yīng)該說作為一款企業(yè)級RPC框架應(yīng)該具備哪些基本的功能:

1.基本的遠程調(diào)用
2.微服務(wù)管理
3.監(jiān)控功能
4.負載均衡
5.網(wǎng)關(guān)限流
6.高并發(fā)介蛉,高可用

基本的遠程調(diào)用

這個是我們今天要談的重點,Dubbo是怎么使用遠程調(diào)用的溶褪?

說到遠程調(diào)用币旧,我們可以采用HTTP,TCP/IP等協(xié)議,我們在大學(xué)的網(wǎng)絡(luò)課程里面學(xué)過猿妈,這些協(xié)議承載了太多內(nèi)容吹菱,很多東西都是我們不需要的,我們調(diào)用選擇一個方法其實只是傳幾個參數(shù)而已彭则,沒有必要用HTTP,TCP/IP傳輸太多我們不需要的內(nèi)容吧鳍刷,所以Dubbo選擇自己實現(xiàn)了自己的協(xié)議,那就是Dubbo協(xié)議俯抖。

現(xiàn)在協(xié)議有了输瓜,那么協(xié)議的內(nèi)容通過什么方式傳輸呢?既然HTTP,TCP/IP不能用芬萍,那么我們只能選擇socket尤揣,但是socket太低端,需要自己考慮的東西太多担忧,所以當(dāng)然是選擇業(yè)內(nèi)作為成熟的框架Netty芹缔。

那么Netty是如何實現(xiàn)網(wǎng)絡(luò)通信的坯癣?我們先看服務(wù)端實現(xiàn)代碼瓶盛,這個段代碼來自Dubbo的Netty Server 類doOpen方法


        NettyHelper.setNettyLoggerFactory();
        ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
        ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
        ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, this.getUrl().getPositiveParameter("iothreads", Constants.DEFAULT_IO_THREADS));
        this.bootstrap = new ServerBootstrap(channelFactory);
        final NettyHandler nettyHandler = new NettyHandler(this.getUrl(), this);
        this.channels = nettyHandler.getChannels();
        this.bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                NettyCodecAdapter adapter = new NettyCodecAdapter(NettyServer.this.getCodec(), NettyServer.this.getUrl(), NettyServer.this);
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
                return pipeline;
            }
        });

        this.channel = this.bootstrap.bind(this.getBindAddress());

如果你對netty不熟悉的話可能看不懂上面的代碼,我來解釋一下:

ServerBootstrap為netty的啟動類,傳入?yún)?shù)是ChannelFactory惩猫,這個類有兩個構(gòu)造函數(shù)芝硬,netty使用reactor模式進行網(wǎng)絡(luò)通信,我們可以看到傳了兩個線程池轧房,一個是boss,一個worker拌阴,顧名思義boss是老板,worker是打工仔奶镶,boss負責(zé)請求的接待迟赃,然后將工作分配給worker進行處理,最后一個參數(shù)是需要分配的io線程數(shù)的個數(shù)厂镇,這個是從URL里面獲取的纤壁,這個相當(dāng)于Dubbo的一個全局上下文,這個參數(shù)是netty 的workers的數(shù)量捺信,所有workers共享worker線程池酌媒,說白就是這些workers輪流去干活,干玩活把任務(wù)丟給worker線程池進行處理迄靠,有興趣的同學(xué)可以去看下Netty源代碼秒咨。

接著我們看到setPipelineFactory方法,這個是Netty內(nèi)部實現(xiàn)的管道機制掌挚,簡單來說就是服務(wù)端如果有數(shù)據(jù)處理就把數(shù)據(jù)丟到這些管道依次執(zhí)行雨席,nettyHandler是Dubbo實現(xiàn)的一個管道處理方法。這些細節(jié)其實我們不用關(guān)注太多吠式,其實說來就是Netty幫我們創(chuàng)建了一個 socket鏈接舅世,如果有請求連接進來,或者有數(shù)據(jù)進來奇徒,我們只需要關(guān)注具體的實現(xiàn)業(yè)務(wù)邏輯雏亚,其它方面Netty已經(jīng)幫我們處理好了。

說到了服務(wù)端的實現(xiàn)摩钙,那么客戶端是如何做的呢罢低?

聰明的你可能已經(jīng)想到,既然有NettyServer胖笛,那么肯定有NettyClient网持,沒錯!下面我們來看NettyClient的doOpen方法實現(xiàn):


        NettyHelper.setNettyLoggerFactory();
        this.bootstrap = new ClientBootstrap(channelFactory);
        this.bootstrap.setOption("keepAlive", true);
        this.bootstrap.setOption("tcpNoDelay", true);
        this.bootstrap.setOption("connectTimeoutMillis", this.getTimeout());
        final NettyHandler nettyHandler = new NettyHandler(this.getUrl(), this);
        this.bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                NettyCodecAdapter adapter = new NettyCodecAdapter(NettyClient.this.getCodec(), NettyClient.this.getUrl(), NettyClient.this);
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
                return pipeline;
            }
        });

注意以上代碼是基于2.8.4长踊,對于最新的Dubbo可能不是這樣功舀,但是原理是一樣的,如果你有理解上面Server端的初始化過程身弊,那么這段代碼應(yīng)該不難看懂辟汰。

所以RPC不過如此吧列敲,但是這只是Dubbo的冰山一腳,本篇文章只是為了說明原理帖汞,列舉了底層核心代碼而已戴而,在實現(xiàn)方法Dubbo使用了CompleteFuture來實現(xiàn)異步調(diào)度。

其它方面

Dubbo作為一款企業(yè)級別的框架翩蘸,當(dāng)然不會只能上面兩段代碼解決所有問題所意,為了考慮擴展性,Dubbo提供了注冊中心催首,以及自己一套URL的上下文傳輸機制扶踊,簡單來說URL就是DubboInvoker,DubboInvoker就是Dubbo的核心郎任,說白了姻檀,DubboInvoker就是封裝上面兩端代碼,使RPC使用對我們開發(fā)人員透明涝滴,我們不用去關(guān)注底層的網(wǎng)絡(luò)傳輸绣版,序列化,就是代理調(diào)用機制歼疮。為了實現(xiàn)擴展Dubbo參考TCP/IP協(xié)議杂抽,實現(xiàn)了Exchanger和Transporter兩層,剛才列舉上面6點中的第5點是在這兩層實現(xiàn)的韩脏。

技術(shù)方面缩麸,Dubbo實現(xiàn)了自己的IOC機制SPI擴展,為了實現(xiàn)高并發(fā)赡矢,Dubbo當(dāng)然會實現(xiàn)自己的線程調(diào)度機制以及高效的時間輪算法杭朱,具體可以參考我之前寫的《Dubbo的線程模型》。

至于負載均衡吹散,集群弧械,以及配置中心的實現(xiàn)也是其可圈可點的地方,有機會我下次再分享吧空民,今天主要是介紹Dubbo的底層原理刃唐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市界轩,隨后出現(xiàn)的幾起案子画饥,更是在濱河造成了極大的恐慌,老刑警劉巖浊猾,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抖甘,死亡現(xiàn)場離奇詭異,居然都是意外死亡葫慎,警方通過查閱死者的電腦和手機衔彻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門薇宠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人米奸,你說我怎么就攤上這事昼接∷瘢” “怎么了悴晰?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逐工。 經(jīng)常有香客問我铡溪,道長,這世上最難降的妖魔是什么泪喊? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任棕硫,我火速辦了婚禮,結(jié)果婚禮上袒啼,老公的妹妹穿的比我還像新娘哈扮。我一直安慰自己,他們只是感情好蚓再,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布滑肉。 她就那樣靜靜地躺著,像睡著了一般摘仅。 火紅的嫁衣襯著肌膚如雪靶庙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天娃属,我揣著相機與錄音六荒,去河邊找鬼。 笑死矾端,一個胖子當(dāng)著我的面吹牛掏击,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秩铆,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铐料,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了豺旬?” 一聲冷哼從身側(cè)響起钠惩,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎族阅,沒想到半個月后篓跛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡坦刀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年愧沟,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔬咬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沐寺,死狀恐怖林艘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情混坞,我是刑警寧澤季率,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布剂桥,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汹买。R本人自食惡果不足惜竖般,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一飒赃、第九天 我趴在偏房一處隱蔽的房頂上張望蜜托。 院中可真熱鬧,春花似錦微酬、人聲如沸绘趋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽陷遮。三九已至,卻和暖如春忙上,著一層夾襖步出監(jiān)牢的瞬間拷呆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工疫粥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茬斧,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓梗逮,卻偏偏與公主長得像项秉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子慷彤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

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