1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        《跟二師兄學(xué)Nacos吧》第1篇 Nacos客戶端服務(wù)注冊(cè)源碼分析

        共 6553字,需瀏覽 14分鐘

         ·

        2021-07-18 18:46

        開篇構(gòu)想

        在此之前,已經(jīng)寫了十多篇Nacos的文章,感覺Nacos還值得更深入的學(xué)習(xí)一下。于是萌生了寫一個(gè)Nacos源碼系列專欄的文章。

        寫作的目標(biāo)呢,有兩個(gè):第一,能夠系統(tǒng)的學(xué)習(xí)Nacos知識(shí);第二,能夠基于Nacos學(xué)到涉及到的知識(shí)點(diǎn)或面;

        展現(xiàn)形式呢,也有兩個(gè):第一,單篇足夠簡(jiǎn)單且又有價(jià)值;第二,發(fā)現(xiàn)代碼中的新穎之處;

        源碼版本信息

        目前在生產(chǎn)實(shí)踐中建議大家采用1.4.2版本,但作為技術(shù)研究,本系列文章會(huì)基于2.0.2版本來(lái)僅僅講解。這是兩個(gè)跨度比較大的版本,建議大家配合源碼進(jìn)行學(xué)習(xí)。

        關(guān)于源碼拉取,環(huán)境搭建部分就不再贅述。下面就開始本篇文章,講解Nacos服務(wù)注冊(cè)的客戶端部分。

        服務(wù)注冊(cè)信息

        講到服務(wù)注冊(cè),我們先要了解一下Nacos都會(huì)將什么信息傳遞給服務(wù)器。直接從Nacos Client項(xiàng)目的NamingTest看起:

        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, "127.0.0.1:8848");
        properties.put(PropertyKeyConst.USERNAME, "nacos");
        properties.put(PropertyKeyConst.PASSWORD, "nacos");

        Instance instance = new Instance();
        instance.setIp("1.1.1.1");
        instance.setPort(800);
        instance.setWeight(2);
        Map<String, String> map = new HashMap<String, String>();
        map.put("netType", "external");
        map.put("version", "2.0");
        instance.setMetadata(map);

        NamingService namingService = NacosFactory.createNamingService(properties);
        namingService.registerInstance("nacos.test.1", instance);

        這是服務(wù)注冊(cè)的核心所有代碼。僅從此處的代碼分析,可以看出,Nacos注冊(cè)服務(wù)實(shí)例時(shí),包含了兩大類信息:Nacos Server連接信息和實(shí)例信息。

        Nacos Server連接信息

        Nacos Server連接信息,存儲(chǔ)在Properties當(dāng)中,包含以下信息:

        • Server地址:Nacos服務(wù)器地址,屬性的key為serverAddr;

        • 用戶名:連接Nacos服務(wù)的用戶名,屬性key為username,默認(rèn)值為nacos;

        • 密碼:連接Nacos服務(wù)的密碼,屬性key為password,默認(rèn)值為nacos;

        實(shí)例信息

        注冊(cè)實(shí)例信息用Instance對(duì)象承載,注冊(cè)的實(shí)例信息又分兩部分:實(shí)例基礎(chǔ)信息和元數(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ù)信息;

        Instance類包含了實(shí)例的基礎(chǔ)信息之外,還包含了用于存儲(chǔ)元數(shù)據(jù)的metadata(描述數(shù)據(jù)的數(shù)據(jù)),類型為HashMap。

        從Demo中放了兩個(gè)數(shù)據(jù):

        • netType:顧名思義,網(wǎng)絡(luò)類型,這里的值為external,也就是外網(wǎng)的意思;

        • version:版本,Nacos的版本,這里是2.0這個(gè)大版本。

        除了Demo中這些“自定義”的信息,在Instance類中還定義了一些默認(rèn)信息,這些信息通過get方法提供:

        public long getInstanceHeartBeatInterval() {
        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL,
        Constants.DEFAULT_HEART_BEAT_INTERVAL);
        }

        public long getInstanceHeartBeatTimeOut() {
        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,
        Constants.DEFAULT_HEART_BEAT_TIMEOUT);
        }

        public long getIpDeleteTimeout() {
        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT,
        Constants.DEFAULT_IP_DELETE_TIMEOUT);
        }

        public String getInstanceIdGenerator() {
        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR,
        Constants.DEFAULT_INSTANCE_ID_GENERATOR);
        }

        上面的get方法在需要元數(shù)據(jù)默認(rèn)值時(shí)會(huì)被用到:

        • preserved.heart.beat.interval:心跳間隙的key,默認(rèn)為5s,也就是默認(rèn)5秒進(jìn)行一次心跳;

        • preserved.heart.beat.timeout:心跳超時(shí)的key,默認(rèn)為15s,也就是默認(rèn)15秒收不到心跳,實(shí)例將會(huì)標(biāo)記為不健康;

        • preserved.ip.delete.timeout:實(shí)例IP被刪除的key,默認(rèn)為30s,也就是30秒收不到心跳,實(shí)例將會(huì)被移除;

        • preserved.instance.id.generator:實(shí)例ID生成器key,默認(rèn)為simple;

        這些都是Nacos默認(rèn)提供的值,也就是當(dāng)前實(shí)例注冊(cè)時(shí)會(huì)告訴Nacos Server說(shuō):我的心跳間隙、心跳超時(shí)等對(duì)應(yīng)的值是多少,你按照這個(gè)值來(lái)判斷我這個(gè)實(shí)例是否健康。當(dāng)然,如果你想讓心跳“加速”,出現(xiàn)故障快速被移除,那可以跳短心跳間隙和超時(shí)時(shí)間。但這也意味著給Nacos服務(wù)帶來(lái)一定的壓力。

        有了這些信息,我們基本是已經(jīng)知道注冊(cè)實(shí)例時(shí)需要傳遞什么參數(shù),需要配置什么參數(shù)了。

        NamingService接口

        NamingService接口是Nacos命名服務(wù)對(duì)外提供的一個(gè)統(tǒng)一接口,看對(duì)應(yīng)的源碼就可以發(fā)現(xiàn),它提供了大量實(shí)例相關(guān)的接口方法,比如:

        • 服務(wù)實(shí)例注冊(cè);

        • 服務(wù)實(shí)例注銷;

        • 獲取服務(wù)實(shí)例列表;

        • 獲取服務(wù)單個(gè)實(shí)例;

        • 訂閱服務(wù)事件;

        • 取消訂閱服務(wù)事件;

        • 獲取所有(或指定)服務(wù)名稱;

        • 獲取所有訂閱的服務(wù);

        • 獲取Nacos服務(wù)的狀態(tài);

        • 主動(dòng)關(guān)閉服務(wù);

        其中部分功能提供了大量的重載方法,應(yīng)用于不同場(chǎng)景和不同類型實(shí)例或服務(wù)的篩選。這個(gè)就不逐一說(shuō)明,按照需要或注釋進(jìn)行使用即可。

        NamingService的實(shí)例化是通過NamingFactory類和上面提到的Nacos服務(wù)信息:

        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);
        }
        }

        很明顯,這里采用了反射的機(jī)制來(lái)實(shí)例化NamingService,接口的具體實(shí)現(xiàn)類為NacosNamingService類。

        NacosNamingService的實(shí)現(xiàn)

        在示例代碼中使用了NamingService#registerInstance方法來(lái)進(jìn)行服務(wù)實(shí)例的注冊(cè),該方法接收兩個(gè)參數(shù),服務(wù)名稱和實(shí)例對(duì)象。

        @Override
        public void registerInstance(String serviceName, Instance instance) throws NacosException {
        registerInstance(serviceName, Constants.DEFAULT_GROUP, instance);
        }

        這個(gè)方法的最大作用是設(shè)置了當(dāng)前實(shí)例的分組信息。我們知道,在Nacos中,通過Namespace、group、Service、Cluster等一層層的將實(shí)例進(jìn)行環(huán)境的隔離。在這里設(shè)置了默認(rèn)的分組為“DEFAULT_GROUP”。

        緊接著調(diào)用的registerInstance方法如下:

        @Override
        public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {
        NamingUtils.checkInstanceIsLegal(instance);
        clientProxy.registerService(serviceName, groupName, instance);
        }

        這個(gè)方法實(shí)現(xiàn)了兩個(gè)功能:第一,檢查心跳時(shí)間設(shè)置的對(duì)不對(duì),配置的超時(shí)時(shí)間總不能比心跳間隔還短吧。第二,通過NamingClientProxy這個(gè)代理來(lái)執(zhí)行服務(wù)注冊(cè)操作。

        反觀NacosNamingService構(gòu)造方法,會(huì)發(fā)現(xiàn)NamingClientProxy這個(gè)代理接口的具體實(shí)現(xiàn)是有NamingClientProxyDelegate來(lái)完成的。

        NamingClientProxyDelegate中實(shí)現(xiàn)

        NamingClientProxy調(diào)用registerService實(shí)際上調(diào)用的就是NamingClientProxyDelegate的對(duì)應(yīng)方法:

        @Override
        public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
        getExecuteClientProxy(instance).registerService(serviceName, groupName, instance);
        }

        真正調(diào)用注冊(cè)服務(wù)的并不是代理實(shí)現(xiàn)類,而是根據(jù)當(dāng)前實(shí)例是否為瞬時(shí)對(duì)象,來(lái)選擇對(duì)應(yīng)的客戶端代理來(lái)進(jìn)行請(qǐng)求的:

        private NamingClientProxy getExecuteClientProxy(Instance instance) {
        return instance.isEphemeral() ? grpcClientProxy : httpClientProxy;
        }

        如果當(dāng)前實(shí)例為瞬時(shí)對(duì)象,則采用gRPC協(xié)議(NamingGrpcClientProxy)進(jìn)行請(qǐng)求,否則采用http協(xié)議(NamingHttpClientProxy)進(jìn)行請(qǐng)求。默認(rèn)為瞬時(shí)對(duì)象,也就是說(shuō),2.0版本中默認(rèn)采用了gRPC協(xié)議進(jìn)行與Nacos服務(wù)進(jìn)行交互。

        NamingGrpcClientProxy中實(shí)現(xiàn)

        關(guān)于gRPC協(xié)議這部分我們會(huì)單獨(dú)進(jìn)行講解,這里暫時(shí)不做拓展。主要看其registerService方法實(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);
        namingGrpcConnectionEventListener.cacheInstanceForRedo(serviceName, groupName, instance);
        InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
        NamingRemoteConstants.REGISTER_INSTANCE, instance);
        requestToServer(request, Response.class);
        }

        在NamingGrpcClientProxy中做了兩件事,一件事是通過事件監(jiān)聽器緩存了當(dāng)前注冊(cè)的實(shí)例信息用于恢復(fù)。緩存的數(shù)據(jù)結(jié)構(gòu)為ConcurrentMap<String, Instance>,key為“serviceName@@groupName”,value就是前面封裝的實(shí)例信息。

        另外一件事就是封裝了參數(shù),基于gRPC協(xié)議進(jìn)行服務(wù)的調(diào)用和結(jié)果的處理。

        流程圖

        下面來(lái)看一張流程圖,來(lái)匯總一下上面到的整個(gè)業(yè)務(wù)邏輯: 

        小結(jié)

        關(guān)于Nacos源碼分析的開篇就寫這么多,主要分析了服務(wù)注冊(cè)需要哪些維度的信息、客戶端提供的核心服務(wù)處理類(NamingService)以及注冊(cè)通信協(xié)議的選擇。其中的一些內(nèi)容還可以細(xì)化,比如gRPC協(xié)議的實(shí)現(xiàn)等,我們后續(xù)文章繼續(xù)進(jìn)行呈現(xiàn)。

        如果文章內(nèi)容有問題或想技術(shù)討論請(qǐng)聯(lián)系我(微信:zhuan2quan,備注Nacos),如果覺得寫的還不錯(cuò),值得一起學(xué)習(xí),那就關(guān)注一下吧。


        往期推薦

        微服務(wù)架構(gòu):Nacos本地緩存 PK 微服務(wù)優(yōu)雅下線

        微服務(wù):剖析一下源碼,Nacos的健康檢查竟如此簡(jiǎn)單

        微服務(wù)之:服務(wù)掛的太干脆,Nacos還沒反應(yīng)過來(lái),怎么辦?

        微服務(wù)之吐槽一下Nacos日志的瘋狂輸出

        學(xué)習(xí)Nacos?咱先把服務(wù)搞起來(lái),實(shí)戰(zhàn)教程~

        你也對(duì)閱讀源碼感興趣,說(shuō)說(shuō)我是如何閱讀Nacos源碼的

        微服務(wù)的靈魂擺渡者——Nacos,來(lái)一篇原理全攻略

        要學(xué)習(xí)微服務(wù)的服務(wù)發(fā)現(xiàn)?先來(lái)了解一些科普知識(shí)吧



        如果你覺得這篇文章不錯(cuò),那么,下篇通常會(huì)更好。添加微信好友,可備注“加群”(微信號(hào):zhuan2quan)。

        一篇文章就看透技術(shù)本質(zhì)的人,
          和花一輩子都看不清的人,
          注定是截然不同的搬磚生涯。
        ▲ 長(zhǎng)按關(guān)注”程序新視界“,洞察技術(shù)內(nèi)幕


        瀏覽 66
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            四虎激情影院| 国产乱伦对白| 色天堂污| 久久久永久免费视频| 欧美A级黄片| 一级操逼视频免费观看| 肏屄视频在线观看| 伊人久久大香| 色呦呦中文字幕| 日本精品中文字幕| 国产一级a毛一级a毛视频在线网站)| 色色网的五月天| 五月天色色图| 在线成人视频网站大香蕉在线网站 | 日本欧美在线视频| 日本韩国欧美18| 日本免费在线黄色视频| 国产在线观看mv免费全集电视剧大全 | 亚洲色情在线| 啪啪视频最新地址发布页| 免费视频无码| 蜜桃系列一区二区精品| 久草视频在线免费看| 91婷婷在线| 影音先锋亚洲无码| 伊人色爱| 一品国精和二品国精的文化意义| 国产视频久久| 日韩一区二区视频| 成人福利| 九色精品| 亚洲三级片视频| 东京热在线免费观看| 亚洲乱码精品久久久久..| 色五月在线观看| 俺去俺来也| 国产人妻一区二区精选| 色播国产成人AV| 婷婷久热| 国产亚洲视频免费观看| 天天日天天干天天爽| 1024手机在线观看| 操b免费| 日韩一区二区三免费高清在线观看| 搞黄免费视频视频| 日韩高清国产一区在线| 看毛片网站| 蜜桃一区二区三区| 亚洲精品午夜福利| 最新国产av| 免费一级做a爱片毛片A片小说| 日韩午夜成人电影| 国产成人高潮毛片| 亚洲无码成人视频| 成人超碰| 男人天堂手机在线| www尤物| 亚洲福利一区| 超碰性爱| 激情五月天导航| 玖玖资源站中文字幕| 亚洲a√| 91av免费在线观看| 久久另类TS人妖一区二区| 在线免费看黄网站| 第一页在线观看| 婷婷毛片| 天天爽天天爽夜夜爽毛片| 国产97在线视频| 一区二区三区四区五区| 少妇av| 一级a免一级a做片免费| 日韩性生活网| 成人免费三级| 日日艹夜夜艹| 三级片免费网址| 无码无码一区二区三区| 日韩人妻精品中文字幕专区不卡| 黄色三级电影| 欧美国产视频| 成人黄色性爱视频| 成人精品电影| 亚洲精品中文字幕在线观看 | 在线h片| 亚洲黄色在线视频| 黑人无码在线| 91无码电影| 亚洲日韩国产AV无码无码精品| 欧美日韩性爱视频| 成人无码区免费AV毛片| 欧美成人视频网站| 亚洲资源站| 欧美A级视频| 久操| 国产无码AV大片| 韩国日本美国免费毛片| 免费看AV大片| 一区无码免费| 四川妇搡BBBB搡BBBB| 天天操视频网站| 亚洲AV永久无码国产精品久久| 88AV在线观看| 亚洲无码免费网站| 国产精品久久久久久无人区| 操B视频免费看| 欧美性猛交XXXX乱大交HD| 青青草精品在线视频| 日韩av在线电影| 亚洲高清无码一区二区三区| 丁香婷婷五月色成人网站| 91网址| 自拍av在线| 丰满的人妻一区二区三区果冻| www.91爱爱,com| 国产九色91回来了| 就去se超碰| 性欧美成人播放77777| 亚洲日韩欧美国产| 人人操人人网站| 欧洲无码精品| 人人看人人艹| 中文无码在线观看中文字幕av中文| 国产视频激情| 亚洲成人无码av| 日本特级黄A片免费观看| 五月婷婷丁香综合| 青青草视频在线免费观看| 第一页在线| 九鼎联盟骗子| 色天堂色男人| 自慰一区| 久久久久久久9999| 老熟女伦一区二区三区| 91大香蕉视频| 国内精品卡一卡二卡三| 国产精品96久久久| 日韩一区二区三区视频| 丁香六月婷婷久久综合| 一级毛AA片| 久久婷婷青青| 久久久久99精品成人片直播 | 婷婷成人综合| 四川少妇BBBB槡BBBB槡| 一区二区三区电影高清电影免费观看 | 热re99久久精品国产99热| 天堂中文在线播放| 成人AV一区二区三区| 亚洲专区在线播放| 九色PORNY国产成人| 午夜探花| 国产在线不卡年轻点的| 亚洲无人禁区| 国产夫妻自拍av| 新超碰97| 欧美性爱视频免费观看| 欧美性猛交XXXX乱大交| 日韩在线综合| 成人精品无码| 特黄特色免费大片| 日本精品三级| 91涩| 欧美精品系列| 日韩性爱视频网站| 亚洲中文字幕在线免费观看视频| 狠狠干综合| 激情五月天小说网| 亚洲中文AV在线| 中文字幕乱码无码人妻系列蜜桃 | 午夜成人亚洲| 欧一美一婬一伦一区二区三区自慰国 | 成人黄片18| 亚洲三级无码| 精品人妻一区二区三区四区| 911国产视频| 欧美亚洲成人在线观看| 久久午夜福利电影| ThePorn人妻白浆| 欧洲精品在线观看| 极品美女援交在线| 日韩中文字幕区| 色哟哟一中文字慕| 丁香五月网站| 午夜福利成人视频| 日韩毛片在线| 成人蜜臀AV| 97干在线| 久久久久一区| 成人无码视频在线观看| 亚洲在线免费视频| 免费观看久久久| 亚洲日韩在线视频播放| 亚洲高清视频免费| 中文字幕天天干| 日韩无码网址| 欧美日韩午夜福利视频| 香蕉视频a| 色悠悠久久综合| 久久999| 欧美在线网站| 亚洲日韩视频| 韩国无码AV| 最近日本中文字幕中文翻译歌词| 蜜桃av无码一区二区三区| 熟妇自拍| 辽宁模特张雪馨视频最新| 国外操逼视频| 精品码产区一区二亚洲国产| 无码中文字幕在线播放| 人人操人人插| 天天操免费| 91天天操| 亚洲小视频在线播放| 日韩一级免费毛片| 国产三级片在线观看| 亚洲图片中文字幕| 韩国三级HD久久精品| 成人色综合| 91搞搞| 久久人人做| 无码电影在线播放| 国产福利免费| 久久精品视频免费| AA级黄色视频| 97pao| 操逼网国产| 不卡在线视频| 色色视频免费看| 丁香婷婷综合网| 老女人日逼视频| 激情网页| 亚洲国产成人精品激情在线 | 人妻中文字幕av| 裸体美女视频欧美18| 免费看无码一级A片在线播放| 激情麻豆论坛| 亚洲欧美在线成人| 四个熟妇搡BBBB搡BBBB| 日本无码在线播放| 久久久97精品久久| 加勒比一区二区三区| AV黄色网址| 在线免费观看黄色| 99久久久国产精品免费蜜臀| 九一国产在线| 人人看人人草| 嫩BBB嗓BBBB榛BBBB| 亚洲Av无码午夜国产精品色软件 | 91N视频| 高清无码免费不卡| 日本精品码喷水在线看| 水果派解说A∨无码区| 精品人妻一区二区免费蜜桃| 人人看人人草| 日本操逼在线播放| 91精品人妻一区二区三区四区 | 五月婷婷色色网| 2014av天堂网| 国产成人精品无码免费| 久热9191| 五月丁香电影| 91免费视频观看| 中文字幕首页| 欧美女人日逼视频| 成人视频无码| 国产一级a毛一级a毛片视频黑人 | 免费涩涩无遮挡18国产| 壁特壁视频在线观看| 国产精品三级| 大地中文资源5页的更新内容| 成人精品无码免费视频| 一插菊花综合网| 欧美日韩综合网| 日韩黄色在线| 日本爱爱视频| 九九九网站| 日韩成人A片| 国精产品秘一区二区| 91久久精品日日躁夜夜躁欧美| 亚洲手机视频| www.在线播放| 国产午夜精品一区二区三区牛牛| 黄色国产av| 啪啪人妻| 亚洲二区在线| 91Av视频| 夜夜夜夜撸| 亚洲色综合久久五月| 人人色人人色| 黄色大片在线播放| 夜夜夜操| 伊人春色AV| 青草视频网| 国产无码高清视频| 大鸡巴日小逼| 精品欧美一区二区三区久久久| 日韩精品视频在线| 免费在线观看内射| 中文字幕观看在线| 国产欧美日韩成人| 国产乱子伦一区二区三区在线观看|