欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Alibaba?Nacos配置中心動(dòng)態(tài)感知原理示例解析

 更新時(shí)間:2023年08月02日 08:44:25   作者:Mr.Fire  
這篇文章主要介紹了Alibaba?Nacos配置中心動(dòng)態(tài)感知原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

Nacos提供兩大核心功能,服務(wù)注冊(cè)發(fā)現(xiàn),配置中心。對(duì)應(yīng)Nacos的架構(gòu)圖,分別是Naming Service和Config Service,其中Config Service是實(shí)現(xiàn)配置中心的核心模塊。實(shí)現(xiàn)了版本管理、灰度發(fā)布、監(jiān)聽(tīng)管理、推送軌跡等功能。針對(duì)配置中心,當(dāng)我們通過(guò)控制臺(tái)或API修改配置之后,客戶(hù)端能動(dòng)態(tài)獲取到修改后的配置,那么配置中心是如何實(shí)現(xiàn)動(dòng)態(tài)感知的呢?

動(dòng)態(tài)監(jiān)聽(tīng)之Pull和Push

當(dāng)Nacos Config Server上的配置發(fā)生變化時(shí),需要讓相關(guān)的應(yīng)用程序感知到配置的變化,這就需要客戶(hù)端對(duì)感興趣的配置實(shí)現(xiàn)監(jiān)聽(tīng)。那么客戶(hù)端是如何實(shí)現(xiàn)配置變更實(shí)時(shí)更新的呢?

一般來(lái)說(shuō),客戶(hù)端與服務(wù)端的交互無(wú)非兩種:Pull模式和Push模式,一個(gè)是客戶(hù)端主動(dòng)拉取,一個(gè)是服務(wù)端主動(dòng)推送。

  • Pull模式:服務(wù)端和客戶(hù)端之間需要維護(hù)長(zhǎng)連接,客戶(hù)端多的情況下耗內(nèi)存、需要心跳機(jī)制檢測(cè)連接狀態(tài)。
  • Push模式:客戶(hù)端需要定時(shí)拉取數(shù)據(jù),不能保證實(shí)時(shí)性,服務(wù)端長(zhǎng)時(shí)間不更新的情況下,定時(shí)任務(wù)為無(wú)效更新,浪費(fèi)資源。

Nacos的Pull模式

Nacos采用的是Pull模式,不過(guò)不是簡(jiǎn)單的Pull,而是一種長(zhǎng)輪詢(xún)機(jī)制。結(jié)合Pull和Push兩者的優(yōu)勢(shì),客戶(hù)端采用長(zhǎng)輪詢(xún)的方式發(fā)起Pull請(qǐng)求,檢查服務(wù)配置消息是否發(fā)生變化,如果更新,客戶(hù)端會(huì)根據(jù)變更的內(nèi)容獲取最新配置信息。

所謂的長(zhǎng)輪詢(xún),就是客戶(hù)端發(fā)起Pull請(qǐng)求之后,服務(wù)端如果發(fā)生配置變更則立即返回,如果服務(wù)端和客戶(hù)端配置是保持一致的,那么服務(wù)端會(huì)“Hold”住這個(gè)請(qǐng)求,在指定時(shí)間內(nèi)不返回結(jié)果,直到這段時(shí)間內(nèi)配置發(fā)生變化。這個(gè)長(zhǎng)連接默認(rèn)超時(shí)時(shí)間是30s。

服務(wù)端收到請(qǐng)求后,先檢查配置是否發(fā)生變化,如果沒(méi)變化,則設(shè)置一個(gè)定時(shí)任務(wù),延期29.5s執(zhí)行,并且把當(dāng)前的客戶(hù)端長(zhǎng)輪詢(xún)連接加入allSubs隊(duì)列。這里有兩種方式觸發(fā)連接返回。

  • 等待29.5s自動(dòng)觸發(fā)檢查機(jī)制,無(wú)論是否發(fā)生變化,都會(huì)返回。
  • 在29.5s內(nèi),通過(guò)Nacos控制臺(tái)或者API的形式對(duì)配置進(jìn)行了修改,會(huì)觸發(fā)ConfigDataChangeEvent事件。

Nacos的動(dòng)態(tài)感知

前面我們已經(jīng)知道客戶(hù)端通過(guò)長(zhǎng)輪詢(xún)請(qǐng)求來(lái)獲取配置變更,但是定時(shí)任務(wù)是延遲執(zhí)行的,那并沒(méi)有達(dá)到實(shí)時(shí)的目的,當(dāng)通過(guò)控制臺(tái)或者API修改配置時(shí),那Nacos是如何實(shí)時(shí)動(dòng)態(tài)更新的呢?

