日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

大白话带你梳理一下Dubbo的那些事儿

發(fā)布時(shí)間:2025/3/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大白话带你梳理一下Dubbo的那些事儿 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

RPC服務(wù)的介紹

相信有過(guò)一些分布式開(kāi)發(fā)經(jīng)歷的讀者都有用過(guò)一些RPC框架,通過(guò)框架包裝好之后提供的API接口調(diào)用遠(yuǎn)程服務(wù),體驗(yàn)感覺(jué)起來(lái)就和調(diào)用本地服務(wù)一樣輕松。這么方便好用的技術(shù)框架,在實(shí)際的開(kāi)發(fā)過(guò)程中是如何包裝的呢?

很早的時(shí)候,國(guó)外的工程師設(shè)計(jì)了一種能夠通過(guò)A計(jì)算機(jī)調(diào)用B計(jì)算機(jī)上邊應(yīng)用程序的技術(shù),這種技術(shù)不需要開(kāi)發(fā)人員對(duì)于網(wǎng)絡(luò)通訊了解過(guò)多,并且調(diào)用其他機(jī)器上邊程序的時(shí)候和調(diào)用本地的程序一樣方便好用。

A機(jī)器發(fā)起請(qǐng)求去調(diào)用B機(jī)器程序的時(shí)候會(huì)被掛起,B機(jī)器接收到A機(jī)器發(fā)起的請(qǐng)求參數(shù)之后會(huì)做一定的參數(shù)轉(zhuǎn)換,最后將對(duì)應(yīng)的程序結(jié)果返回給A,這就是最原始的RPC服務(wù)調(diào)用了。

RPC調(diào)用的優(yōu)勢(shì)

簡(jiǎn)單

不需要開(kāi)發(fā)者對(duì)于網(wǎng)絡(luò)通信做過(guò)多的設(shè)置,例如我們?cè)谑褂胔ttp協(xié)議進(jìn)行遠(yuǎn)程接口調(diào)用的時(shí)候,總是會(huì)需要編寫(xiě)較多的http協(xié)議參數(shù)(header,context,Accept-Language,Accept-Encode等等),這些處理對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),實(shí)際上都并不是特別友好。但是RPC服務(wù)調(diào)用框架通常都將這類(lèi)解析進(jìn)行了對(duì)應(yīng)的封裝,大大降低了開(kāi)發(fā)人員的使用難度。

高效

在網(wǎng)絡(luò)傳輸方面,RPC更多是處于應(yīng)用層和傳輸層之間。這里我們需要先理清楚一個(gè)問(wèn)題,網(wǎng)絡(luò)分層。RPC是處于會(huì)話(huà)層的部分,相比處于應(yīng)用層的HTTP而言,RPC要比Rest服務(wù)調(diào)用更加輕便。

常見(jiàn)的遠(yuǎn)程調(diào)用技術(shù)

rmi

利用java.rmi包實(shí)現(xiàn),基于Java遠(yuǎn)程方法協(xié)議(Java Remote Method Protocol) 和java的原生序列化

Hessian

是一個(gè)輕量級(jí)的remoting onhttp工具,使用簡(jiǎn)單的方法提供了RMI的功能。基于HTTP協(xié)議,采用二進(jìn)制編解碼。

protobuf-rpc-pro

是一個(gè)Java類(lèi)庫(kù),提供了基于 Google 的 Protocol Buffers 協(xié)議的遠(yuǎn)程方法調(diào)用的框架。基于 Netty 底層的 NIO 技術(shù)。支持 TCP 重用/ keep-alive、SSL加密、RPC 調(diào)用取消操作、嵌入式日志等功能。

Thrift

是一種可伸縮的跨語(yǔ)言服務(wù)的軟件框架。它擁有功能強(qiáng)大的代碼生成引擎,無(wú)縫地支持C + +,C#,Java,Python和PHP和Ruby。thrift允許你定義一個(gè)描述文件,描述數(shù)據(jù)類(lèi)型和服務(wù)接口。依據(jù)該文件,編譯器方便地生成RPC客戶(hù)端和服務(wù)器通信代碼。

