Nacos系列:Nacos的Java SDK使用

Maven依賴

Nacos提供完整的Java SDK秕狰,便于配置管理和服務發(fā)現(xiàn)及管理奥洼,以 Nacos-0.8.0 版本為例

添加Maven依賴:

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>0.8.0</version>
</dependency>

僅僅引入nacos-client是不夠的棚放,否則啟動時會出現(xiàn)如下錯誤:

sun.misc.Launcher$AppClassLoader@18b4aac2 JM.Log:WARN Init JM logger with NopLoggerFactory, pay attention. sun.misc.Launcher$AppClassLoader@18b4aac2
java.lang.ClassNotFoundException: org.apache.logging.log4j.core.Logger
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.alibaba.nacos.client.logger.log4j2.Log4j2LoggerFactory.<init>(Log4j2LoggerFactory.java:33)
    at com.alibaba.nacos.client.logger.LoggerFactory.<clinit>(LoggerFactory.java:59)
    at com.alibaba.nacos.client.config.utils.LogUtils.<clinit>(LogUtils.java:49)
    at com.alibaba.nacos.client.config.NacosConfigService.<clinit>(NacosConfigService.java:55)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.alibaba.nacos.api.config.ConfigFactory.createConfigService(ConfigFactory.java:40)
    at com.alibaba.nacos.api.config.ConfigFactory.createConfigService(ConfigFactory.java:59)
    at com.alibaba.nacos.api.NacosFactory.createConfigService(NacosFactory.java:52)
    at com.learn.nacos.config.NacosConfig.main(NacosConfig.java:12)

根據(jù)錯誤提示票摇,應該還需要添加log4j相關依賴昌执,官網(wǎng)的文檔并沒有對此說明,我在pom.xml添加了下面這些依賴才不報錯

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.11</version>
</dependency>
<dependency>
    <groupId>org.logback-extensions</groupId>
    <artifactId>logback-ext-spring</artifactId>
    <version>0.1.4</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

配置管理

創(chuàng)建ConfigService都弹,可以通過 NacosFactory.createConfigService()ConfigFactory.createConfigService() 來創(chuàng)建,后者是前者的底層實現(xiàn)方式匙姜,這兩種方式都包含如下兩個方法:

createConfigService(serverAddr)
createConfigService(properties)

創(chuàng)建示例:

// 方式一
String serverAddr = "127.0.0.1:8848";
ConfigService configService = ConfigFactory.createConfigService(serverAddr);

// 方式二
ConfigService configService = ConfigFactory.createConfigService(properties)
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);

查看ConfigService源碼畅厢,它提供了如下方法:

獲取 Nacos Server 當前狀態(tài)String getServerStatus()

底層源碼:

public String getServerStatus() {
    if (worker.isHealthServer()) {
        return "UP";
    } else {
        return "DOWN";
    }
}

根據(jù)源碼注釋,該狀態(tài)應該是指 Nacos Server 的狀態(tài)氮昧,我把 Nacos Server 關閉之后框杜,再次運行示例,得到的結(jié)果仍然是UP袖肥,不知道這是不是一個BUG咪辱。

發(fā)布配置boolean publishConfig(String dataId, String group, String content) throws NacosException

支持程序自動發(fā)布Nacos配置,創(chuàng)建和修改配置使用同一個方法椎组,配置不存在則創(chuàng)建油狂;配置已存在則更新。

底層源碼:

try {
    result = agent.httpPost(url, headers, params, encode, POST_TIMEOUT);
} catch (IOException ioe) {
    log.warn("NACOS-0006",
        LoggerHelper.getErrorCodeStr("NACOS", "NACOS-0006", "環(huán)境問題", "[publish-single] exception"));
    log.warn(agent.getName(), "[publish-single] exception, dataId={}, group={}, msg={}", dataId, group,
        ioe.toString());
    return false;
}

發(fā)布配置后寸癌,如果馬上用getConfig()讀取配置专筷,有時候會讀不到,設置了足夠的等待時長后才可保證每次正常讀取蒸苇,看了源碼才知道Nacos的配置管理(發(fā)布磷蛹、讀取、移除)都是通過HTTP接口完成的溪烤,但發(fā)布配置的時延是多少味咳,官網(wǎng)似乎沒有說明?幾秒鐘的時延在一些對實時性要求很高的場景會不會存在影響呢檬嘀?

讀取配置String getConfig(String dataId, String group, long timeoutMs) throws NacosException

timeoutMs指讀取配置超時時間槽驶,官網(wǎng)推薦設置為3000ms

