<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服務(wù)發(fā)現(xiàn)、引用過程

          共 2792字,需瀏覽 6分鐘

           ·

          2021-09-18 10:42


          前言


          這篇我們要說的服務(wù)引用,服務(wù)引用是有兩種情況的,也可以看做是兩種時(shí)機(jī),第一個(gè)是在Spring容器調(diào)用ReferenceBean的afterPropertiesSet方法時(shí)引用服務(wù),第二個(gè)就是在ReferenceBean對(duì)應(yīng)的服務(wù)被注入到其他類中時(shí)引用。這兩個(gè)引用服務(wù)的時(shí)機(jī)區(qū)別在于,第一個(gè)是餓漢式的,第二個(gè)是懶漢式的

          是不是一說餓漢和懶漢,大家順便回憶了一波單例模式

          默認(rèn)情況下,Dubbo使用懶漢式引用服務(wù)。如果需要使用餓漢式,可通過配置 <dubbo:reference> 的 init 屬性開啟。

          服務(wù)引入的三種方式:


          第一種是引用本地 (JVM) 服務(wù),上篇在服務(wù)暴露里面也說過了每個(gè)服務(wù)都會(huì)通過走injvm協(xié)議然后走本地的暴露,因?yàn)榇嬖谝粋€(gè)服務(wù)端和消費(fèi)端是同一臺(tái)機(jī)器上的情況,這樣就直接走本地調(diào)用了,不需要走遠(yuǎn)程調(diào)用了,節(jié)省網(wǎng)絡(luò)開銷

          第二是通過直連方式引用遠(yuǎn)程服務(wù),這種在線上基本不會(huì)采用這種形式的,一般都是平時(shí)我們自己測(cè)試用,直接寫死服務(wù)端的地址來調(diào)用

          第三是通過注冊(cè)中心引用遠(yuǎn)程服務(wù),Consumer 通過注冊(cè)中心得知 Provider 的相關(guān)信息,然后進(jìn)行服務(wù)的引入

          不管是哪種引用方式,最后都會(huì)得到一個(gè) Invoker 實(shí)例。如果有多個(gè)注冊(cè)中心,多個(gè)服務(wù)提供者,這個(gè)時(shí)候會(huì)得到一組 Invoker 實(shí)例,此時(shí)需要通過集群管理類 Cluster 將多個(gè) Invoker 合并成一個(gè)實(shí)例。合并后的 Invoker 實(shí)例已經(jīng)具備調(diào)用本地或遠(yuǎn)程服務(wù)的能力了

          但是呢,開發(fā)者秉承不對(duì)用戶業(yè)務(wù)代碼侵入的原則,所以此時(shí)框架還需要通過代理工廠類ProxyFactory為服務(wù)接口生成代理類,并讓代理類去調(diào)用Invoker邏輯,避免了Dubbo框架代碼對(duì)業(yè)務(wù)代碼的侵入


          服務(wù)發(fā)現(xiàn)

          dubbo的服務(wù)發(fā)現(xiàn),就是通過從注冊(cè)中心訂閱服務(wù)提供者,并且組裝成URL,然后通過URL創(chuàng)建出invoker來實(shí)現(xiàn)的

          服務(wù)的引入和服務(wù)的暴露一樣,也是通過 spring 自定義標(biāo)簽機(jī)制解析生成對(duì)應(yīng)的 Bean,Provider Service 對(duì)應(yīng)解析的是 ServiceBean 而 Consumer Reference 對(duì)應(yīng)的是 ReferenceBean

          dubbo 的服務(wù)發(fā)現(xiàn),是通過從注冊(cè)中心訂閱服務(wù)提供者組裝成 URL,然后通過 URL 創(chuàng)建出 Invoker 來實(shí)現(xiàn)的。

          這里是入口,進(jìn)去看ReferenceBean


          createLazyProxy中我們會(huì)看到DubboReferenceLazyInitTargetSource這一目標(biāo)資源,點(diǎn)進(jìn)來new的地方,里面的protected的方法createObject調(diào)用了getCallProxy,而這個(gè)方法最終調(diào)用的是referenceConfig.get()


          點(diǎn)進(jìn)來,我們進(jìn)入的是ReferenceConfig類的方法,而非ReferenceBean的,這是因?yàn)镽eferenceConfig是作為ReferenceBean的內(nèi)部的屬性出現(xiàn)的


          Init()方法內(nèi)部主要就是通過Map設(shè)置各種參數(shù),我們看init其中的一個(gè)方法叫做createProxy,我們根據(jù)名字也可以知道大概意思就是創(chuàng)建代理對(duì)象,點(diǎn)進(jìn)去看看


          如果是走本地的話,那么直接構(gòu)建個(gè)本地協(xié)議的 URL 然后進(jìn)行服務(wù)的引入,即 refprotocol.refer,這個(gè)方法之后會(huì)做分析,本地的引入就不深入了,就是去之前服務(wù)暴露的 exporterMap 拿到服務(wù)
          如果不是本地,那肯定是遠(yuǎn)程了,接下來就是判斷是點(diǎn)對(duì)點(diǎn)直連 provider 還是通過注冊(cè)中心拿到 provider 信息再連接 provider 了,我們分析一下配置了 url 的情況,如果配置了 url 那么不是直連的地址,就是注冊(cè)中心的地址


          這其實(shí)就是整個(gè)流程了,簡(jiǎn)述一下就是先檢查配置,通過配置構(gòu)建一個(gè) map ,然后利用 map 來構(gòu)建 URL ,再通過 URL 上的協(xié)議利用自適應(yīng)擴(kuò)展機(jī)制調(diào)用對(duì)應(yīng)的 protocol.refer 得到相應(yīng)的 invoker 

          我給大家總結(jié)個(gè)流程圖,這樣大家看著更加清晰



          服務(wù)引用


          Dubbo 的服務(wù)引用,實(shí)際上是為引用的接口創(chuàng)建一個(gè) Proxy,這個(gè) Proxy 的功能就是去執(zhí)行 refprotocol.refer(interfaceClass, url) 創(chuàng)建出來的 Invoker。當(dāng)服務(wù)提供者有多個(gè)時(shí),就創(chuàng)建一個(gè) ClusterInvoker。

          Cluster 是一個(gè) SPI 擴(kuò)展點(diǎn),默認(rèn)使用com.alibaba.dubbo.rpc.cluster.support.FailoverCluster

          所以,Consumer 端服務(wù)調(diào)用的邏輯被封裝在 refprotocol.refer(interfaceClass, url) 創(chuàng)建出來的 Invoker 上


          主要就是獲取注冊(cè)中心實(shí)例,然后調(diào)用 doRefer 進(jìn)行真正的 refer。


          這里會(huì)向注冊(cè)中心注冊(cè)自身的信息,生成一個(gè)Invoker,底層生成用于遠(yuǎn)程調(diào)用的invoker,然后通過cluster包裝一下再得到ClusterInvoker,因此一個(gè)服務(wù)可能有多個(gè)提供者,然后最后注冊(cè)相應(yīng)的監(jiān)聽器

          拿到了Provider的信息之后就可以通過監(jiān)聽觸發(fā) Protocol# refer 了,具體調(diào)用哪個(gè) protocol 還是得看 URL的協(xié)議的,我們看下這個(gè)內(nèi)部DubboProtocol的refer


          而這個(gè)connect最終返回 HeaderExchangeClient里面封裝的是 NettyClient,然后最終得到的invoker就是對(duì)這個(gè)client的封裝,最終將返回一個(gè)Proxy的代理對(duì)象


          回顧


          其實(shí)整個(gè)流程看代碼啥的,一開始可能會(huì)遇到很多新名詞,但是細(xì)細(xì)一想其實(shí)不難,靜下心來好好分析,就都很簡(jiǎn)單了
          其實(shí)就是通過各種配置參數(shù)和協(xié)議組裝成相應(yīng)的URL,然后通過自動(dòng)適配去對(duì)相應(yīng)的實(shí)現(xiàn)類進(jìn)行相應(yīng)的服務(wù)的引入和后續(xù)的調(diào)用

          如果是寫死的地址就直接連接,是注冊(cè)中心就向注冊(cè)中心注冊(cè)信息,然后訂閱注冊(cè)中心的相關(guān)信息,得到服務(wù)提供者的IP端口號(hào)等信息,通過netty進(jìn)行連接,底層會(huì)通過directory和cluster進(jìn)行底層多個(gè)服務(wù)的屏蔽和負(fù)載均衡的處理,得到代理對(duì)象Invoker,再通過動(dòng)態(tài)代理封裝得到代理類,總之就是不侵入業(yè)務(wù)代碼,能用代理解決的就用代理

          不侵入代碼的最好辦法就是加代理,遇事不決加層代理

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

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


          好文章,我在看??

          瀏覽 103
          點(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>
                  欧美爆乳一区 | 国产夫妻自拍在线观看 | 无码成人精品久久影院三级 | 中文字幕人妻无码蜜桃 | 成人做爰黄 片免费观看 |