最初由facebook開(kāi)發(fā)用做系統(tǒng)內(nèi)部語(yǔ)言之間的RPC通信,2007年由facebook貢獻(xiàn)到apache基金 ,現(xiàn)在是apache下的opensource之一 。支持多種語(yǔ)言之間的RPC方式的通信:php語(yǔ)言client可以構(gòu)造一個(gè)對(duì)象,調(diào)用相應(yīng)的服務(wù)方法來(lái)調(diào)用java語(yǔ)言的服務(wù),跨越語(yǔ)言的C/S RPC調(diào)用。底層通訊基于SOCKET。

Avro

出自Hadoop之父Doug Cutting, 在Thrift已經(jīng)相當(dāng)流行的情況下推出Avro的目標(biāo)不僅是提供一套類(lèi)似Thrift的通訊中間件,更是要建立一個(gè)新的,標(biāo)準(zhǔn)性的云計(jì)算的數(shù)據(jù)交換和存儲(chǔ)的Protocol。支持HTTP,TCP兩種協(xié)議。

Dubbo

Dubbo是 阿里巴巴公司開(kāi)源的一個(gè)高性能優(yōu)秀的服務(wù)框架,使得應(yīng)用可通過(guò)高性能的 RPC 實(shí)現(xiàn)服務(wù)的輸出和輸入功能,可以和 Spring框架無(wú)縫集成。

上邊我們說(shuō)到了RPC的遠(yuǎn)程調(diào)用發(fā)展歷史,那么下邊我們一起來(lái)深入探討一下RPC的服務(wù)。

首先我們來(lái)看看OSI的網(wǎng)絡(luò)協(xié)議內(nèi)容。

OSI的七層網(wǎng)絡(luò)模型

對(duì)于OSI的七層網(wǎng)絡(luò)模型我繪制了下邊的這么一張圖:


下邊是我個(gè)人對(duì)于這七層協(xié)議的理解:

  • 應(yīng)用層?主要是對(duì)于服務(wù)接口的格式多定義,例如提供一定的終端接口暴露給外部應(yīng)用調(diào)用。

  • 表示層?處理一些數(shù)據(jù)傳輸?shù)母袷睫D(zhuǎn)換,例如說(shuō)編碼的統(tǒng)一,加密和解密處理。

  • 會(huì)話(huà)層?管理用戶(hù)的會(huì)話(huà)和對(duì)話(huà),建立不同機(jī)器之間的會(huì)話(huà)連接。

  • 傳輸層?向網(wǎng)絡(luò)層提供可靠有序的數(shù)據(jù)包信息。

  • 網(wǎng)絡(luò)層?真正發(fā)送數(shù)據(jù)包信息的層面,提供流和擁塞控制,從而降低網(wǎng)絡(luò)的資源損耗。

  • 數(shù)據(jù)鏈路層?封裝對(duì)應(yīng)的數(shù)據(jù)包,檢測(cè)和糾正數(shù)據(jù)包傳輸信息。

  • 物理層?通過(guò)網(wǎng)絡(luò)通訊設(shè)備發(fā)送數(shù)據(jù)

HTTP & RPC

HTTP主要是位于TCP/IP協(xié)議棧的應(yīng)用層部分,首先需要構(gòu)建三次握手的鏈接,接著才能進(jìn)行數(shù)據(jù)信息的請(qǐng)求發(fā)送,最后進(jìn)行四次揮手?jǐn)嚅_(kāi)鏈接。

RPC在請(qǐng)求的過(guò)程中跨越了傳輸層和應(yīng)用層,這是因?yàn)樗旧硎且蕾?lài)于Socket的原因。(再深入的原因我也不知道)。減少了上邊幾層的封裝,RPC的請(qǐng)求效率自然是要比HTTP高效很多。

那么一個(gè)完整的RPC調(diào)用應(yīng)該包含哪些部分呢?

通常我們將一個(gè)完整的RPC架構(gòu)分為了以下幾個(gè)核心組件:

  • Server

  • Client

  • Server Stub

  • Client Stub

這四個(gè)模塊中我稍微說(shuō)下stub吧。這個(gè)單詞翻譯過(guò)來(lái)稱(chēng)之為存根。

Client Stub 就是將客戶(hù)端請(qǐng)求的參數(shù),服務(wù)名稱(chēng),服務(wù)地址進(jìn)行打包,統(tǒng)一發(fā)送給server方。

Server Stub 我用通俗易懂的語(yǔ)言來(lái)解釋就是服務(wù)端接收到Client發(fā)送的數(shù)據(jù)之后進(jìn)行消息解包,調(diào)用本地方法。(看過(guò)netty拆包機(jī)制應(yīng)該會(huì)對(duì)這塊比較了解)。

