Nacos配置中心搭建及動態(tài)刷新配置及踩坑記錄
近期有用到阿里的開源配置中心及注冊中心nacos,特此記錄并分享一些學習筆記及配置踩坑點。
一、Nacos配置中心介紹
從架構圖上可以知道,Nacos提供了兩種服務,一種是用于服務注冊、發(fā)現的Naming Service,一種是用于配置中心、動態(tài)配置的Config Service,而他們底層均由core模塊來支持。
外層提供OpenAPI供客戶端使用,并提供了User Console、Admin Console方便用戶使用 。

用戶通過管理平臺發(fā)布配置,通過HTTP調用將配置注冊到服務端,服務端將之保存在MySQL等持久化存儲引擎中;用戶通過客戶端SDK訪問服務端的配置,同時建立HTTP的長輪詢監(jiān)聽配置項變更,同時為了減輕服務端壓力和保證容災特性,配置項拉取到客戶端之后會保存一份快照在本地文件中,SDK優(yōu)先讀取本地文件里的配置。
當服務端的配置發(fā)生變更時,客戶端會通過監(jiān)聽機制,拿到變更后的最新配置信息。

簡單來說,Nacos 客戶端是怎么實時獲取到 Nacos 服務端的最新數據的:
Nacos 并不是通過推的方式將服務端最新的配置信息發(fā)送給客戶端的,而是客戶端維護了一個長輪詢的任務,定時去拉取發(fā)生變更的配置信息,然后將最新的數據推送給 Listener 的持有者。
二、配置中心搭建
1.配置中心啟用
首先需要到官網上下載nacos-server,然后將服務跑起來之后。
根據自己的需要,建立幾個命名空間,當然使用默認的public的命名空間也是可以的,如圖所示。

2.創(chuàng)建配置文件
在配置列表中創(chuàng)建配置文件,其中配置文件命名方式需要注意。
在Nacos-Server中新建配置,其中Data ID它的定義規(guī)則是:${prefix}-${spring.profiles.active}.${file-extension}
prefix默認為 spring.application.name 的值,也可以通過配置項 spring.cloud.nacos.config.prefix 來配置。spring.profiles.active即為當前環(huán)境對應的 profile,可以通過配置項 spring.profiles.active 來配置。file-exetension為配置內容的數據格式,可以通過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支持 properties 和 yaml 類型。
注意:當 spring.profiles.active 為空時,對應的連接符 - 也將不存在,dataId 的拼接格式變成 prefix.{prefix}.prefix.{file-extension}
在本文中,我的項目名稱為vaso-core,配置文件使用的是dev環(huán)境,因此我的配置文件如下:

其中的文件內容就是正常的yaml格式的內容填寫就行,這邊就不具體展示了。

3.工程配置
首先我們需要導入nacos-config的依賴(注:我這邊沒有使用nacos的注冊發(fā)現,依舊沿用自身使用的eureka)。
其中依賴版本的對應關系可以在官網中查找。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>其次我們需要在配置文件中進行配置,采用bootstrap.yml文件進行配置,因為springboot會優(yōu)先啟動bootstrap.yml文件中的配置。其中文件內容如下:
bootstrasp.yml:
spring:
application:
name: vaso-core
cloud:
nacos:
# discovery:
# server-addr: xx.xx.xxx.xx:8848
# namespace: 8b387ec4-e60d-4878-baf4-f2246e58a1d6
config:
server-addr: xx.xx.xxx.xx:8848
file-extension: yml
namespace: 8b387ec4-e60d-4878-baf4-f2246e58a1d6
profiles:
active: devnamespace的內容為上文中配置的dev命名空間的id。
最后我們需要引入@refreshscope關鍵字,保證可以實時刷新配置。在controller層或者要刷新的值所在的類上進行注釋就行。

其中我們的demo是如下所示:

三、試驗結果
將工程跑起來,可以看到一開始就已經去配置中心讀取配置了,如圖:

此時將配置中心內容修改,可以看到已經實時刷新了配置。

四、踩坑經歷
其實在正式使用之前也碰到過nacos無法試試實時刷新的問題,打斷點卻發(fā)現實際已經讀取到本地,通過進入spring的源碼中查看,也發(fā)現其實已經可以拿到配置了,但是卻一直無法刷新配置。
最后通過一個禮拜的定位源碼,斷點查詢才發(fā)現一個本質性的問題。欲哭無淚
@RefreshScope與數據源之間存在沖突??!
具體如下:
- 因為項目是多數據源,所以使用的是自定義數據源配置的DataSource,用@Bean注入。
- 在SpringBoot 2.0以上默認使用Hikari連接池,一旦連接池啟動,就無法再修改HikariDataSource,所以刷新配置時連帶數據源一起刷新,于是會報錯。
Caused by: java.lang.IllegalStateException: The configuration of the pool is sealed once started. Use HikariConfigMXBean for runtime changes.
解決方法: 在自定義的DataSource上加入注解@RefreshScope,或者使用spring.scloud.refresh.extra-refreshable配置指定classname列表即可。
查看Hikari的默認配置即可發(fā)現,這個與刷新配置之間是存在沖突的。

因此在數據源配置類中加入注釋,這樣每次刷新配置的時候會重新刷新這個Bean,那么就可以保證不會報錯,這樣的spring的刷新機制就可以順利執(zhí)行下去了。

五、總結
通過這次經歷,我發(fā)現定位問題的過程是一門極高的學問,學會怎么去看源碼,懂原理才能更好的更精準的分析問題所在之處。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
BiConsumer接口中的方法andThen?accept使用詳解
這篇文章主要為大家介紹了BiConsumer接口中的方法andThen?accept使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07

