免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Dubbo系列-揚帆起航

前言

接下來一段時間敖丙將帶大家開啟緊張刺激的 Dubbo 之旅!是的要開始寫 Dubbo 系列的文章了,之前我已經(jīng)寫過一篇架構(gòu)演進的文章,也說明了微服務(wù)的普及化以及重要性,服務(wù)化場景下隨之而來的就是服務(wù)之間的通信問題,那服務(wù)間的通信腦海中想到的就是 RPC,說到 RPC 就離不開咱們的 Dubbo。

這篇文章敖丙先帶著大家來總覽全局,一般而言熟悉一個框架你要先知道這玩意是做什么的,能解決什么痛點,核心的模塊是什么,大致運轉(zhuǎn)流程是怎樣的。

你要一來就扎入細節(jié)之中無法自拔,一波 DFS 直接被勸退的可能性高達99.99%,所以本暖男敖丙將帶大家先過一遍 Dubbo 的簡介、總體分層、核心組件以及大致調(diào)用流程。

不僅如此我還會帶著大家過一遍如果要讓你設(shè)計一個 RPC 框架你看看都需要什么功能?這波操作之后你會發(fā)現(xiàn)嘿嘿 Dubbo 怎么設(shè)計的和我想的一樣呢?真是英雄所見略同啊!

而且我還會寫一個簡單版 RPC 框架實現(xiàn),讓大家明白 RPC 到底是如何工作的。

如果看了這篇文章你要還是不知道 Dubbo 是啥,我可以要勸退了。

我們先來談一談什么叫 RPC ,我發(fā)現(xiàn)有很多同學不太了解這個概念,還有人把 RPC 和 HTTP 來進行對比。所以咱們先來說說什么是 RPC。

什么是 RPC

RPC,Remote Procedure Call 即遠程過程調(diào)用,遠程過程調(diào)用其實對標的是本地過程調(diào)用,本地過程調(diào)用你熟悉吧?

想想那青蔥歲月,你在大學趕著期末大作業(yè),正在攻克圖書管理系統(tǒng),你奮筆疾書瘋狂地敲擊鍵盤,實現(xiàn)了圖書借閱、圖書歸還等等模塊,你實現(xiàn)的一個個方法之間的調(diào)用就叫本地過程調(diào)用。

你要是和我說你實現(xiàn)圖書館里系統(tǒng)已經(jīng)用了服務(wù)化,搞了遠程調(diào)用了,我只能和你說你有點東西。

簡單的說本機上內(nèi)部的方法調(diào)用都可以稱為本地過程調(diào)用,而遠程過程調(diào)用實際上就指的是你本地調(diào)用了遠程機子上的某個方法,這就是遠程過程調(diào)用。

所以說 RPC 對標的是本地過程調(diào)用,至于 RPC 要如何調(diào)用遠程的方法可以走 HTTP、也可以是基于 TCP 自定義協(xié)議。

所以說你討論 RPC 和 HTTP 就不是一個層級的東西。

RPC 框架就是要實現(xiàn)像那小助手一樣的東西,目的就是讓我們使用遠程調(diào)用像本地調(diào)用一樣簡單方便,并且解決一些遠程調(diào)用會發(fā)生的一些問題,使用戶用的無感知、舒心、放心、順心,它好我也好,快樂沒煩惱。

如何設(shè)計一個 RPC 框架

在明確了什么是 RPC,以及 RPC 框架的目的之后,咱們想想如果讓你做一款 RPC 框架你該如何設(shè)計?

服務(wù)消費者

我們先從消費者方(也就是調(diào)用方)來看需要些什么,首先消費者面向接口編程,所以需要得知有哪些接口可以調(diào)用,可以通過公用 jar 包的方式來維護接口。

現(xiàn)在知道有哪些接口可以調(diào)用了,但是只有接口啊,具體的實現(xiàn)怎么來?這事必須框架給處理了!所以還需要來個代理類,讓消費者只管調(diào),啥事都別管了,我代理幫你搞定

