<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)、引用過程

          共 3320字,需瀏覽 7分鐘

           ·

          2021-09-06 14:44



          前言


          前面兩篇分別介紹了Dubbo的入門和Dubbo的服務(wù)暴露


          這篇我們要說的服務(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)的 BeanProvider 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)?/span>ReferenceConfig是作為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ì)通過directorycluster進(jìn)行底層多個(gè)服務(wù)的屏蔽和負(fù)載均衡的處理,得到代理對(duì)象Invoker,再通過動(dòng)態(tài)代理封裝得到代理類,總之就是不侵入業(yè)務(wù)代碼,能用代理解決的就用代理

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



          求贊

          好了,以上就是全部?jī)?nèi)容了,我是小魚仙,你們的學(xué)習(xí)成長(zhǎng)小伙伴         

                                                                    

          我希望有一天能夠靠寫字養(yǎng)活自己,現(xiàn)在還在磨練,這個(gè)時(shí)間可能會(huì)有很多年,感謝你們做我最初的讀者和傳播者。請(qǐng)大家相信,只要給我一份愛,我終究會(huì)還你們一頁(yè)情的。

          再次感謝大家能夠讀到這里,我后面會(huì)持續(xù)的更新技術(shù)文章以及一些記錄生活的靈魂文章,如果覺得不錯(cuò)的,覺得大魚同學(xué)有點(diǎn)東西的話,求點(diǎn)贊、關(guān)注、分享三連

          哦,對(duì)了!后續(xù)的更新文章我都會(huì)及時(shí)放到這里,歡迎大家點(diǎn)擊觀看,都是干貨文章啊,建議收藏,以后隨時(shí)翻閱查看

          https://github.com/DayuMM2021/Java

          瀏覽 42
          點(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>
                  99热| 在线观看黄色网页 | www.操操操 | 亚洲一级a人与一级A片 | 91人人摸 |