底層源碼:

// 優(yōu)先使用本地配置
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
if (content != null) {
    log.warn(agent.getName(), "[get-config] get failover ok, dataId={}, group={}, tenant={}, config={}", dataId,
        group, tenant, ContentUtils.truncateContent(content));
    cr.setContent(content);
    configFilterChainManager.doFilter(null, cr);
    content = cr.getContent();
    return content;
}

try {
    content = worker.getServerConfig(dataId, group, tenant, timeoutMs);

    cr.setContent(content);
    configFilterChainManager.doFilter(null, cr);
    content = cr.getContent();

    return content;
} catch (NacosException ioe) {
    if (NacosException.NO_RIGHT == ioe.getErrCode()) {
        throw ioe;
    }
    log.warn("NACOS-0003",
        LoggerHelper.getErrorCodeStr("NACOS", "NACOS-0003", "環(huán)境問題", "get from server error"));
    log.warn(agent.getName(), "[get-config] get from server error, dataId={}, group={}, tenant={}, msg={}",
        dataId, group, tenant, ioe.toString());
}

從源碼上看,配置會先從本地緩存文件讀取鸳兽,如果沒讀取到掂铐,才會去請求Nacos Server的配置,這個緩存文件在哪呢贸铜?就在當前用戶的nacos目錄下
生成的緩存文件:nacos/config/fixed-127.0.0.1_8848_nacos/snapshot/DEFAULT_GROUP/nacos-sdk-java-config堡纬,配置內(nèi)容和發(fā)布到Nacos Server的配置內(nèi)容是一致的。

移除配置boolean removeConfig(String dataId, String group) throws NacosException

支持程序自動發(fā)布Nacos配置蒿秦,配置不存在時會直接返回成功烤镐,移除配置后,本地的緩存文件也會被刪除

底層源碼:

try {
    result = agent.httpDelete(url, null, params, encode, POST_TIMEOUT);
} catch (IOException ioe) {
    log.warn("[remove] error, " + dataId + ", " + group + ", " + tenant + ", msg: " + ioe.toString());
    return false;
}

移除配置同發(fā)布配置一樣棍鳖,如果移除后馬上查詢炮叶,有可能還能將剛移除的配置查出來碗旅,也存在一定的時延,需要設置等待時間讀取镜悉。

添加配置監(jiān)聽void addListener(String dataId, String group, Listener listener) throws NacosException

支持動態(tài)監(jiān)聽配置的變化祟辟,運行示例源碼,在Nacos控制臺把配置內(nèi)容修改為sdk-java-config:change from nacos console侣肄,此時觀看IDE控制臺旧困,你會看到如下打印信息:

當前線程:com.alibaba.nacos.client.Worker.longPollingfixed-127.0.0.1_8848 ,監(jiān)聽到配置內(nèi)容變化:sdk-java-config:change from nacos console

移除配置監(jiān)聽void removeListener(String dataId, String group, Listener listener)

移除監(jiān)聽后,配置的變化不會再監(jiān)聽

啟動完整示例稼锅,運行結(jié)果如下吼具,請注意配置監(jiān)聽線程和配置管理線程不是同一個線程

當前線程:main ,服務狀態(tài):UP
添加監(jiān)聽
添加監(jiān)聽成功
發(fā)布配置
發(fā)布配置成功
當前線程:com.alibaba.nacos.client.Worker.longPollingfixed-127.0.0.1_8848 ,監(jiān)聽到配置內(nèi)容變化:nacos-sdk-java-config:init
當前線程:main ,發(fā)布配置后獲取配置內(nèi)容:nacos-sdk-java-config:init
重新發(fā)布配置
重新發(fā)布配置成功
當前線程:main ,重新發(fā)布配置后獲取配置內(nèi)容:sdk-java-config:update
當前線程:com.alibaba.nacos.client.Worker.longPollingfixed-127.0.0.1_8848 ,監(jiān)聽到配置內(nèi)容變化:sdk-java-config:update
當前線程:com.alibaba.nacos.client.Worker.longPollingfixed-127.0.0.1_8848 ,監(jiān)聽到配置內(nèi)容變化:sdk-java-config:change from nacos console
移除配置
移除配置成功
當前線程:main ,移除配置后獲取配置內(nèi)容:null
取消監(jiān)聽
取消監(jiān)聽成功

服務管理

創(chuàng)建NamingService,可以通過 NacosFactory.createNamingService()NamingFactory.createNamingService() 來創(chuàng)建矩距,后者是前者的底層實現(xiàn)方式拗盒,這兩種方式都包含如下兩個方法:

createNamingService(serverAddr)
createNamingService(properties)

創(chuàng)建示例:

// 方式一
String serverAddr = "127.0.0.1:8848";
NamingService namingService = NamingFactory.createNamingService(serverAddr);

// 方式二
NamingService namingService = NamingFactory.createNamingService(properties)
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);

查看NamingService類源碼,它提供了如下方法:

獲取 Nacos Server 當前狀態(tài)String getServerStatus()

注冊服務實例void registerInstance(多個參數(shù))

方式一:
String serverIp = "127.0.0.1";
int serverPort = 8848;
String serverAddr = serverIp + ":" + serverPort;
String serviceName = "nacos-sdk-java-discovery";
NamingService namingService = NamingFactory.createNamingService(serverAddr);
namingService.registerInstance(serviceName, serverIp, serverPort);

方式二:
Instance instance = new Instance();
instance.setIp(serverIp);//IP
instance.setPort(serverPort);//端口
instance.setServiceName(serviceName);//服務名
instance.setEnabled(true);//true: 上線 false: 下線
instance.setHealthy(healthy);//健康狀態(tài)
instance.setWeight(1.0);//權(quán)重
instance.addMetadata("nacos-sdk-java-discovery", "true");//元數(shù)據(jù)
NamingService namingService = NamingFactory.createNamingService(serverAddr);
namingService.registerInstance(serviceName, instance);

注冊后锥债,本地會生成緩存文件
1陡蝇、在Nacos安裝目錄data目錄下:data/naming/data/public/com.alibaba.nacos.naming.domains.meta.public##nacos-sdk-java-discovery
2、當前用戶的nacos目錄下:/nacos/naming/public/failover/nacos-sdk-java-discovery
3哮肚、當前用戶的nacos目錄下:/nacos/naming/public/nacos-sdk-java-discovery

即使刪除服務實例登夫,上面三個緩存文件也不會被刪除,Nacos控制臺服務列表中該服務也還存在著(但服務實例數(shù)會變成0)绽左;刪除Nacos控制臺的該服務悼嫉,安全目錄data目錄下的緩存文件會被刪除艇潭,但當前用戶的nacos目錄下的文件不會被刪除拼窥,這里面是什么機制,我暫時還沒整明白蹋凝,等后面整明白了再來補充鲁纠。

刪除服務實例void deregisterInstance(多個參數(shù))

獲取所有服務實例List<Instance> getAllInstances(多個參數(shù))

獲取所有健康或不健康的服務實例List<Instance> selectInstances(多個參數(shù))

隨機獲取一個健康實例(根據(jù)負載均衡算法)Instance selectOneHealthyInstance(多個參數(shù))

添加服務實例監(jiān)聽void subscribe(多個參數(shù))

添加服務實例監(jiān)聽void unsubscribe(多個參數(shù))

分頁獲取所有服務實例ListView<String> getServicesOfServer(多個參數(shù))

獲取所有監(jiān)聽的服務實例List<ServiceInfo> getSubscribeServices()

啟動完整示例,運行結(jié)果如下鳍寂,請注意服務實例監(jiān)聽線程和服務實例管理線程不是同一個線程