對了,還需要告訴代理,你調(diào)用的是哪個方法,并且參數(shù)的值是什么。

雖說代理幫你搞定但是代理也需要知道它到底要調(diào)哪個機子上的遠程方法,所以需要有個注冊中心,這樣調(diào)用方從注冊中心可以知曉可以調(diào)用哪些服務(wù)提供方,一般而言提供方不止一個,畢竟只有一個掛了那不就沒了。

所以提供方一般都是集群部署,那調(diào)用方需要通過負載均衡來選擇一個調(diào)用,可以通過某些策略例如同機房優(yōu)先調(diào)用啊啥的。

當然還需要有容錯機制,畢竟這是遠程調(diào)用,網(wǎng)絡(luò)是不可靠的,所以可能需要重試什么的。

還要和服務(wù)提供方約定一個協(xié)議,例如我們就用 HTTP 來通信就好啦,也就是大家要講一樣的話,不然可能聽不懂了。

當然序列化必不可少,畢竟我們本地的結(jié)構(gòu)是“立體”的,需要序列化之后才能傳輸,因此還需要約定序列化格式

并且這過程中間可能還需要摻入一些 Filter,來作一波統(tǒng)一的處理,例如調(diào)用計數(shù)啊等等。

這些都是框架需要做的,讓消費者像在調(diào)用本地方法一樣,無感知。

服務(wù)提供者

服務(wù)提供者肯定要實現(xiàn)對應的接口這是毋庸置疑的。

然后需要把自己的接口暴露出去,向注冊中心注冊自己,暴露自己所能提供的服務(wù)。

然后有消費者請求過來需要處理,提供者需要用和消費者協(xié)商好的協(xié)議來處理這個請求,然后做反序列化。

序列化完的請求應該扔到線程池里面做處理,某個線程接受到這個請求之后找到對應的實現(xiàn)調(diào)用,然后再將結(jié)果原路返回。

注冊中心

上面其實我們都提到了注冊中心,這東西就相當于一個平臺,大家在上面暴露自己的服務(wù),也在上面得知自己能調(diào)用哪些服務(wù)。

當然還能做配置中心,將配置集中化處理,動態(tài)變更通知訂閱者。

監(jiān)控運維

面對眾多的服務(wù),精細化的監(jiān)控和方便的運維必不可少。

這點很多開發(fā)者在開發(fā)的時候察覺不到,到你真正上線開始運行維護的時候,如果沒有良好的監(jiān)控措施,快速的運維手段,到時候就是睜眼瞎!手足無措,等著挨批把!

那種痛苦不要問我為什么知道,我就是知道!

小結(jié)一下

讓我們小結(jié)一下,大致上一個 RPC 框架需要做的就是約定要通信協(xié)議,序列化的格式、一些容錯機制、負載均衡策略、監(jiān)控運維和一個注冊中心!

簡單實現(xiàn)一個 RPC 框架

沒錯就是簡單的實現(xiàn),上面我們在思考如何設(shè)計一個 RPC 框架的時候想了很多,那算是生產(chǎn)環(huán)境使用級別的功能需求了,我們這是 Demo,目的是突出 RPC框架重點功能 - 實現(xiàn)遠程調(diào)用。

所以啥七七八八的都沒,并且我用偽代碼來展示,其實也就是刪除了一些保護性和約束性的代碼,因為看起來太多了不太直觀,需要一堆 try-catch 啥的,因此我刪減了一些,直擊重點。

Let's Do It!

首先我們定義一個接口和一個簡單實現(xiàn)。