LongPollingService 監(jiān)聽(tīng)事件類(lèi)

LongPollingService繼承AbstractEventListener,AbstractEventListener是事件抽象類(lèi),它有一個(gè)onEvent抽象方法,而LongPollingService實(shí)現(xiàn)了這個(gè)方法

@Override
public void onEvent(Event event) {
    if (isFixedPolling()) {
        // ignore
    } else {
        if (event instanceof LocalDataChangeEvent) {
            LocalDataChangeEvent evt = (LocalDataChangeEvent)event;
            scheduler.execute(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
        }
    }
}

LongPollingService可以看到LocalDataChangeEvent事件,這個(gè)事件是服務(wù)端的配置數(shù)據(jù)發(fā)生變化時(shí)發(fā)布的一個(gè)事件。onEvent方法中通過(guò)線(xiàn)程池來(lái)執(zhí)行一個(gè)DataChangeTask任務(wù)。

DataChangeTask線(xiàn)程

DataChangeTask是一個(gè)線(xiàn)程,實(shí)現(xiàn)了Runnable接口,對(duì)應(yīng)的run()如下:

class DataChangeTask implements Runnable {
    @Override
    public void run() {
        try {
            ConfigService.getContentBetaMd5(groupKey);
            for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {
                ClientLongPolling clientSub = iter.next();
                if (clientSub.clientMd5Map.containsKey(groupKey)) {
                    // 如果beta發(fā)布且不在beta列表直接跳過(guò)
                    if (isBeta && !betaIps.contains(clientSub.ip)) {
                        continue;
                    }
                    // 如果tag發(fā)布且不在tag列表直接跳過(guò)
                    if (StringUtils.isNotBlank(tag) && !tag.equals(clientSub.tag)) {
                        continue;
                    }
                    getRetainIps().put(clientSub.ip, System.currentTimeMillis());
                    iter.remove(); // 刪除訂閱關(guān)系
                    LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}|{}",
                        (System.currentTimeMillis() - changeTime),
                        "in-advance",
                        RequestUtil.getRemoteIp((HttpServletRequest)clientSub.asyncContext.getRequest()),
                        "polling",
                        clientSub.clientMd5Map.size(), clientSub.probeRequestSize, groupKey);
                    clientSub.sendResponse(Arrays.asList(groupKey));
                }
            }
        } catch (Throwable t) {
            LogUtil.defaultLog.error("data change error:" + t.getMessage(), t.getCause());
        }
    }
    DataChangeTask(String groupKey) {
        this(groupKey, false, null);
    }
    DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps) {
        this(groupKey, isBeta, betaIps, null);
    }
    DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps, String tag) {
        this.groupKey = groupKey;
        this.isBeta = isBeta;
        this.betaIps = betaIps;
        this.tag = tag;
    }
    final String groupKey;
    final long changeTime = System.currentTimeMillis();
    final boolean isBeta;
    final List<String> betaIps;
    final String tag;
}
  • 遍歷allSubs中的客戶(hù)端長(zhǎng)輪詢(xún)請(qǐng)求。
  • 比較每個(gè)客戶(hù)端長(zhǎng)輪詢(xún)請(qǐng)求攜帶的groupKey,如果服務(wù)端變更的配置和客戶(hù)端請(qǐng)求關(guān)注的配置一致,則直接返回,這里調(diào)用clientSub.sendResponse()方法返回。

總結(jié)

好了,最后整理下nacos實(shí)時(shí)動(dòng)態(tài)感知的流程如下:

  • 客戶(hù)端通過(guò)長(zhǎng)輪詢(xún)的方式發(fā)起Pull請(qǐng)求服務(wù)端獲取配置變更;
  • 服務(wù)端判斷如果是長(zhǎng)輪詢(xún)請(qǐng)求,對(duì)比數(shù)據(jù)的MD5,如果發(fā)生變化則直接返回,否則通過(guò)延遲任務(wù)執(zhí)行ClientLongPolling線(xiàn)程;
  • 配置中心修改配置后,會(huì)發(fā)布ConfigDataChangeEvent事件;
  • EventDispatcher觸發(fā)事件,通知監(jiān)聽(tīng)者。LongPollingService就是監(jiān)聽(tīng)者之一。
  • 監(jiān)聽(tīng)者通過(guò)線(xiàn)程池開(kāi)啟定時(shí)線(xiàn)程,遍歷客戶(hù)端的所有長(zhǎng)輪詢(xún)的請(qǐng)求, 通過(guò)groupKey匹配到對(duì)應(yīng)請(qǐng)求,直接返回。

