Nacos的基本使用之配置管理
1、統一配置管理的基本介紹
- 配置變化頻繁時,需要頻繁的打包部署應用。
- 不同環境的配置需要分開管理(比如測試環境與生產環境)。
- 而在分布式微服務架構中,服務數量劇增,如果還是手動去實現配置信息的修改或數據的遷移等,效率是很低的,而且手動操作配置也極有可能出現錯誤的情況
- 集中管理配置:一個使用微服務架構的應用系統可能會包括成千上萬個微服務,因此集中管理配置是非常有必要的。
- 不同環境不同配置:例如,數據源配置在不同的環境(開發、測試、預發布、生產等)中是不同的。
- 運行期間可動態調整:例如,可根據各個微服務的負載情況,動態調整數據源連接池大小或熔斷閾值,并且在調整配置時不重啟微服務。
- 配置修改后自動更新:如配置內容發生變化,微服務能夠自動更新配置。

1.1、主流配置中心對比
目前市面上用的比較多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等,下面主要對比一下Spring Cloud Config、Apollo和Nacos。

從配置中心角度來看,性能方面Nacos的讀寫性能最高,Apollo次之,Spring Cloud Config依賴Git場景不適合開放的大規模自動化運維API。功能方面Apollo最為完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Config不帶運維管理界面,需要自行開發。Nacos的一大優勢是整合了注冊中心、配置中心功能,部署和操作相比Apollo都要直觀簡單,因此它簡化了架構復雜度,并減輕運維及部署工作。
綜合來看,Nacos的特點和優勢還是比較明顯的。
2、nacos配置管理
2.1、在Nacos中添加配置信息
在 nacos 服務端默認是沒有任何配置的,我們可以在配置列表頁面新增一個配置,如下:

在彈出表單中填寫以下配置信息:
- Data ID:實際上就是配置文件名,可以以 【服務名稱-環境.文件后綴名】格式命名

實際上并不是所有的配置都適合放到配置中心,建議將一些關鍵參數,需要運行時隨時可調整的參數放到 nacos 配置中心,一些比較固定的配置則可以放在項目本身的配置文件當中。
2.2、服務拉取配置
一個服務如果以 nacos 作為配置中心,則會先拉取 nacos 中管理的配置,然后與本地的配置文件比如 application.yml 中的配置合并,最后作為項目的完整配置,啟動項目。
- 沒有nacos管理配置文件的情況下的項目啟動流程:

- 使用nacos管理配置時項目的啟動流程:

項目啟動的時候需要提前知道 nacos 的環境信息,而 application.yml 在讀取 nacos 配置后才會讀取,所以無法把 nacos 的相關信息配置在 application.yml 中,此時我們可以使用 bootstrap.yml文件。bootstrap.ym是一個引導文件,優先級高于application.yml,它會在application.yml之前被讀取。
要想讓服務能夠拉取 nacos 配置中心的配置,可以通過以下步驟:
比如讓 user-service 服務拉取我們在上面的 nacos 配置中心新增的 userservice-dev.yaml 的配置,首先先引入 nacos 配置管理依賴,如下:
<!--nacos配置管理依賴--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
然后,在 user-service 的 resource 目錄下新建一個bootstrap.yaml文件,文件內容如下:
spring: application: name: userservice # 服務名稱 profiles: active: dev #開發環境,這里是dev cloud: nacos: server-addr: localhost:8848 # Nacos地址 config: file-extension: yaml # 文件后綴名
這里會根據 spring.cloud.nacos.server-addr 來得到 nacos 配置中心的地址,再根據 【spring.application.name】-【spring.profiles.active】.【spring.cloud.nacos.config.file-extension】 作為配置的 DATA ID來從配置中心讀取配置,也就是讀取了 userservice-dev.yaml 配置。
以上配置完成后即可從配置中心讀取配置,使用配置的代碼示例如下:
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Value("${pattern.dateformat}")
private String dateformat;
@GetMapping("test01")
public String now(){
return dateformat;
}
}
2.3、多環境配置共享
實際上微服務啟動時,會去 nacos 配置中心讀取多個配置文件,也就是不僅僅會讀取指定的 profile 的配置文件,還會讀取多個環境共享的配置文件。
比如配置如下:
spring: application: name: userservice # 服務名稱 profiles: active: dev #開發環境,這里是dev cloud: nacos: server-addr: localhost:8848 # Nacos地址 config: file-extension: yaml # 文件后綴名
此時會讀取 [spring.application.name]-[spring.profiles.active].yaml(即 userservice-dev.yaml) 和 [spring.application.name].yaml (即 userservice.yaml)配置文件。無論 profile 如何變化,[spring.application.name].yaml 這個文件一定會被讀取,所以如果是多個環境都共享的配置可以寫入這個文件當中。比如上面的 spring.profiles.active = test,userservice.yaml 配置文件也會被讀取。
可以在 nacos 配置中心新建 userservice.yaml 配置,如下:

當 nacos 和項目的本地配置文件中存在相同配置時,優先級如下: 服務名-profile.yaml > 服務名.yaml > 本地配置,如下:

當存在相同配置時,高優先級的配置文件中的配置會覆蓋掉低優先級的配置。
2.4、配置熱更新
默認情況下,修改了 nacos 配置中心的配置,微服務的配置不會隨之更新的,需要重啟微服務才能讀到新配置。
通過 @Value 和通過 @ConfigurationProperties 來讀取配置時,實現熱更新的方式不同。
2.4.1、通過 @Value 讀取配置時實現熱更新
如果是通過 @Value 來讀取配置的,此時只需在使用 @Value 注入的變量所在類上添加注解 @RefreshScope 即可,如下:
@RefreshScope @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @Value("${pattern.dateformat}") private String dateformat; @GetMapping("test01") public String now(){ return dateformat; } }
此時你在 nacos 配置中心修改配置并發布后,可以發現服務能自動接收到一些更新信息,類似下圖,此時也就實現了配置熱更新,此時再訪問微服務的接口,可以看到返回的信息已經發生了改變。

2.4.2、通過 @ConfigurationProperties 讀取配置時實現熱更新
當使用 @ConfigurationProperties 來讀取配置時,微服務讀取配置中心的配置可以自動實現熱更新,無需進行其他操作。
3、nacos 集群搭建
在測試環境下可以以單體模式啟動 nacos ,但是 Nacos 在生產環境下都是部署為集群狀態的。
搭建集群的基本步驟:
- 搭建數據庫,初始化數據庫表結構
- 下載nacos安裝包,修改nacos配置,啟動nacos集群
- 啟動nginx作為反向代理
下面我們搭建一個以 Nginx 作為負載均衡,nacos 有三個節點的集群,三個nacos節點的 ip 都是 127.0.0.1,端口分別為8845、8846、8847。架構圖如下:

3.1、搭建數據庫
Nacos 默認是將數據存儲在內嵌數據庫 Derby 中的,該數據庫不屬于生產可用的數據庫,官方推薦的最佳實踐是使用帶有主從的高可用數據庫集群。
下面我們只以單點的數據庫為例來搭建。首先新建一個 mysql 數據庫,命名為nacos,而后導入下面的SQL:
CREATE TABLE `config_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(255) DEFAULT NULL, `content` longtext NOT NULL COMMENT 'content', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間', `src_user` text COMMENT 'source user', `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', `app_name` varchar(128) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段', `c_desc` varchar(256) DEFAULT NULL, `c_use` varchar(64) DEFAULT NULL, `effect` varchar(64) DEFAULT NULL, `type` varchar(64) DEFAULT NULL, `c_schema` text, PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = config_info_aggr */ /******************************************/ CREATE TABLE `config_info_aggr` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(255) NOT NULL COMMENT 'group_id', `datum_id` varchar(255) NOT NULL COMMENT 'datum_id', `content` longtext NOT NULL COMMENT '內容', `gmt_modified` datetime NOT NULL COMMENT '修改時間', `app_name` varchar(128) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租戶字段'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = config_info_beta */ /******************************************/ CREATE TABLE `config_info_beta` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL COMMENT 'content', `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間', `src_user` text COMMENT 'source user', `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = config_info_tag */ /******************************************/ CREATE TABLE `config_info_tag` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `tag_id` varchar(128) NOT NULL COMMENT 'tag_id', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL COMMENT 'content', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間', `src_user` text COMMENT 'source user', `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = config_tags_relation */ /******************************************/ CREATE TABLE `config_tags_relation` ( `id` bigint(20) NOT NULL COMMENT 'id', `tag_name` varchar(128) NOT NULL COMMENT 'tag_name', `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `nid` bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`nid`), UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`), KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = group_capacity */ /******************************************/ CREATE TABLE `group_capacity` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID', `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整個集群', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用默認值', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位為字節,0表示使用默認值', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數,,0表示使用默認值', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合數據的子配置大小上限,單位為字節,0表示使用默認值', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間', PRIMARY KEY (`id`), UNIQUE KEY `uk_group_id` (`group_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = his_config_info */ /******************************************/ CREATE TABLE `his_config_info` ( `id` bigint(64) unsigned NOT NULL, `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `data_id` varchar(255) NOT NULL, `group_id` varchar(128) NOT NULL, `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL, `md5` varchar(32) DEFAULT NULL, `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `src_user` text, `src_ip` varchar(50) DEFAULT NULL, `op_type` char(10) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶字段', PRIMARY KEY (`nid`), KEY `idx_gmt_create` (`gmt_create`), KEY `idx_gmt_modified` (`gmt_modified`), KEY `idx_did` (`data_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租戶改造'; /******************************************/ /* 數據庫全名 = nacos_config */ /* 表名稱 = tenant_capacity */ /******************************************/ CREATE TABLE `tenant_capacity` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID', `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用默認值', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位為字節,0表示使用默認值', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合數據的子配置大小上限,單位為字節,0表示使用默認值', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間', PRIMARY KEY (`id`), UNIQUE KEY `uk_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租戶容量信息表'; CREATE TABLE `tenant_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `kp` varchar(128) NOT NULL COMMENT 'kp', `tenant_id` varchar(128) default '' COMMENT 'tenant_id', `tenant_name` varchar(128) default '' COMMENT 'tenant_name', `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc', `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source', `gmt_create` bigint(20) NOT NULL COMMENT '創建時間', `gmt_modified` bigint(20) NOT NULL COMMENT '修改時間', PRIMARY KEY (`id`), UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`), KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info'; CREATE TABLE `users` ( `username` varchar(50) NOT NULL PRIMARY KEY, `password` varchar(500) NOT NULL, `enabled` boolean NOT NULL ); CREATE TABLE `roles` ( `username` varchar(50) NOT NULL, `role` varchar(50) NOT NULL, UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE ); CREATE TABLE `permissions` ( `role` varchar(50) NOT NULL, `resource` varchar(255) NOT NULL, `action` varchar(8) NOT NULL, UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE ); INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE); INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
3.2、配置 nacos
下載 nacos 安裝包并解壓后即安裝完成,下面進行 nacos 集群的配置。
進入 nacos 安裝目錄的 conf 目錄下,復制配置文件 cluster.conf.example 并重命名為 cluster.conf,給文件 cluster.conf 添加以下內容:
127.0.0.1:8845 127.0.0.1.8846 127.0.0.1.8847
類似如下:

然后繼續修改 conf/application.properties 文件,在文件內添加以下內容,配置數據庫連接信息,如下:
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC db.user.0=root db.password.0=123456
以此一個 nacos 節點就已經配置完成,只需將 nacos 復制三份,然后分別修改三個文件夾中的application.properties,將 server.port 分別修改為 8845、8846、8847 即可。
分別啟動這三個 nacos 節點即可,直接雙擊 bin/startup.cmd 文件即可啟動,啟動結果如下:

3.3、啟動Nginx作為反向代理
上述步驟中啟動 nacos 集群后,即可啟動一個 Nginx 作為反向代理,nacos 客戶端需要訪問連接 nacos 服務端時,只需訪問 Nginx 的服務即可。
Nginx 配置如下:
upstream nacos-cluster { server 127.0.0.1:8845; server 127.0.0.1:8846; server 127.0.0.1:8847; } server { listen 80; server_name localhost; location /nacos { proxy_pass http://nacos-cluster; } }
訪問 http://localhost/nacos 即可訪問到 nacos 集群,Nginx 會將接收到的請求負載均衡到三個 nacos 節點當中。
比如 nacos 節點需訪問 nacos 集群時,項目配置文件如下:
spring: cloud: nacos: server-addr: localhost:80 # Nacos地址

浙公網安備 33010602011771號