public interface AobingService {  
    String hello(String name);  


public class AobingServiceImpl implements AobingService {  
    public String hello(String name) {  
        return 'Yo man Hello,I am' + name;  
    }  
}  

然后我們再來實現(xiàn)服務(wù)提供者暴露服務(wù)的功能。

public class AobingRpcFramework 
     public static void export(Object service, int port) throws Exception 
          ServerSocket server = new ServerSocket(port);
          while(true) {
              Socket socket = server.accept();
              new Thread(new Runnable() {
                  //反序列化
                  ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 
                  String methodName = input.read(); //讀取方法名
                  Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); //參數(shù)類型
                  Object[] arguments = (Object[]) input.readObject(); //參數(shù)
                  Method method = service.getClass().getMethod(methodName, parameterTypes);  //找到方法
                  Object result = method.invoke(service, arguments); //調(diào)用方法
                  // 返回結(jié)果
                  ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                  output.writeObject(result);
              }).start();
          }
     }
    public static <T> refer (Class<T> interfaceClass, String host, int port) throws Exception {
       return  (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, 
            new InvocationHandler() {  
                public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {  
                    Socket socket = new Socket(host, port);  //指定 provider 的 ip 和端口
                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 
                    output.write(method.getName());  //傳方法名
                    output.writeObject(method.getParameterTypes());  //傳參數(shù)類型
                    output.writeObject(arguments);  //傳參數(shù)值
                    ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
                    Object result = input.readObject();  //讀取結(jié)果
                    return result;  
               }
        });  
    }  
}

好了,這個 RPC 框架就這樣好了,是不是很簡單?就是調(diào)用者傳遞了方法名、參數(shù)類型和參數(shù)值,提供者接收到這樣參數(shù)之后調(diào)用對于的方法返回結(jié)果就好了!這就是遠程過程調(diào)用。

我們來看看如何使用

        //服務(wù)提供者只需要暴露出接口
       AobingService service = new AobingServiceImpl ();  
       AobingRpcFramework.export(service, 2333);  

       //服務(wù)調(diào)用者只需要設(shè)置依賴
       AobingService service = AobingRpcFramework.refer(AobingService.class, '127.0.0.1'2333);  
       service.hello(); 

看起來好像好不錯喲,不過這很是簡陋,用作 demo 有助理解還是極好的!

接下來就來看看 Dubbo 吧!上正菜!

Dubbo 簡介

Dubbo 是阿里巴巴 2011年開源的一個基于 Java 的 RPC 框架,中間沉寂了一段時間,不過其他一些企業(yè)還在用 Dubbo 并自己做了擴展,比如當當網(wǎng)的 Dubbox,還有網(wǎng)易考拉的 Dubbok。

但是在 2017 年阿里巴巴又重啟了對 Dubbo 維護。在 2017 年榮獲了開源中國 2017 最受歡迎的中國開源軟件 Top 3。

在 2018 年和 Dubbox 進行了合并,并且進入 Apache 孵化器,在 2019 年畢業(yè)正式成為 Apache 頂級項目。

目前 Dubbo 社區(qū)主力維護的是 2.6.x 和 2.7.x 兩大版本,2.6.x 版本主要是 bug 修復和少量功能增強為準,是穩(wěn)定版本。

而 2.7.x 是主要開發(fā)版本,更新和新增新的 feature 和優(yōu)化,并且 2.7.5 版本的發(fā)布被 Dubbo 認為是里程碑式的版本發(fā)布,之后我們再做分析。

它實現(xiàn)了面向接口的代理 RPC 調(diào)用,并且可以配合 ZooKeeper 等組件實現(xiàn)服務(wù)注冊和發(fā)現(xiàn)功能,并且擁有負載均衡、容錯機制等。

Dubbo 總體架構(gòu)

我們先來看下官網(wǎng)的一張圖。

本丙再暖心的給上圖內(nèi)每個節(jié)點的角色說明一下。

節(jié)點角色說明
Consumer需要調(diào)用遠程服務(wù)的服務(wù)消費方
Registry注冊中心
Provider服務(wù)提供方
Container服務(wù)運行的容器
Monitor監(jiān)控中心

