新聞中心
簡介
首先我們?cè)诳碞acos源碼之前,要先想想為什么我們要讀源碼?是為了裝杯?還是為了在心儀的女神面前給她娓娓道來展示自己的代碼功底?當(dāng)然不全是!

這都不是我們讀源碼的最終目的。作為一名技術(shù)人,上面的都是浮云,真正激勵(lì)我們的應(yīng)該是能夠提升我們技術(shù)功底和整體技術(shù)大局觀。此乃大道也!閑言少敘,接下來我們就來看一看,看源碼究竟有什么好處。
- 提升技術(shù)功底: 當(dāng)我們?nèi)タ丛创a的時(shí)候,能夠?qū)W習(xí)源碼里面優(yōu)秀的設(shè)計(jì)思想,還含有設(shè)計(jì)模式和并發(fā)編程技術(shù),解決問題的思路,能夠知其所以然。
- 新技術(shù)學(xué)習(xí)能力: 當(dāng)我們看多了源碼,對(duì)于一個(gè)新技術(shù)或者框架的掌握速度會(huì)有大幅度提升,能根據(jù)經(jīng)驗(yàn)或官網(wǎng)資料快速掌握底層的實(shí)現(xiàn),技術(shù)更新迭代也可以更快的入手。
- 快速解決問題能力: 遇到問題,尤其是框架源碼的問題,能夠更快速定位。
- 面試獲取更高成功率: 現(xiàn)在出去面試,一般中高級(jí)一點(diǎn)的,都會(huì)問到框架源碼級(jí)別的實(shí)現(xiàn),如果能夠說出來,可以提升面試的成功率和薪資待遇,源碼面試是區(qū)別程序員水平另一面鏡子。
- 認(rèn)識(shí)更多圈子: 多活躍開源社區(qū),熟讀源碼后多思考,發(fā)現(xiàn)問題或需求主動(dòng)參與開源技術(shù)研發(fā),與圈內(nèi)大牛成為朋友。
閱讀源碼的方法
- 搭建入門demo: 我們可以先看一下官網(wǎng)提供的文檔,搭建Demo,快速掌握框架的基本使用。
- 看核心代碼: 對(duì)于初次看源碼的同學(xué),不要太過于關(guān)注源碼的細(xì)枝末節(jié),先把主要核心流程梳理出來,找到其入口,分析靜態(tài)代碼,如果遇到問題,可以進(jìn)行斷點(diǎn)調(diào)試。
- 繪圖和筆記: 梳理好核心功能后,可以用流程圖記錄下來,好記性不如爛筆頭,同時(shí)對(duì)關(guān)鍵的源碼部分可以進(jìn)行備注,分析參數(shù)的變化。同時(shí)要善于用Debug,來觀看源碼的執(zhí)行過程。
- 復(fù)習(xí)總結(jié): 當(dāng)我們把框架的所有功能點(diǎn)的源碼都分析完成后,回到主流程在梳理一遍,最后在自己腦袋中形成一個(gè)閉環(huán),這樣源碼的核心內(nèi)容和主流程就基本上理解了。
Nacos核心功能點(diǎn)
- 服務(wù)注冊(cè): Nacos Client會(huì)通過發(fā)送REST請(qǐng)求的方式向Nacos Server注冊(cè)自己的服務(wù),提供自身的元數(shù)據(jù),比如IP地址,端口等信息。Nacos Server接收到注冊(cè)請(qǐng)求后,就會(huì)把這些元數(shù)據(jù)信息存儲(chǔ)在一個(gè)雙層的內(nèi)存Map中。
- 服務(wù)心跳: 在服務(wù)注冊(cè)后,Nacos Client會(huì)維護(hù)一個(gè)定時(shí)心跳來支持通知Nacos Server,說明服務(wù)一直處于可用狀態(tài),防止被剔除。默認(rèn)5s發(fā)送一次心跳。
- 服務(wù)健康檢查: Nacos Server會(huì)開啟一個(gè)定時(shí)任務(wù)用來檢查注冊(cè)服務(wù)實(shí)例的健康狀況,對(duì)于超過15s沒有收到客戶端心跳的實(shí)例會(huì)將它的healthy屬性設(shè)置為false(客戶端服務(wù)發(fā)現(xiàn)時(shí)不會(huì)發(fā)現(xiàn))。如果某個(gè)實(shí)例超過30秒沒有收到心跳,直接剔除該實(shí)例(被剔除的實(shí)例如果恢復(fù)發(fā)送心跳則會(huì)重新注冊(cè))
- 服務(wù)發(fā)現(xiàn): 服務(wù)消費(fèi)者(Nacos Client)在調(diào)用服務(wù)提供者的服務(wù)時(shí),會(huì)發(fā)送一個(gè)REST請(qǐng)求給Nacos Server,獲取上面注冊(cè)的服務(wù)清單,并且緩存在Nacos Client本地,同時(shí)在Nacos Client本地開啟一個(gè)定時(shí)任務(wù)定時(shí)拉取服務(wù)端最新的注冊(cè)表信息更新到本地緩存。
- 服務(wù)同步: Nacos Server集群之間會(huì)互相同步服務(wù)實(shí)例,用來保證服務(wù)信息的一致性。
Nacos源碼下載
首先我們需要將Nacos的源碼下載下來,下載地址:https://github.com/alibaba/nacos。
我們將源碼下下來以后,導(dǎo)入到idea中。
proto編譯
當(dāng)我們導(dǎo)入成功以后,會(huì)出現(xiàn)程序包c(diǎn)om.alibaba.nacos.consistency.entity不存在的錯(cuò)誤提示,這是因?yàn)镹acos底層的數(shù)據(jù)通信會(huì)基于protobuf對(duì)數(shù)據(jù)做序列化和反序列化,需要先將proto文件編譯為對(duì)應(yīng)的Java代碼。
最簡單的 不安裝任何的東西 idea2021.2已經(jīng)捆綁安裝了這個(gè)。
可以通過mvn copmpile來在target自動(dòng)生成他們。
Nacos缺少Istio依賴問題解決
我們只需要在文件根目錄下執(zhí)行以下命令即可:
mvn clean package -Dmaven.test.skip=true -Dcheckstyle.skip=true
做完以上兩步,我們就可以啟動(dòng)Nacos的了。
啟動(dòng)Nacos
首先我們找到 nacos-console 這個(gè)模塊,這個(gè)就是我們的管理后臺(tái),找到它的啟動(dòng)類,因?yàn)镹acos默認(rèn)為集群啟動(dòng),所以我們要設(shè)置它為單機(jī)啟動(dòng),方便演示。
設(shè)置命令:
-Dnacos.standalone=true -Dnacos.home=E:\test\nacos。
啟動(dòng)成功后,賬號(hào)密碼:nacos/nacos。
到這里我們Nacos的源碼啟動(dòng)就完成了。
開啟源碼
我們先從客戶端服務(wù)的注冊(cè)開始說起,我們可以先想一想如果Nacos客戶端要注冊(cè),會(huì)把什么信息傳遞給服務(wù)器?這里我們可以看到在 nacos-client下的NamingTest有這么一些信息。
@Ignore
public class NamingTest {
@Test
public void testServiceList() throws Exception {
//Nacos Server連接信息
Properties properties = new Properties();
//Nacos服務(wù)器地址
properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
//連接Nacos服務(wù)的用戶名
properties.put(PropertyKeyConst.USERNAME, "nacos");
//連接Nacos服務(wù)的密碼
properties.put(PropertyKeyConst.PASSWORD, "nacos");
//實(shí)例信息
Instance instance = new Instance();
//實(shí)例IP,提供給消費(fèi)者進(jìn)行通信的地址
instance.setIp("1.1.1.1");
//端口,提供給消費(fèi)者訪問的端口
instance.setPort(800);
//權(quán)重,當(dāng)前實(shí)例的權(quán)限,浮點(diǎn)類型(默認(rèn)1.0D)
instance.setWeight(2);
Mapmap = new HashMap ();
map.put("netType", "external");
map.put("version", "2.0");
instance.setMetadata(map);
//關(guān)鍵代碼 創(chuàng)建自己的實(shí)例
NamingService namingService = NacosFactory.createNamingService(properties);
namingService.registerInstance("nacos.test.1", instance);
ThreadUtils.sleep(5000L);
Listlist = namingService.getAllInstances("nacos.test.1");
System.out.println(list);
ThreadUtils.sleep(30000L);
// ExpressionSelector expressionSelector = new ExpressionSelector();
// expressionSelector.setExpression("INSTANCE.metadata.registerSource = 'dubbo'");
// ListViewserviceList = namingService.getServicesOfServer(1, 10, expressionSelector);
}
}
上面就是客戶端注冊(cè)的一個(gè)測(cè)試類,模仿了真實(shí)的服務(wù)注冊(cè)到Nacos的過程,包括NacosServer連接、實(shí)例的創(chuàng)建、實(shí)例屬性的賦值、注冊(cè)實(shí)例,所以在這個(gè)其中包含了服務(wù)注冊(cè)的核心代碼,從這里我們可以大致看出,它包含了兩個(gè)類的信息:Nacos Server連接信息和實(shí)例信息。
Nacos Server連接信息:
從上述中我們可以看到有關(guān)于Nacos Server連接信息是存儲(chǔ)在Properties中。
- Server地址:Nacos服務(wù)器地址,屬性的key為serverAddr。
- 用戶名:連接Nacos服務(wù)的用戶名,屬性key為username,默認(rèn)值為nacos。
- 密碼:連接Nacos服務(wù)的密碼,屬性key為password,默認(rèn)值為nacos。
實(shí)例信息:
從上述測(cè)試中我們可以看到注冊(cè)實(shí)例信息用instance進(jìn)行承載,而實(shí)例信息又分為兩部分,一個(gè)是基礎(chǔ)實(shí)例信息,一個(gè)是元數(shù)據(jù)信息。
實(shí)例基礎(chǔ)信息:
- instanceId:實(shí)例的唯一ID。
- ip:實(shí)例IP,提供給消費(fèi)者進(jìn)行通信的地址。
- port:端口,提供給消費(fèi)者訪問的端口。
- weight:權(quán)重,當(dāng)前實(shí)例的權(quán)限,浮點(diǎn)類型(默認(rèn)1.0D)。
- healthy:健康狀況,默認(rèn)true。
- enabled:實(shí)例是否準(zhǔn)備好接收請(qǐng)求,默認(rèn)true。
- ephemeral:實(shí)例是否為瞬時(shí)的,默認(rèn)為true。
- clusterName:實(shí)例所屬的集群名稱。
- serviceName:實(shí)例的服務(wù)信息。
元數(shù)據(jù):
元數(shù)據(jù)類型為HashMap,從當(dāng)前Demo我們能夠看到的數(shù)據(jù)只有兩個(gè)。
- netType:網(wǎng)絡(luò)類型,這里設(shè)置的值為external(外網(wǎng))。
- version Nacos版本,這里為2.0。
除此之外,我們?cè)贗nstance類中還可以看到一些默認(rèn)信息,這些方法都是通過get方法進(jìn)行提供的。
//心跳間隙的key,默認(rèn)為5s,也就是默認(rèn)5秒進(jìn)行一次心跳
public long getInstanceHeartBeatInterval() {
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL,
Constants.DEFAULT_HEART_BEAT_INTERVAL);
}
//心跳超時(shí)的key,默認(rèn)為15s,也就是默認(rèn)15秒收不到心跳,實(shí)例將會(huì)標(biāo)記為不健康;
public long getInstanceHeartBeatTimeOut() {
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,
Constants.DEFAULT_HEART_BEAT_TIMEOUT);
}
//實(shí)例IP被刪除的key,默認(rèn)為30s,也就是30秒收不到心跳,實(shí)例將會(huì)被移除;
public long getIpDeleteTimeout() {
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT,
Constants.DEFAULT_IP_DELETE_TIMEOUT);
}
//實(shí)例ID生成器key,默認(rèn)為simple;
public String getInstanceIdGenerator() {
return getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR,
Constants.DEFAULT_INSTANCE_ID_GENERATOR);
}
為什么要說這個(gè)呢?從這些參數(shù)中我們就可以了解到,我們服務(wù)的心跳間隙是多少以及超時(shí)時(shí)間,傳遞什么參數(shù)配置什么參數(shù),以此來了解我們的實(shí)例是否健康。同時(shí)我們也可以看到一個(gè)比較關(guān)鍵且核心的類,是真正創(chuàng)建實(shí)例的類 ——NamingService。
NamingService
NamingService是Nacos對(duì)外提供的一個(gè)統(tǒng)一的接口,當(dāng)我們點(diǎn)進(jìn)去查看,可以看到大概以下幾個(gè)方法,這些方法提供了不同的重載方法,方便我們用于不同的場(chǎng)景。
//服務(wù)實(shí)例注冊(cè)
void registerInstance(...) throws NacosException;
//服務(wù)實(shí)例注銷
void deregisterInstance(...) throws NacosException;
//獲取服務(wù)實(shí)例列表
ListgetAllInstances(...) throws NacosException;
//查詢健康服務(wù)實(shí)例
ListselectInstances(...) throws NacosException;
//查詢集群中健康的服務(wù)實(shí)例
ListselectInstances(....List clusters....)throws NacosException;
//使用負(fù)載均衡策略選擇一個(gè)健康的服務(wù)實(shí)例
Instance selectOneHealthyInstance(...) throws NacosException;
//訂閱服務(wù)事件
void subscribe(...) throws NacosException;
//取消訂閱服務(wù)事件
void unsubscribe(...) throws NacosException;
//獲取所有(或指定)服務(wù)名稱
ListViewgetServicesOfServer(...) throws NacosException;
//獲取所有訂閱的服務(wù)
ListgetSubscribeServices() throws NacosException;
//獲取Nacos服務(wù)的狀態(tài)
String getServerStatus();
//主動(dòng)關(guān)閉服務(wù)
void shutDown() throws NacosException;
NamingService的實(shí)例化是通過NacosFactory.createNamingService(properties);實(shí)現(xiàn)的,內(nèi)部源碼是通過反射來實(shí)現(xiàn)實(shí)例化過程。
NamingService namingService = NacosFactory.createNamingService(properties);
public static NamingService createNamingService(Properties properties) throws NacosException {
try {
Class> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
return (NamingService) constructor.newInstance(properties);
} catch (Throwable e) {
throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
}
}
接下來我們就來看一看NamingService的具體實(shí)現(xiàn)。
//調(diào)用registerInstance方法
namingService.registerInstance("nacos.test.1", instance);
@Override
public void registerInstance(String serviceName, Instance instance) throws NacosException {
//默認(rèn)的分組為“DEFAULT_GROUP”
registerInstance(serviceName, Constants.DEFAULT_GROUP, instance);
}
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
//檢查心跳時(shí)間是否正常
NamingUtils.checkInstanceIsLegal(instance);
//通過代理注冊(cè)服務(wù)
clientProxy.registerService(serviceName, groupName, instance);
}
心跳檢測(cè)代碼
//心跳間隙超過限制 返回錯(cuò)誤
if (instance.getInstanceHeartBeatTimeOut() < instance.getInstanceHeartBeatInterval()
|| instance.getIpDeleteTimeout() < instance.getInstanceHeartBeatInterval()) {
throw new NacosException(NacosException.INVALID_PARAM,
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.");
}
通過代理注冊(cè)服務(wù),我們了解到clientProxy代理接口是通過NamingClientProxyDelegate來完成,我們可以在init構(gòu)造方法中得出,具體的實(shí)例對(duì)象。
private void init(Properties properties) throws NacosException {
//使用NamingClientProxyDelegate來完成
this.clientProxy = new NamingClientProxyDelegate(this.namespace, serviceInfoHolder, properties, changeNotifier);
}
NamingClientProxyDelegate實(shí)現(xiàn)在NamingClientProxyDelegate中,真正調(diào)用注冊(cè)服務(wù)的并不是代理實(shí)現(xiàn)類,而且先判斷當(dāng)前實(shí)例是否為瞬時(shí)對(duì)象后,來選擇對(duì)應(yīng)的客戶端代理來進(jìn)行請(qǐng)求。
@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
getExecuteClientProxy(instance).registerService(serviceName, groupName, instance);
}
如果當(dāng)前實(shí)例是瞬時(shí)對(duì)象,則采用gRPC協(xié)議(NamingGrpcClientProxy)進(jìn)行請(qǐng)求,否則采用Http協(xié)議(NamingHttpClientProxy),默認(rèn)為瞬時(shí)對(duì)象,在2.0版本中默認(rèn)采用gRPC協(xié)議進(jìn)行與Nacos服務(wù)進(jìn)行交互。
//判斷當(dāng)前實(shí)例是否為瞬時(shí)對(duì)象
private NamingClientProxy getExecuteClientProxy(Instance instance) {
return instance.isEphemeral() ? grpcClientProxy : httpClientProxy;
}
NamingGrpcClientProxy中的實(shí)現(xiàn)
@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
instance);
//數(shù)據(jù)的緩存
redoService.cacheInstanceForRedo(serviceName, groupName, instance);
//gRPC進(jìn)行服務(wù)調(diào)用
doRegisterService(serviceName, groupName, instance);
}
大體關(guān)系圖如下所示:
Nacos客戶端在項(xiàng)目的應(yīng)用
我們想要讓某一個(gè)服務(wù)注冊(cè)到Nacos中,首先要引入一個(gè)依賴:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
在依賴中,去查看SpringBoot自動(dòng)裝配文件自動(dòng)裝配文件META-INF/spring.factories。
通過SpringBoot的自動(dòng)裝配來加載EnableAutoConfiguration對(duì)應(yīng)的類,這里我們可以看到很多有關(guān)于Nacos相關(guān)的類,怎么知道哪個(gè)是我們真正需要關(guān)心的類,服務(wù)在注冊(cè)的時(shí)候走的是哪個(gè),一般自動(dòng)裝配,我們都會(huì)找到帶有“Auto”關(guān)鍵字的文件進(jìn)行查看,然后再結(jié)合我們需要找的,我們是客戶端注冊(cè)服務(wù),所以我們大體可以定位到NacosServiceRegistryAutoConfiguration這個(gè)文件。
查看NacosServiceRegistryAutoConfiguration源碼,在這里我們只需要關(guān)注最核心的nacosAutoServiceRegistration方法
而我們真正關(guān)心的只有三個(gè)類NacosAutoServiceRegistration類是注冊(cè)的核心,我們來看一下它的繼承關(guān)系。
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
public NacosAutoServiceRegistration nacosAutoServiceRegistration(
NacosServiceRegistry registry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry,
autoServiceRegistrationProperties, registration);
}
從上述內(nèi)容中我們可以知道,Nacos服務(wù)自動(dòng)注冊(cè)是從NacosServiceRegistryAutoConfiguration類開始的,并自動(dòng)注冊(cè)到NacosAutoServiceRegistration類中。
在下圖中我們可以看到,主要是調(diào)用了super 方法,所以我們繼續(xù)查看該類的構(gòu)造方法:AbstractAutoServiceRegistration。
public class NacosAutoServiceRegistration
extends AbstractAutoServiceRegistration{
public NacosAutoServiceRegistration(ServiceRegistryserviceRegistry,
AutoServiceRegistrationProperties autoServiceRegistrationProperties,
NacosRegistration registration) {
super(serviceRegistry, autoServiceRegistrationProperties);
this.registration = registration;
}
}
AbstractAutoServiceRegistration 實(shí)現(xiàn)了ApplicationListener接口,用來監(jiān)聽Spring容器啟動(dòng)過程中WebServerInitializedEvent事件,一般如果我們實(shí)現(xiàn)這個(gè)類的時(shí)候,會(huì)實(shí)現(xiàn)一個(gè)方法onApplicationEvent(),這個(gè)方法會(huì)在我們項(xiàng)目啟動(dòng)的時(shí)候觸發(fā)。
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
由此我們可以看到bind里面的這個(gè)方法。
@Deprecated
public void bind(WebServerInitializedEvent event) {
//獲取 ApplicationContext對(duì)象
ApplicationContext context = event.getApplicationContext();
//判斷服務(wù)的 Namespace
if (context instanceof ConfigurableWebServerApplicationContext) {
if ("management".equals(((ConfigurableWebServerApplicationContext) context).getServerNamespace())) {
return;
}
}
//記錄當(dāng)前服務(wù)的端口
this.port.compareAndSet(0, event.getWebServer().getPort());
//【核心】啟動(dòng)注冊(cè)流程
this.start();
}
start()方法調(diào)用register();方法來注冊(cè)服務(wù)。
public void start() {
if (!isEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Discovery Lifecycle disabled. Not starting");
}
return;
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
//如果服務(wù)是沒有運(yùn)行狀態(tài)時(shí),進(jìn)行初始化
if (!this.running.get()) {
//發(fā)布服務(wù)開始注冊(cè)事件
this.context.publishEvent(new InstancePreRegisteredEvent(this, getRegistration()));
//【核心】注冊(cè)服務(wù)
register();
if (shouldRegisterManagement()) {
registerManagement();
}
//發(fā)布注冊(cè)完成事件
this.context.publishEvent(new InstanceRegisteredEvent<>(this, getConfiguration()));
//服務(wù)狀態(tài)設(shè)置為運(yùn)行狀態(tài)
this.running.compareAndSet(false, true);
}
}
NacosServiceRegistry.register()方法,如下所示:
@Override
public void register(Registration registration) {
//判斷ServiceId是否為空
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
//獲取Nacos的服務(wù)信息
NamingService namingService = namingService();
//獲取服務(wù)ID和分組
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
//構(gòu)建instance實(shí)例(IP/Port/Weight/clusterName.....)
Instance instance = getNacosInstanceFromRegistration(registration);
try {
//向服務(wù)端注冊(cè)此服務(wù)
namingService.registerInstance(serviceId, group, instance);
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
instance.getIp(), instance.getPort());
}
catch (Exception e) {
if (nacosDiscoveryProperties.isFailFast()) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
rethrowRuntimeException(e);
}
else {
log.warn("Failfast is false. {} register failed...{},", serviceId,
registration.toString(), e);
}
}
}
NacosNamingService.registerInstance()方法,如下:
@Override
public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
//檢查超時(shí)參數(shù)是否異常,心跳超時(shí)時(shí)間(15s)必須大于心跳間隙(5s)
NamingUtils.checkInstanceIsLegal(instance);
//拼接服務(wù)名,格式:groupName@@serviceName
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
//判斷是否為臨時(shí)實(shí)例,默認(rèn)為true
if (instance.isEphemeral()) {
//臨時(shí)實(shí)例,定時(shí)向Nacos服務(wù)發(fā)送心跳
BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
beatReactor.addBeatInfo(groupedServiceName, beatInfo);
}
//【核心】發(fā)送注冊(cè)服務(wù)實(shí)例請(qǐng)求
serverProxy.registerService(groupedServiceName, groupName, instance);
}
在registerService中我們可以看到Nacos服務(wù)注冊(cè)接口需要的完整參數(shù)。
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName,
instance);
final Map params = new HashMap(16);
//環(huán)境
params.put(CommonParams.NAMESPACE_ID, namespaceId);
//服務(wù)名稱
params.put(CommonParams.SERVICE_NAME, serviceName);
//分組名稱
params.put(CommonParams.GROUP_NAME, groupName);
//集群名稱
params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
//當(dāng)前實(shí)例IP
params.put("ip", instance.getIp());
//當(dāng)前實(shí)例端口
params.put("port", String.valueOf(instance.getPort()));
//權(quán)重
params.put("weight", String.valueOf(instance.getWeight()));
params.put("enable", String.valueOf(instance.isEnabled()));
params.put("healthy", String.valueOf(instance.isHealthy()));
params.put("ephemeral", String.valueOf(instance.isEphemeral()));
params.put("metadata", JacksonUtils.toJson(instance.getMetadata()));
reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
}
補(bǔ)充在這里我們會(huì)發(fā)現(xiàn)我們請(qǐng)求實(shí)例接口的地址為/nacos/v1/ns/instance,其實(shí)這個(gè)在官網(wǎng)中也有提供對(duì)應(yīng)的地址給我們,并且是對(duì)應(yīng)的。
客戶端注冊(cè)流程圖
總結(jié)
以上就是Nacos的客戶端注冊(cè)流程,閱讀源碼并沒有我們想象中的那么難,道阻且長,行之將至,當(dāng)你開始行動(dòng)的時(shí)候,你就已經(jīng)開始進(jìn)步了,別管學(xué)多少。
網(wǎng)站標(biāo)題:Nacos源碼系列—關(guān)于服務(wù)注冊(cè)的那些事
文章URL:http://fisionsoft.com.cn/article/cdcpojd.html


咨詢
建站咨詢