當前線程:main ,服務狀態(tài):UP
注冊實例
注冊實例成功
添加監(jiān)聽
添加監(jiān)聽成功
當前線程:main ,注冊實例后獲取所有實例:[{"clusterName":"DEFAULT","enabled":true,"instanceId":"127.0.0.1#8848#DEFAULT#nacos-sdk-java-discovery","ip":"127.0.0.1","metadata":{},"port":8848,"serviceName":"nacos-sdk-java-discovery","valid":true,"weight":1.0}]
當前線程:main ,注冊實例后獲取所有健康實例:[{"clusterName":"DEFAULT","enabled":true,"instanceId":"127.0.0.1#8848#DEFAULT#nacos-sdk-java-discovery","ip":"127.0.0.1","metadata":{},"port":8848,"serviceName":"nacos-sdk-java-discovery","valid":true,"weight":1.0}]
當前線程:com.alibaba.nacos.naming.client.listener ,監(jiān)聽到實例名稱:nacos-sdk-java-discovery
當前線程:com.alibaba.nacos.naming.client.listener ,監(jiān)聽到實例內(nèi)容:[{"clusterName":"DEFAULT","enabled":true,"instanceId":"127.0.0.1#8848#DEFAULT#nacos-sdk-java-discovery","ip":"127.0.0.1","metadata":{},"port":8848,"serviceName":"nacos-sdk-java-discovery","valid":true,"weight":1.0}]
當前線程:main ,注冊實例后獲取一個健康實例:{"clusterName":"DEFAULT","enabled":true,"instanceId":"127.0.0.1#8848#DEFAULT#nacos-sdk-java-discovery","ip":"127.0.0.1","metadata":{},"port":8848,"serviceName":"nacos-sdk-java-discovery","valid":true,"weight":1.0}
當前線程:com.alibaba.nacos.naming.client.listener ,監(jiān)聽到實例名稱:nacos-sdk-java-discovery
當前線程:com.alibaba.nacos.naming.client.listener ,監(jiān)聽到實例內(nèi)容:[{"clusterName":"DEFAULT","enabled":true,"instanceId":"127.0.0.1#8848#DEFAULT#nacos-sdk-java-discovery","ip":"127.0.0.1","metadata":{"change":"true;"},"port":8848,"serviceName":"nacos-sdk-java-discovery","valid":true,"weight":2.0}]
取消監(jiān)聽
取消監(jiān)聽成功
刪除實例
刪除實例成功
Exception in thread "main" java.lang.IllegalStateException: no host to srv for serviceInfo: nacos-sdk-java-discovery
    at com.alibaba.nacos.client.naming.core.Balancer$RandomByWeight.selectAll(Balancer.java:45)
    at com.alibaba.nacos.client.naming.core.Balancer$RandomByWeight.selectHost(Balancer.java:53)
    at com.alibaba.nacos.client.naming.NacosNamingService.selectOneHealthyInstance(NacosNamingService.java:270)
    at com.alibaba.nacos.client.naming.NacosNamingService.selectOneHealthyInstance(NacosNamingService.java:263)
    at com.alibaba.nacos.client.naming.NacosNamingService.selectOneHealthyInstance(NacosNamingService.java:253)
    at com.learn.nacos.discovery.NacosDiscovery.main(NacosDiscovery.java:121)
當前線程:main ,刪除實例后獲取所有實例:[]
當前線程:main ,刪除實例后獲取所有健康實例:[]

以上就是 Nacos Java SDK 配置管理和服務管理功能的介紹改含,請參考示例源碼學習。

示例源碼

項目:learn-nacos-sdk-java

代碼已上傳至碼云Github上迄汛,歡迎下載學習

歡迎工作一到五年的Java工程師朋友們加入Java架構(gòu)開發(fā): 957734884捍壤,群內(nèi)提供免費的Java架構(gòu)學習資料(里面有高可用、高并發(fā)鞍爱、高性能及分布式鹃觉、Jvm性能調(diào)優(yōu)、Spring源碼睹逃,MyBatis盗扇,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構(gòu)資料)合理利用自己每一分每一秒的時間來學習提升自己祷肯,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕疗隶,使勁拼佑笋,給未來的自己一個交代!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斑鼻,一起剝皮案震驚了整個濱河市蒋纬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坚弱,老刑警劉巖颠锉,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異史汗,居然都是意外死亡琼掠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門停撞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓷蛙,“玉大人,你說我怎么就攤上這事戈毒〖桠” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵埋市,是天一觀的道長冠桃。 經(jīng)常有香客問我,道長道宅,這世上最難降的妖魔是什么食听? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮污茵,結(jié)果婚禮上樱报,老公的妹妹穿的比我還像新娘。我一直安慰自己泞当,他們只是感情好迹蛤,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著襟士,像睡著了一般盗飒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陋桂,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天逆趣,我揣著相機與錄音,去河邊找鬼章喉。 笑死汗贫,一個胖子當著我的面吹牛身坐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播落包,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼部蛇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咐蝇?” 一聲冷哼從身側(cè)響起汛闸,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤侈净,失蹤者是張志新(化名)和其女友劉穎黍氮,沒想到半個月后晕鹊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡旭寿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年警绩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盅称。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡肩祥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缩膝,到底是詐尸還是另有隱情混狠,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布疾层,位于F島的核電站将饺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏痛黎。R本人自食惡果不足惜予弧,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望舅逸。 院中可真熱鬧桌肴,春花似錦皇筛、人聲如沸琉历。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旗笔。三九已至,卻和暖如春拄踪,著一層夾襖步出監(jiān)牢的瞬間蝇恶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工惶桐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撮弧,地道東北人潘懊。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像贿衍,于是被迫代替她去往敵國和親授舟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容