Dubbo的核心屬性

其實(shí)Dubbo配置里面的核心內(nèi)容就是 服務(wù)暴露,服務(wù)發(fā)現(xiàn),服務(wù)治理

什么是服務(wù)暴露,服務(wù)發(fā)現(xiàn),服務(wù)治理?

下邊我們用一段xml的配置來(lái)進(jìn)行講解:

<?xml?version="1.0"?encoding="UTF-8"?> <beans?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://code.alibabatech.com/schema/dubbo?http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><dubbo:application?name="dubbo-invoker-provider"><dubbo:parameter?key="qos.port"?value="22222"/></dubbo:application><dubbo:registry?address="zookeeper://127.0.0.1:2181"/><dubbo:protocol?name="dubbo"?port="20880"/><bean?id="userService"?class="com.sise.user.service.UserServiceImpl"?/><dubbo:service?interface="com.sise.user.service.UserService"?ref="userService"?/> </beans>

在dubbo的配置文件里面,通常我們所說(shuō)的dubbo:service 可以理解為服務(wù)暴露,dubbo:refernce 為服務(wù)發(fā)現(xiàn),mock是服務(wù)治理,timeout屬于服務(wù)治理的一種(性能調(diào)優(yōu)).

假設(shè)dubbo里面希望將一些公共的配置抽取出來(lái),我們可以通過(guò)properties文件進(jìn)行配置,dubbo在加載配置文件的優(yōu)先順序如下:

  • 優(yōu)先會(huì)讀取JVM -D啟動(dòng)參數(shù)后邊的內(nèi)容

  • 讀取xml配置文件

  • 讀取properties配置文件內(nèi)容

  • dubbo默認(rèn)會(huì)讀取dubbo.properties配置文件的信息,例如下邊這種配置:

    dubbo.application.name=dubbo-user-service dubbo.registry.address=zookeeper://127.0.0.1:2181

    假設(shè)我們的dubbo配置文件不命名為dubbo.properties(假設(shè)命名為了my-dubbo.properties)的時(shí)候,可以在啟動(dòng)參數(shù)的后邊加上這么一段指令:

    ?-Ddubbo.properties.file=my-dubbo.properties

    那么在應(yīng)用程序啟動(dòng)之后,對(duì)應(yīng)的工程就會(huì)讀取指定的配置文件,這樣就可以將一些共用的dubbo配置給抽取了出來(lái)。

    XML和配置類(lèi)的映射

    在工作中,我們通常都會(huì)通過(guò)配置xml的方式來(lái)設(shè)定一個(gè)服務(wù)端暴露的服務(wù)接口和消費(fèi)端需要調(diào)用的服務(wù)信息,這些配置的xml實(shí)際上在dubbo的源碼中都會(huì)被解析為對(duì)應(yīng)的實(shí)體類(lèi)對(duì)象。

    例如說(shuō)我們常用到的reference配置類(lèi),下邊我貼出一段代碼:

    package?com.sise.user.config; import?com.sise.user.service.UserService; import?com.sise.user.service.UserServiceImpl; import?org.apache.dubbo.config.*; import?java.io.IOException; import?java.util.concurrent.CountDownLatch; /***?dubbo里面的自定義配置類(lèi)**?@author?idea*?@data?2019/12/29*/ public?class?DubboSelfDefConfig?{/***?dubbo的服務(wù)暴露*/public?void?server()?{ApplicationConfig?applicationConfig?=?new?ApplicationConfig();applicationConfig.setName("dubbo-server-config");RegistryConfig?registryConfig?=?new?RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");ProtocolConfig?protocolConfig?=?new?ProtocolConfig();protocolConfig.setName("dubbo");protocolConfig.setPort(20880);protocolConfig.setThreads(200);UserService?userService?=?new?UserServiceImpl();ServiceConfig<UserService>?serviceConfig?=?new?ServiceConfig<>();serviceConfig.setApplication(applicationConfig);serviceConfig.setRegistry(registryConfig);serviceConfig.setProtocol(protocolConfig);serviceConfig.setInterface(UserService.class);serviceConfig.setRef(userService);serviceConfig.export();}public?void?consumer()?{ApplicationConfig?applicationConfig?=?new?ApplicationConfig();applicationConfig.setName("dubbo-client-config");RegistryConfig?registryConfig?=?new?RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");ReferenceConfig<UserService>?referenceConfig?=?new?ReferenceConfig<>();referenceConfig.setApplication(applicationConfig);referenceConfig.setRegistry(registryConfig);referenceConfig.setInterface(UserService.class);UserService?localRef?=?referenceConfig.get();localRef.echo("idea");}public?static?void?main(String[]?args)?throws?InterruptedException,?IOException?{DubboSelfDefConfig?d?=?new?DubboSelfDefConfig();d.consumer();CountDownLatch?countDownLatch?=?new?CountDownLatch(1);countDownLatch.await();} }

    在這段代碼里面,通過(guò)案例可以發(fā)現(xiàn)有這些信息內(nèi)容:

    ????UserService?localRef?=?referenceConfig.get();localRef.echo("idea");

    這兩行語(yǔ)句是獲取具體服務(wù)的核心之處,由于我在別處定義了一個(gè)叫做UserService 的公共服務(wù)接口,因此在服務(wù)引用的過(guò)程中可以進(jìn)行轉(zhuǎn)換。

    Dubbo2.7的三大新特新

    Dubbo的github官方地址為 https://github.com/apache/dubbo

    在這里插入圖片描述


    Dubbo 目前有如圖所示的 5 個(gè)分支,其中 2.7.1-release 只是一個(gè)臨時(shí)分支,忽略不計(jì),對(duì)其他 4 個(gè)分支而言,我歸納了一下,分別有如下信息:

    • 2.5.x 近期已經(jīng)通過(guò)投票,Dubbo 社區(qū)即將停止對(duì)其的維護(hù)。

    • 2.6.x 為長(zhǎng)期支持的版本,也是 Dubbo 貢獻(xiàn)給 Apache 之前的版本,其包名前綴為:com.alibaba,JDK 版本對(duì)應(yīng) 1.6。

    • 3.x-dev 是前瞻性的版本,對(duì) Dubbo 進(jìn)行一些高級(jí)特性的補(bǔ)充,如支持 rx 特性。

    • master 為長(zhǎng)期支持的版本,版本號(hào)為 2.7.x,也是 Dubbo 貢獻(xiàn)給 Apache 的開(kāi)發(fā)版本,其包名前綴為:org.apache,JDK 版本對(duì)應(yīng) 1.8。

    Dubbo 2.7 新特性

    Dubbo 2.7.x 作為 Apache 的孵化版本,除了代碼優(yōu)化之外,還新增了許多重磅的新特性,本文將會(huì)介紹其中最典型的2個(gè)新特性:

    • 異步化改造

    • 三大中心改造

    異步化改造

    1.異步化調(diào)用的方式,在Dubbo2.7版本里面提供了異步化調(diào)用的功能,相關(guān)案例代碼如下所示:

    @RestController @RequestMapping(value?=?"/test") public?class?TestController?{@Reference(async?=?true)private?UserService?userService;@GetMapping("/testStr")public?String?testStr(String?param){return?userService.testEcho(param);} }

    但是通過(guò)這種異步發(fā)送的方式我們通常都是獲取不到響應(yīng)值的,所以這里的return為null。

    如果在低于2.7版本的dubbo框架中希望獲取到異步返回的響應(yīng)值還是需要通過(guò)RPC上下文來(lái)提取信息。

    代碼案例如下所示:

    ?@GetMapping("/futureGet")public?String?futureGet(String?param)?throws?ExecutionException,?InterruptedException?{userService.testEcho(param);Future<String>?future=?RpcContext.getContext().getFuture();String?result?=?future.get();System.out.println("this?is?:"+result);return?result;}

    通過(guò)RPC上下文的方式可以取到對(duì)應(yīng)的響應(yīng)值,但是這種方式需要有所等待,因此此時(shí)的效率會(huì)有所降低。假設(shè)我們將dubbo的版本提升到了2.7.1之后,通過(guò)使用CompletableFuture來(lái)進(jìn)行接口優(yōu)化的話(huà),這部分的代碼實(shí)現(xiàn)就會(huì)有所變化:

    /***?@author?idea*?@date?2019/12/31*?@Version?V1.0*/ public?interface?DemoService?{String?sayHello(String?name)?;default?CompletableFuture<String>?sayAsyncHello(String?name){return?CompletableFuture.completedFuture(sayHello(name));} }

    調(diào)用方代碼:

    package?com.sise.consumer.controller;import?com.sise.dubbo.service.DemoService; import?org.apache.dubbo.config.annotation.Reference; import?org.springframework.web.bind.annotation.RequestMapping; import?org.springframework.web.bind.annotation.RestController; import?java.util.concurrent.CompletableFuture; import?java.util.concurrent.atomic.AtomicReference; /***?@author?idea*?@date?2019/12/31*?@Version?V1.0*/ @RestController @RequestMapping(value?=?"/demo") public?class?DemoController?{@Referenceprivate?DemoService?demoService;@RequestMapping(value?=?"/testDemo")public?String?testDemo(String?name){System.out.println("【testDemo】?this?is?:"+name);return?demoService.sayHello(name);}.@RequestMapping(value?=?"/testAsyncDemo")public?String?testAsyncDemo(String?name){System.out.println("【testAsyncDemo】?this?is?:"+name);CompletableFuture<String>?future?=?demoService.sayAsyncHello(name);AtomicReference<String>?result?=?null;//通過(guò)一條callback線(xiàn)程來(lái)處理響應(yīng)的數(shù)據(jù)信息future.whenComplete((retValue,exception)->{if(exception==null){System.out.println(retValue);result.set(retValue);}?else?{exception.printStackTrace();}});return?"通過(guò)一條callback線(xiàn)程來(lái)處理響應(yīng)的數(shù)據(jù)信息,所以這個(gè)時(shí)候獲取不到信息響應(yīng)";} }

    這樣的調(diào)用是借助了callback線(xiàn)程來(lái)幫我們處理原先的數(shù)據(jù)內(nèi)容,關(guān)于dubbo里面的異步化調(diào)用,我借用了官方的一張圖來(lái)進(jìn)行展示:



    我們上邊講解的眾多方法都只是針對(duì)于dubbo的客戶(hù)端異步化,并沒(méi)有講解關(guān)于服務(wù)端的異步化處理,這是因?yàn)榻Y(jié)合dubbo的業(yè)務(wù)線(xiàn)程池模型來(lái)思考,服務(wù)端的異步化處理比較雞肋(因?yàn)閐ubbo內(nèi)部服務(wù)端的線(xiàn)程池本身就是異步化調(diào)用的了)。

    當(dāng)然dubbo 2.6 里面對(duì)于接口異步化調(diào)用的配置到了2.7版本依舊有效。

    三大中心的改造

    注冊(cè)中心

    在dubbo2.7之前,dubbo主要還是由consumer,provider ,register組成,然而在2.7版本之后,dubbo的注冊(cè)中心被拆解為了三個(gè)中心,分別是原先的注冊(cè)中心元數(shù)據(jù)中心以及配置中心

    元數(shù)據(jù)配置

    在dubbo2.7版本中,將原先注冊(cè)在zk上邊的過(guò)多數(shù)據(jù)進(jìn)行了注冊(cè)拆分,這樣能夠保證減少對(duì)于zk端的壓力。具體配置如下:

    <dubbo:registry?address=“zookeeper://127.0.0.1:2181”?simplified="true"/>

    簡(jiǎn)化了相應(yīng)配置之后,dubbo也只會(huì)上傳一些必要的服務(wù)治理數(shù)據(jù)了,簡(jiǎn)化版本的服務(wù)數(shù)據(jù)只剩下下邊這些信息:

    dubbo://30.5.120.185:20880/com.sise.TestService? application=test-provider& dubbo=2.0.2& release=2.7.0& timestamp=1554982201973

    對(duì)于其他的元數(shù)據(jù)信息將會(huì)被存儲(chǔ)到一些元數(shù)據(jù)中心里面,例如說(shuō)redis,nacos,zk等

    元數(shù)據(jù)配置改造主要解決的問(wèn)題是:推送量大 -> 存儲(chǔ)數(shù)據(jù)量大 -> 網(wǎng)絡(luò)傳輸量大 -> 延遲嚴(yán)重

    配置中心

    dubbo2.7開(kāi)始支持多種分布式配置中心的組件。例如說(shuō):zk,Spring Cloud Config, Apollo, Nacos,關(guān)于這部分的配置網(wǎng)上的資料也比較多,我就不在這里細(xì)說(shuō)了。

    有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

    歡迎大家關(guān)注Java之道公眾號(hào)

    好文章,我在看??

    總結(jié)

    以上是生活随笔為你收集整理的大白话带你梳理一下Dubbo的那些事儿的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。