來源:blog.csdn.net/cold___play/article/details/108032204
Nacos架構

- Provider APP:服務提供者
- Consumer APP:服務消費者
- Name Server:通過VIP(Virtual IP)或DNS的方式實作Nacos高可用集群的服務路由
- Nacos Server:Nacos服務提供者,里面包含的Open API是功能訪問入口,Conig Service、Naming Service 是Nacos提供的配置服務、命名服務模塊,Consitency Protocol是一致性協議,用來實作Nacos集群節點的資料同步,這里使用的是Raft演算法(Etcd、Redis哨兵選舉)
- Nacos Console:控制臺
注冊中心的原理
- 服務實體在啟動時注冊到服務注冊表,并在關閉時注銷
- 服務消費者查詢服務注冊表,獲得可用實體
- 服務注冊中心需要呼叫服務實體的健康檢查API來驗證它是否能夠處理請求

SpringCloud完成注冊的時機
在Spring-Cloud-Common包中有一個類org.springframework.cloud. client.serviceregistry .ServiceRegistry ,它是Spring Cloud提供的服務注冊的標準,集成到Spring Cloud中實作服務注冊的組件,都會實作該介面,

該介面有一個實作類是NacoServiceRegistry,
SpringCloud集成Nacos的實作程序:
在spring-clou-commons包的META-INF/spring.factories中包含自動裝配的配置資訊如下:

其中AutoServiceRegistrationAutoConfiguration就是服務注冊相關的配置類:

在AutoServiceRegistrationAutoConfiguration配置類中,可以看到注入了一個AutoServiceRegistration實體,該類的關系圖如下所示,

可以看出, AbstractAutoServiceRegistration抽象類實作了該介面,并且最重要的是NacosAutoServiceRegistration繼承了AbstractAutoServiceRegistration,
看到EventListener我們就應該知道,Nacos是通過Spring的事件機制繼承到SpringCloud中去的,
AbstractAutoServiceRegistration實作了onApplicationEvent抽象方法,并且監聽WebServerInitializedEvent事件(當Webserver初始化完成之后) , 呼叫this.bind ( event )方法,

最侄訓呼叫NacosServiceREgistry.register()方法進行服務注冊,


NacosServiceRegistry的實作
在NacosServiceRegistry.registry方法中,呼叫了Nacos Client SDK中的namingService.registerInstance完成服務的注冊,

跟蹤NacosNamingService的registerInstance()方法:

- 通過
beatReactor.addBeatInfo()創建心跳資訊實作健康檢測, Nacos Server必須要確保注冊的服務實體是健康的,而心跳檢測就是服務健康檢測的手段, serverProxy.registerService()實作服務注冊
心跳機制:

從上述代碼看,所謂心跳機制就是客戶端通過schedule定時向服務端發送一個資料包 ,然后啟動-個執行緒不斷檢測服務端的回應,如果在設定時間內沒有收到服務端的回應,則認為服務器出現了故障,Nacos服務端會根據客戶端的心跳包不斷更新服務的狀態,
注冊原理:
Nacos提供了SDK和Open API兩種形式來實作服務注冊,
Open API:

SDK:

這兩種形式本質都一樣,底層都是基于HTTP協議完成請求的,所以注冊服務就是發送一個HTTP請求:

對于nacos服務端,對外提供的服務介面請求地址為nacos/v1/ns/instance,實作代碼咋nacos-naming模塊下的InstanceController類中:

- 從請求引數匯總獲得serviceName(服務名)和namespaceId(命名空間Id)
- 呼叫registerInstance注冊實體

- 創建一個控服務(在Nacos控制臺“服務串列”中展示的服務資訊),實際上是初始化一個serviceMap,它是一個ConcurrentHashMap集合
- getService,從serviceMap中根據namespaceId和serviceName得到一個服務物件
- 呼叫addInstance添加服務實體


- 根據namespaceId、serviceName從快取中獲取Service實體
- 如果Service實體為空,則創建并保存到快取中

- 通過
putService()方法將服務快取到記憶體 service.init()建立心跳機制consistencyService.listen實作資料一致性監聽
service.init ( )方法的如下圖所示,它主要通過定時任務不斷檢測當前服務下所有實體最后發送心跳包的時間,如果超時,則設定healthy為false表示服務不健康,并且發送服務變更事件,
在這里請大家思考一一個問題,服務實體的最后心跳包更新時間是誰來觸發的?實際上前面有講到, Nacos客戶端注冊服務的同時也建立了心跳機制,

putService方法,它的功能是將Service保存到serviceMap中:

繼續呼叫addInstance方法把當前注冊的服務實體保存到Service中:

總結:
-
Nacos客戶端通過Open API的形式發送服務注冊請求
-
Nacos服務端收到請求后,做以下三件事:
-
- 構建一個Service物件保存到ConcurrentHashMap集合中
- 使用定時任務對當前服務下的所有實體建立心跳檢測機制
- 基于資料一致性協議服務資料進行同步
服務提供者地址查詢
Open API:

SDK:

InstanceController中的list方法:

- 決議請求引數
- 通過doSrvIPXT回傳服務串列資料


- 根據namespaceId、serviceName獲得Service實體
- 從Service實體中基于srvIPs得到所有服務提供者實體
- 遍歷組裝JSON字串并回傳
Nacos服務地址動態感知原理
可以通過subscribe方法來實作監聽,其中serviceName表示服務名、EventListener表示監聽到的事件:

具體呼叫方式如下:

或者呼叫selectInstance方法,如果將subscribe屬性設定為true,會自動注冊監聽:


Nacos客戶端中有一個HostReactor類,它的功能是實作服務的動態更新,基本原理是:
- 客戶端發起時間訂閱后,在HostReactor中有一個UpdateTask執行緒,每10s發送一次Pull請求,獲得服務端最新的地址串列
- 對于服務端,它和服務提供者的實體之間維持了心跳檢測,一旦服務提供者出現例外,則會發送一個Push訊息給Nacos客戶端,也就是服務端消費者
- 服務消費者收到請求之后,使用HostReactor中提供的processServiceJSON決議訊息,并更新本地服務地址串列
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/446982.html
標籤:Java
