<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Dubbo源碼分析:小白入門篇

          共 6145字,需瀏覽 13分鐘

           ·

          2021-11-15 13:42

          關(guān)注公眾號(hào)java后端技術(shù)全棧

          回復(fù)“000”獲取優(yōu)質(zhì)面試資料

          大家好,我是老田

          答應(yīng)了小伙伴的Dubbo源碼分析系列,今天終于來(lái)了,希望不是很晚。

          主要也是現(xiàn)在Spring CLoud Alibaba實(shí)在是太火了,很多小伙伴都想好好搞搞。

          既然如此,我們就選擇從Dubbo開始吧。

          如果你已經(jīng)對(duì)Dubbo熟練使用了,那這篇文章不太適合你,但如果想了解Dubbo,想學(xué)習(xí)Dubbo,那就非常適合你。

          什么是Dubbo?

          Dubbo一開始是由阿里巴巴開發(fā),后面貢獻(xiàn)給了Apache,所以后面我們稱之為Apache Dubbo或者直接叫Dubbo。

          Dubbo 是一款高性能、輕量級(jí)的開源服務(wù)框架 。

          先糾正讀法:

          錯(cuò)誤讀法:diubo、dubo

          正確讀法:|?d?b??|

          Dubbo的六大核心能力

          • 面向接口代理的高性能RPC調(diào)用
          • 智能容錯(cuò)和負(fù)載均衡
          • 服務(wù)自動(dòng)注冊(cè)和發(fā)現(xiàn)
          • 高度可擴(kuò)展能力
          • 運(yùn)行期流量調(diào)度
          • 可視化的服務(wù)治理與運(yùn)維。

          開發(fā)中,我們都喜歡把Dubbo簡(jiǎn)稱為RPC開源框架。

          什么是RPC?

          RPCRemote Procedure Call的簡(jiǎn)稱,翻譯過(guò)來(lái)就是:遠(yuǎn)程過(guò)程調(diào)用

          簡(jiǎn)單的理解是一個(gè)節(jié)點(diǎn)請(qǐng)求另一個(gè)節(jié)點(diǎn)提供的服務(wù) 。

          通俗點(diǎn)講:

          兩臺(tái)服務(wù)器A和B,在服務(wù)器A上部署一個(gè)應(yīng)用程序serverA,在服務(wù)器B上部署一個(gè)應(yīng)用程序serverB。此時(shí),serverA想調(diào)用serverB里的某個(gè)方法,由于不在同一服務(wù)器內(nèi),不能直接調(diào)用,需要通過(guò)網(wǎng)絡(luò)來(lái)表達(dá)調(diào)用的語(yǔ)義和傳導(dǎo)調(diào)用的數(shù)據(jù)。

          調(diào)用遠(yuǎn)程的方法就像調(diào)用本地的方法一樣。

          我們開發(fā)中,通常兩個(gè)服務(wù)(不同服務(wù)器上的服務(wù))之間的調(diào)用,通常都是用HTTP REST。

          RPC框架

          其實(shí)關(guān)于RPC框架,市面上有很多了,Dubbo只是其中之一。比如說(shuō)還有:

          • gRPC 是 Google 開發(fā)的高性能、通用的開源 RPC 框架,gRPC 使用 ProtoBuf 來(lái)定義服務(wù),ProtoBuf 是 Google 開發(fā)的一種數(shù)據(jù)序列化協(xié)議,性能比較高,壓縮和傳輸效率高,語(yǔ)法也比較簡(jiǎn)單。另外,gRPC 支持多種語(yǔ)言,并能夠基于語(yǔ)言自動(dòng)生成客戶端和服務(wù)端功能庫(kù)。
          • Thrift 起源于 Facebook,和 Dubbo 一樣,后來(lái)被提交 Apache 基金會(huì)將 Thrift 作為一個(gè)開源項(xiàng)目。Facebook 創(chuàng)造 Thrift 的目的是為了解決 Facebook 各系統(tǒng)間大數(shù)據(jù)量的傳輸通信,以及系統(tǒng)間語(yǔ)言環(huán)境不同需要跨平臺(tái)的問(wèn)題。
          • Motan 是新浪微博開源的一個(gè) Java RPC 框架,官方文檔對(duì)外宣傳在微博平臺(tái)已經(jīng)廣泛應(yīng)用,每天為數(shù)百個(gè)服務(wù)完成近千億次的調(diào)用。
          • ...

          Dubbo核心角色

          我們來(lái)看看Dubbo架構(gòu)中的核心角色:

          該圖來(lái)自于官網(wǎng),下面我們對(duì)圖做一個(gè)簡(jiǎn)單介紹:

          Registry

          注冊(cè)中心。負(fù)責(zé)服務(wù)地址的注冊(cè)與查找,服務(wù)的 ProviderConsumer 只在啟動(dòng)時(shí)與注冊(cè)中心交互。注冊(cè)中心通過(guò)長(zhǎng)連接感知 Provider 的存在,在 Provider 出現(xiàn)宕機(jī)的時(shí)候,注冊(cè)中心會(huì)立即推送相關(guān)事件通知 Consumer。

          Provider

          服務(wù)提供者。在它啟動(dòng)的時(shí)候,會(huì)向 Registry 進(jìn)行注冊(cè)操作,將自己服務(wù)的地址和相關(guān)配置信息封裝成 URL 添加到 ZooKeeper 中。

          Consumer

          服務(wù)消費(fèi)者。在它啟動(dòng)的時(shí)候,會(huì)向 Registry 進(jìn)行訂閱操作。訂閱操作會(huì)從 ZooKeeper 中獲取 Provider 注冊(cè)的 URL,并在 ZooKeeper 中添加相應(yīng)的監(jiān)聽器。獲取到 Provider URL 之后,Consumer 會(huì)根據(jù)負(fù)載均衡算法從多個(gè) Provider 中選擇一個(gè) Provider 并與其建立連接,最后發(fā)起對(duì) ProviderRPC 調(diào)用。如果 Provider URL 發(fā)生變更,Consumer 將會(huì)通過(guò)之前訂閱過(guò)程中在注冊(cè)中心添加的監(jiān)聽器,獲取到最新的 Provider URL 信息,進(jìn)行相應(yīng)的調(diào)整,比如斷開與宕機(jī) Provider 的連接,并與新的 Provider 建立連接。Consumer 與 Provider 建立的是長(zhǎng)連接,且 Consumer 會(huì)緩存 Provider 信息,所以一旦連接建立,即使注冊(cè)中心宕機(jī),也不會(huì)影響已運(yùn)行的 ProviderConsumer。

          Monitor

          監(jiān)控中心。用于統(tǒng)計(jì)服務(wù)的調(diào)用次數(shù)和調(diào)用時(shí)間。ProviderConsumer 在運(yùn)行過(guò)程中,會(huì)在內(nèi)存中統(tǒng)計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。監(jiān)控中心在上面的架構(gòu)圖中并不是必要角色,監(jiān)控中心宕機(jī)不會(huì)影響 Provider、Consumer 以及 Registry 的功能,只會(huì)丟失監(jiān)控?cái)?shù)據(jù)而已。

          猥瑣發(fā)育,后期爆發(fā),(前期可能關(guān)注的不多,但是后期它特別香)

          Container:

          服務(wù)運(yùn)行容器。是一個(gè)獨(dú)立的容器,因?yàn)榉?wù)通常不需要Tomcat、JBoss等Web容器的特性,沒必要用Web容器去加載服務(wù)。服務(wù)容器只是一個(gè)簡(jiǎn)單的main方法,并加載一個(gè)簡(jiǎn)單的Spring容器,用于暴露服務(wù)。

          流程說(shuō)明

          在上面這張圖中,有幾個(gè)角色,并且還畫了很多線條,下面我們對(duì)此做一個(gè)簡(jiǎn)單說(shuō)明。

          • 服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
          • 服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
          • 服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
          • 注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長(zhǎng)連接推送變更數(shù)據(jù)給消費(fèi)者。
          • 服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
          • 服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。

          Dubbo官網(wǎng)

          Dubbo的官網(wǎng):https://dubbo.apache.org/

          由于Dubbo是由阿里巴巴技術(shù)團(tuán)隊(duì)開發(fā)的,所以,文檔方面對(duì)于咱們中國(guó)人來(lái)說(shuō)那是相當(dāng)?shù)挠押?,一個(gè)字:爽!

          另外,Dubbo官網(wǎng)上很多東西,我們就不在這里一一介紹了。

          建議大家都去官網(wǎng)逛逛。

          話不多說(shuō),咱們先來(lái)嗨一把!

          demo案例1

          我們先來(lái)搞一個(gè)沒有注冊(cè)中心的案例。

          我們搭建一個(gè)項(xiàng)目,并創(chuàng)建三個(gè)module

          • dubbo-demo
          • dubbo-demo-api
          • dubbo-demo-provider
          • dubbo-demo-consumer

          項(xiàng)目整體結(jié)構(gòu)如下:

          下面,我們來(lái)代碼做一個(gè)簡(jiǎn)單說(shuō)明。

          首先是pom依賴:


          <dependency>
          ?????<groupId>org.apache.dubbogroupId>
          ?????<artifactId>dubboartifactId>
          ?????<version>3.0.4version>
          dependency>

          <dependency>
          ?????<groupId>com.tian.dubbogroupId>
          ?????<artifactId>dubbo-demo-apiartifactId>
          ?????<version>1.0-SNAPSHOTversion>
          dependency>

          consumer和provider項(xiàng)目都需要添加這兩個(gè)依賴。

          api

          api主要是定義服務(wù)接口以及一些工具類,主要是供consumer和provider共用。

          在api中我們只定義了一個(gè)服務(wù)接口:DemoService

          package?com.tian.dubbo.service;

          public?interface?DemoService?{
          ????String?sayHello(String?msg);
          }

          然后打成jar,在consumer和provider項(xiàng)目中添加到pom.xml依賴?yán)?,最后兩遍都可以使用了?/p>

          provider

          在resources目錄下創(chuàng)建一個(gè)目錄META-INF.spring,然后在目錄下創(chuàng)建一個(gè)application.xml,內(nèi)容如下:


          <beans?xmlns="http://www.springframework.org/schema/beans"
          ???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          ???????xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
          ???????xsi:schemaLocation="http://www.springframework.org/schema/beans????????http://www.springframework.org/schema/beans/spring-beans.xsd????????http://code.alibabatech.com/schema/dubbo????????http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

          ?????
          ????<dubbo:application?name="dubbo-provider"/>
          ?????
          ????<dubbo:registry?address="N/A"/>
          ?????
          ????<dubbo:protocol?name="dubbo"?port="20880"/>
          ?????
          ????<dubbo:service?interface="com.tian.dubbo.service.DemoService"?ref="demoService"/>
          ????<bean?id="demoService"?class="com.tian.dubbo.service.DemoServiceImpl"/>
          beans>

          再在resources目錄下創(chuàng)建一個(gè)日志打印的配置文件:log4j.properties

          ###set log levels###
          log4j.rootLogger=debug, stdout
          ###output to the console###
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.Target=System.out
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n

          在定義一個(gè)業(yè)務(wù)實(shí)現(xiàn)類:DemoServiceImpl

          package?com.tian.dubbo.service;

          public?class?DemoServiceImpl?implements?DemoService?{
          ????public?String?sayHello(String?msg)?{
          ????????System.out.println("msg=?"?+?msg);
          ????????return?"SUCCESS";
          ????}
          }

          再就是定義一個(gè)provider的啟動(dòng)類:ProviderMain

          package?com.tian.dubbo;

          import?org.apache.dubbo.container.Main;

          public?class?ProviderMain?{
          ????public?static?void?main(String[]?args)?{
          ????????Main.main(args);
          ????}
          }

          注意:這里的Main類是Dubbo

          最后,我們啟動(dòng)ProviderMain類,日志輸出:

          好了,已經(jīng)啟動(dòng)成功了。

          我們繼續(xù)來(lái)看看consumer項(xiàng)目,在項(xiàng)目中,也就是調(diào)用我們服務(wù)的項(xiàng)目。

          consumer

          在consumer項(xiàng)目中application.xml配置文件和provider有所區(qū)別。


          <beans?xmlns="http://www.springframework.org/schema/beans"
          ???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          ???????xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
          ???????xsi:schemaLocation="http://www.springframework.org/schema/beans????????http://www.springframework.org/schema/beans/spring-beans.xsd????????http://code.alibabatech.com/schema/dubbo????????http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

          ????
          ????<dubbo:application?name="dubbo-consumer"/>
          ?????
          ????
          ????<dubbo:reference?id="demoService"
          ?????????????????????interface="com.tian.dubbo.service.DemoService"
          ?????url="dubbo://127.0.0.1:20880/com.tian.dubbo.service.DemoService"/>

          beans>

          這個(gè)url地址,我們?cè)趐rovider啟動(dòng)的時(shí)候,可以從日志中找到。

          日志文件和provider一樣,然后就是ConsumerMain啟動(dòng)類了。

          package?com.tian.dubbo;

          import?com.tian.dubbo.service.DemoService;
          import?org.springframework.context.ApplicationContext;
          import?org.springframework.context.support.ClassPathXmlApplicationContext;

          public?class?ConsumerMain?{
          ????public?static?void?main(String[]?args)?{
          ????????DemoService?demoService?=?null;
          ????????ApplicationContext?context?=?new?ClassPathXmlApplicationContext
          ????????????????("classpath:META-INF/spring/application.xml");
          ????????demoService?=?context.getBean(DemoService.class);
          ????????//調(diào)用服務(wù)
          ????????System.out.println(demoService.sayHello("tian"));
          ????}
          }

          前面,我們已經(jīng)把provider成功啟動(dòng)了,下面我們就來(lái)啟動(dòng)ConsumerMain

          從日志可以看出我們已經(jīng)成功調(diào)用了provider,我們?cè)賮?lái)看看provider的日志輸出:

          也成功的輸出了我們想要的。

          到此,一個(gè)簡(jiǎn)單的入門無(wú)注冊(cè)中心(通過(guò)url直接調(diào)用)的方式就完成了。

          url在開發(fā)聯(lián)調(diào)的時(shí)候還是很擁有的哦,因?yàn)樗鼣[脫了對(duì)注冊(cè)中心的依賴。

          demo案例2

          前面我們已經(jīng)演示完了無(wú)注冊(cè)中心,下面我們來(lái)演示有注冊(cè)中心。

          Dubbo目前差不多能支持市面上所有的注冊(cè)中心:

          • consul
          • zookeeper
          • eureka
          • redis
          • etcd
          • nacos
          • ....

          我們?cè)趯?shí)際開發(fā)中,Dubbo注冊(cè)中心大部分都是使用ZookeeperNacos

          下面?zhèn)兓?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">Zookeeper來(lái)演示(nacos類似,下面會(huì)說(shuō)到)。

          代碼層面

          我基于前面的案例進(jìn)行改造。改造只需要調(diào)整兩個(gè)地方:

          • consumer和provider中添加pom依賴
          • application.xml中添加注冊(cè)中心
          pom依賴

          我們需要在前面demo中consumer和provider的pom.xml中添加Zookeeper的依賴:

          <dependency>
          ?????<groupId>org.apache.dubbogroupId>
          ?????<artifactId>dubbo-dependencies-zookeeperartifactId>
          ?????<version>3.0.4version>
          ?????<type>pomtype>
          dependency>
          provider端

          在provider項(xiàng)目中我們需要調(diào)整:

          <dubbo:registry?address="N/A"/>

          改成:

          <dubbo:registry?address="zookeeper://127.0.0.1:2181"?timeout="10000"/>

          這個(gè)timeout建議配上,我這里其實(shí)沒必要配,因?yàn)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);">dubbo服務(wù)和Zookeeper都在我本地。

          然后我們啟動(dòng)provider項(xiàng)目:

          看到我們的項(xiàng)目已經(jīng)啟動(dòng)成功,并且已經(jīng)注冊(cè)到Zookeeper上了。

          我們可以使用Zookeeper的可視化工具,看看注冊(cè)上去的信息。

          我們?cè)倏纯碿onsumer端的調(diào)整。

          consumer端

          我們需要在application.xml中添加

          <dubbo:registry?address="zookeeper://127.0.0.1:2181"?timeout="10000"/>

          同時(shí),去掉reference中的url:

          <dubbo:reference?id="demoService"
          ?????????????????????interface="com.tian.dubbo.service.DemoService"
          ?????url="dubbo://127.0.0.1:20880/com.tian.dubbo.service.DemoService"/>

          因?yàn)槭峭ㄟ^(guò)Zookeeper注冊(cè)中心拿到地址,所以這里的url就可以去掉了。

          最后,啟動(dòng)ConsumerMain類:

          可以看到我們也成功調(diào)用服務(wù),另外也有大量的Zookeeper日志。

          到此,說(shuō)明,我們的Zookeeper為注冊(cè)中心的demo案例也成功了。

          注意:provider和consumer項(xiàng)目都需要依賴相關(guān)jar包(api、zookeeper、dubbo)

          其他

          關(guān)于Nacos,我們這里就不演示了,因?yàn)樘?jiǎn)單了,如果你把Nacos搭建好了后,直接配置就好了。

          <dubbo:registry?address="nacos://127.0.0.1:8848"?timeout="10000"/>

          就是把a(bǔ)ddress地址改一下就可以了。

          Nacos 的演示,我們下一篇文章中見。

          總結(jié)

          本文分享了Dubbo入門案例的兩個(gè)版本:無(wú)注冊(cè)中心和Zookeeper注冊(cè)中心。

          也啰嗦了一些Dubbo廢話(其實(shí)官網(wǎng)都有的)。

          好了,今天咱們就分享到這里!

          下一篇:Dubbo源碼分析:Dubbo集成Spring Boot 爽歪歪!

          喜歡的朋友,我們下一期見!

          參考:Dubbo官網(wǎng)和楊正四《Dubbo源碼解讀與實(shí)戰(zhàn)》



          推薦閱讀:

          Redis為什么變慢,一文講透如何排查Redis性能問(wèn)題

          7張圖揭曉RocketMQ存儲(chǔ)設(shè)計(jì)的精髓

          騰訊二面:Redis 事務(wù)支持 ACID 么?

          聊聊分布式鎖——Redis和Redisson的方式

          關(guān)號(hào)互聯(lián)網(wǎng)全棧架構(gòu),價(jià)

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一级特黄色aa大片 | 欧美老熟妇XX | www.999国产精品乱伦 | 小日本一级黄色电影 | 无码国产精品一区二区三 |