以上就是Alibaba Nacos配置中心動(dòng)態(tài)感知原理示例解析的詳細(xì)內(nèi)容,更多關(guān)于Alibaba Nacos配置中心動(dòng)態(tài)感知的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringCloud基于Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的問(wèn)題小結(jié)

    SpringCloud基于Feign實(shí)現(xiàn)遠(yuǎn)程調(diào)用的問(wèn)題小結(jié)

    這篇文章主要介紹了SpringCloud基于Feign遠(yuǎn)程調(diào)用,通過(guò)使用 Feign 的方式,我們可以更加優(yōu)雅地進(jìn)行多參數(shù)的遠(yuǎn)程調(diào)用,避免了手動(dòng)拼接URL或構(gòu)建復(fù)雜的請(qǐng)求體,需要的朋友可以參考下
    2024-02-02
  • Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Boot中的SpringSecurity基礎(chǔ)教程

    Spring Security是一個(gè)功能強(qiáng)大且高度可定制的身份驗(yàn)證和訪(fǎng)問(wèn)控制框架。它實(shí)際上是保護(hù)基于spring的應(yīng)用程序的標(biāo)準(zhǔn)Spring Security是一個(gè)框架,側(cè)重于為Java應(yīng)用程序提供身份驗(yàn)證和授權(quán),這篇文章主要介紹了Spring Boot中的SpringSecurity學(xué)習(xí),需要的朋友可以參考下
    2023-01-01
  • 深入淺析springsecurity入門(mén)登錄授權(quán)

    深入淺析springsecurity入門(mén)登錄授權(quán)

    SpringSecurity為我們提供了基于注解的權(quán)限控制方案,這也是我們項(xiàng)目中主要采用的方式,我們可以使用注解去指定訪(fǎng)問(wèn)對(duì)應(yīng)的資源所需的權(quán)限,這篇文章主要介紹了springsecurity入門(mén)登錄授權(quán),需要的朋友可以參考下
    2024-05-05
  • java之swing單選框用法實(shí)例分析

    java之swing單選框用法實(shí)例分析

    這篇文章主要介紹了java之swing單選框用法,以實(shí)例形式分析了swing圖形界面單選框的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • 如何用java對(duì)接微信小程序下單后的發(fā)貨接口

    如何用java對(duì)接微信小程序下單后的發(fā)貨接口

    這篇文章主要介紹了在微信小程序后臺(tái)實(shí)現(xiàn)發(fā)貨通知的步驟,包括獲取Access_token、使用RestTemplate調(diào)用發(fā)貨接口、處理AccessToken緩存以及發(fā)貨成功后的提醒,需要的朋友可以參考下
    2025-03-03
  • 詳解三種java實(shí)現(xiàn)多線(xiàn)程的方式

    詳解三種java實(shí)現(xiàn)多線(xiàn)程的方式

    數(shù)據(jù)時(shí)代的到來(lái),多線(xiàn)程一直都是比較關(guān)心的問(wèn)題之一,這篇文章介紹了JAVA實(shí)現(xiàn)多線(xiàn)程的三種方法,有需要的朋友可以參考一下
    2015-08-08
  • Java8 Stream對(duì)兩個(gè) List 遍歷匹配數(shù)據(jù)的優(yōu)化處理操作

    Java8 Stream對(duì)兩個(gè) List 遍歷匹配數(shù)據(jù)的優(yōu)化處理操作

    這篇文章主要介紹了Java8 Stream對(duì)兩個(gè) List 遍歷匹配數(shù)據(jù)的優(yōu)化處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決

    kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決

    這篇文章主要介紹了kafka 啟動(dòng)報(bào)錯(cuò) missingTopicsFatal is true的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java如何將json字符串與實(shí)體類(lèi)互相轉(zhuǎn)換

    Java如何將json字符串與實(shí)體類(lèi)互相轉(zhuǎn)換

    在我們調(diào)用三方平臺(tái)接口時(shí),經(jīng)常需要將我們封裝的實(shí)體類(lèi)轉(zhuǎn)換為json作為傳參,下面這篇文章主要給大家介紹了關(guān)于Java如何將json字符串與實(shí)體類(lèi)互相轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Java并發(fā)編程之threadLocal

    Java并發(fā)編程之threadLocal

    ThreadLocal是JDK包提供的,它提供了線(xiàn)程本地變量,也就是說(shuō)如果創(chuàng)建了一個(gè)ThreadLocal變量,需要的朋友可以參考一下喲
    2021-09-09

最新評(píng)論