我再來大致說一下整體的流程,首先服務(wù)提供者 Provider 啟動然后向注冊中心注冊自己所能提供的服務(wù)。

服務(wù)消費者 Consumer 啟動向注冊中心訂閱自己所需的服務(wù)。然后注冊中心將提供者元信息通知給 Consumer, 之后 Consumer 因為已經(jīng)從注冊中心獲取提供者的地址,因此可以通過負載均衡選擇一個 Provider 直接調(diào)用

之后服務(wù)提供方元數(shù)據(jù)變更的話注冊中心會把變更推送給服務(wù)消費者。

服務(wù)提供者和消費者都會在內(nèi)存中記錄著調(diào)用的次數(shù)和時間,然后定時的發(fā)送統(tǒng)計數(shù)據(jù)到監(jiān)控中心。

一些注意點

首先注冊中心和監(jiān)控中心是可選的,你可以不要監(jiān)控,也不要注冊中心,直接在配置文件里面寫然后提供方和消費方直連。

然后注冊中心、提供方和消費方之間都是長連接,和監(jiān)控方不是長連接,并且消費方是直接調(diào)用提供方,不經(jīng)過注冊中心

就算注冊中心和監(jiān)控中心宕機了也不會影響到已經(jīng)正常運行的提供者和消費者,因為消費者有本地緩存提供者的信息。

Dubbo 分層架構(gòu)

總的而言 Dubbo 分為三層,如果每一層再細分下去,一共有十層。別怕也就十層,本丙帶大家過一遍,大家先有個大致的印象,之后的文章丙會帶著大家再深入。

大的三層分別為 Business(業(yè)務(wù)層)、RPC 層、Remoting,并且還分為 API 層和 SPI 層。

分為大三層其實就是和我們知道的網(wǎng)絡(luò)分層一樣的意思,只有層次分明,職責邊界清晰才能更好的擴展。

而分 API 層和 SPI 層這是 Dubbo 成功的一點,采用微內(nèi)核設(shè)計+SPI擴展,使得有特殊需求的接入方可以自定義擴展,做定制的二次開發(fā)。

接下來咱們再來看看每一層都是干嘛的。

  • Service,業(yè)務(wù)層,就是咱們開發(fā)的業(yè)務(wù)邏輯層。

  • Config,配置層,主要圍繞 ServiceConfig 和 ReferenceConfig,初始化配置信息。

  • Proxy,代理層,服務(wù)提供者還是消費者都會生成一個代理類,使得服務(wù)接口透明化,代理層做遠程調(diào)用和返回結(jié)果。

  • Register,注冊層,封裝了服務(wù)注冊和發(fā)現(xiàn)。

  • Cluster,路由和集群容錯層,負責選取具體調(diào)用的節(jié)點,處理特殊的調(diào)用要求和負責遠程調(diào)用失敗的容錯措施。

  • Monitor,監(jiān)控層,負責監(jiān)控統(tǒng)計調(diào)用時間和次數(shù)。

  • Portocol,遠程調(diào)用層,主要是封裝 RPC 調(diào)用,主要負責管理 Invoker,Invoker代表一個抽象封裝了的執(zhí)行體,之后再做詳解。

  • Exchange,信息交換層,用來封裝請求響應模型,同步轉(zhuǎn)異步。

  • Transport,網(wǎng)絡(luò)傳輸層,抽象了網(wǎng)絡(luò)傳輸?shù)慕y(tǒng)一接口,這樣用戶想用 Netty 就用 Netty,想用 Mina 就用 Mina。

  • Serialize,序列化層,將數(shù)據(jù)序列化成二進制流,當然也做反序列化。

SPI

我再稍微提一下 SPI(Service Provider Interface),是 JDK 內(nèi)置的一個服務(wù)發(fā)現(xiàn)機制,它使得接口和具體實現(xiàn)完全解耦。我們只聲明接口,具體的實現(xiàn)類在配置中選擇。

