涉及輕微的原始碼展示,可放心參考;
服務註冊發現是微服務架構中最基礎的能力,下面將從原始碼層面分析實現邏輯和原理,在這之前要先來看下依賴工程的基礎結構,涉及如下幾個核心元件:
在熟悉工程依賴之間的結構時,還要明白服務間互動的流程和原理,這樣在分析原始碼設計時,有一個清晰的思路與輪廓;如何實現下面的服務互動模式,在閱讀原始碼工程時,圍繞如下兩個核心邏輯:
在這裡先簡單的聊一下個人在閱讀原始碼工程時的基本思路,比如微服務元件:通常從設定引數作為切入口,觀察基於引數構建的核心物件,再重點分析物件的管理模式,以及適配的擴充套件能力,最後結合專案的應用場景即可:
閱讀原始碼最重要的是耐著心情慢慢看,並隨手畫下核心流程,實際上如果有一定的程式設計經驗,不管是閱讀什麼工程的原始碼,只要用心去分析單點的實現原理,都算不上過度複雜,但是元件通常為了複用能力,會去適配多種複雜的場景,這樣勢必要採用抽象的封裝和設計模式,原始碼工程的複雜度自然就會相應提高,這個話題後續會細聊。
首先從Nacos設定引數開始,這裡只設定服務發現的兩個引數:1Nacos註冊中心的伺服器端地址,2在服務的後設資料中載入分支號;然後來具體的看原始碼流程:
在設定引數載入的過程中,有很多預設的預設值,所以需要關注最終會提供的引數資訊,來判斷是否需要自定義設定,另外AutoConfig
設定要重點看範例化的物件;斷點的流程可以按照如下的方式做設定,這裡陳列的是在設定載入階段的幾個核心節點:
NamingService是Nacos服務管理介面,涉及註冊、查詢、復原、檢查等多個方法,即對應的是Nacos伺服器端的相應API請求,在註冊執行的階段會細說用法。
看完服務設定之後再看註冊設定,對於設定中複雜的設計,需要重點關注兩個資訊:ConditionalOn和matchIfMissing,這樣很容易發現預設載入:
在構建服務註冊的核心類NacosServiceRegistry時,通過服務的登記資訊轉換為註冊的範例化物件,然後通過NamingService介面方法,上報範例化物件;需要注意的是,雖然這裡只看了Nacos中的相關API,但實際上API實現了諸多spring-cloud-commons包中宣告的介面,比如Registration、ServiceInstance等。
通常微服務的註冊中心元件,都是基於server-client
架構和部署方式,使用者端需要根據自身啟動狀態去上報或者復原註冊,伺服器端負責統一維護註冊資料:
在最終執行服務註冊時,其動作本質就是請求Nacos伺服器端的一個Post方法,並將設定資料上報,例如:IP地址、埠、後設資料、權重等;這樣使用者端註冊邏輯執行完成,然後再看伺服器端資料視覺化介面,就可以看到註冊的使用者端服務。
至於Nacos伺服器端是如何管理這些註冊資料的,參考部署版本的nacos-naming
模組原始碼,閱讀上報介面和頁面中的列表載入的實現即可;注意在初始的組態檔中,加入的branch分支引數也在後設資料結構中。
在NamingService介面中,涉及多個服務管理的方法,在執行原理上基本相同就不在贅述,這樣註冊中心的Client端和Server端就形成了通訊機制,接下來再看Client端之間的通訊。
Feign在設定方面比較複雜,提供了多個場景下的適配能力,這裡只以兩個常見的引數作為切入點:1通訊超時時間,2Http選型(採用預設值);
這裡要重點關注的是註解的掃描和註冊以及容器管理,要理解Feign的上下文環境需要明白上文中描述的服務間互動原理,然後參考FeignClientFactoryBean工廠類中構建邏輯。
雖然Feign註解的方式可以簡化開發,但是在具體執行的時候還是Http的請求響應模式,這裡可以參考LoadBalancerFeignClient類中的execute方法:
不管是Feign元件還是Spring框架,預設的負載均衡策略都是採用Ribbon的實現方式,在上述流程中設定和負載均衡命令都依賴Ribbon元件,接下來看服務選擇策略。
這裡構建了呼叫負載均衡介面的命令,ILoadBalancer介面中提供服務管理的相關方法,其中最核心的就是chooseServer方法,然後結合具體的策略規則實現服務的選擇的功能:
Ribbon元件中負載均衡的策略有好幾種規則,比如隨機選擇、Key匹配、權重傾斜等;在工作中常用的就是預設規則即RoundRobinRule,以及基於Key設計的灰度模式,簡單做法就是服務啟動時在後設資料中新增的分支號作為匹配的標識;
現在回到流程的開始看,通過Nacos元件進行服務註冊和管理,通過Feign元件基於Ribbon負載均衡策略做服務通訊,如果單看各節點元件的邏輯還比較容易理解,但是通過Spring框架做元件之間的共同作業排程時,複雜程度明顯提高;
如果是剛開始閱讀原始碼的階段,可以只關注相應流程的核心邏輯,選擇性忽略細節的實現原理,當然重點還是要多讀讀Spring的設計,這樣時間久了自然會有很多收穫。
程式設計檔案:
https://gitee.com/cicadasmile/butte-java-note
應用倉庫:
https://gitee.com/cicadasmile/butte-flyer-parent