具體的就是你定義了一個接口,然后在META-INF/services目錄下放置一個與接口同名的文本文件,文件的內(nèi)容為接口的實現(xiàn)類,多個實現(xiàn)類用換行符分隔。

這樣就通過配置來決定具體用哪個實現(xiàn)!

而 Dubbo SPI 還做了一些改進,篇幅有限留在之后再談。

Dubbo 調(diào)用過程

上面我已經(jīng)介紹了每個層到底是干嘛的,我們現(xiàn)在再來串起來走一遍調(diào)用的過程,加深你對 Dubbo 的理解,讓知識點串起來,由點及面來一波連連看。

我們先從服務(wù)提供者開始,看看它是如何工作的。

服務(wù)暴露過程

首先 Provider 啟動,通過 Proxy 組件根據(jù)具體的協(xié)議Protocol 將需要暴露出去的接口封裝成 Invoker,Invoker 是 Dubbo 一個很核心的組件,代表一個可執(zhí)行體。

然后再通過 Exporter 包裝一下,這是為了在注冊中心暴露自己套的一層,然后將 Exporter 通過 Registry 注冊到注冊中心。這就是整體服務(wù)暴露過程。

消費過程

接著我們來看消費者調(diào)用流程(把服務(wù)者暴露的過程也在圖里展示出來了,這個圖其實算一個挺完整的流程圖了)。

首先消費者啟動會向注冊中心拉取服務(wù)提供者的元信息,然后調(diào)用流程也是從 Proxy 開始,畢竟都需要代理才能無感知。

Proxy 持有一個 Invoker 對象,調(diào)用 invoke 之后需要通過 Cluster 先從 Directory 獲取所有可調(diào)用的遠程服務(wù)的 Invoker 列表,如果配置了某些路由規(guī)則,比如某個接口只能調(diào)用某個節(jié)點的那就再過濾一遍 Invoker 列表。

剩下的 Invoker 再通過 LoadBalance 做負載均衡選取一個。然后再經(jīng)過 Filter 做一些統(tǒng)計什么的,再通過 Client 做數(shù)據(jù)傳輸,比如用 Netty 來傳輸。

傳輸需要經(jīng)過 Codec 接口做協(xié)議構(gòu)造,再序列化。最終發(fā)往對應的服務(wù)提供者。

服務(wù)提供者接收到之后也會進行 Codec 協(xié)議處理,然后反序列化后將請求扔到線程池處理。某個線程會根據(jù)請求找到對應的 Exporter ,而找到 Exporter 其實就是找到了 Invoker,但是還會有一層層 Filter,經(jīng)過一層層過濾鏈之后最終調(diào)用實現(xiàn)類然后原路返回結(jié)果。

完成整個調(diào)用過程!

總結(jié)

這次敖丙帶著大家先了解了下什么是 RPC,然后規(guī)劃了一波 RPC 框架需要哪些組件,然后再用代碼實現(xiàn)了一個簡單的 RPC 框架。

然后帶著大家了解了下 Dubbo 的發(fā)展歷史、總體架構(gòu)、分層設(shè)計架構(gòu)以及每個組件是干嘛的,再帶著大伙走了一遍整體調(diào)用過程。

我真的是太暖了啊!

dubbo近期我會安排幾個章節(jié)繼續(xù)展開,最后會出一個面試版本的dubbo,我們拭目以待吧。

我是敖丙,你知道的越多,你不知道的越多,我們下期見!

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Dubbo常見題目
淺談服務(wù)治理、微服務(wù)與Service Mesh(一)Dubbo的前世今生
《我想進大廠》之Dubbo普普通通9問
幾種微服務(wù)框架調(diào)研報告
測試開發(fā):自學Dubbo+Python經(jīng)驗總結(jié)分享
簡單之美 | Dubbo架構(gòu)設(shè)計詳解
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服