Nacos 配置中心开发随笔

更改密码

Nacos 开启认证功能后,登录的默认用户名和密码是 nacos / nacos,为了系统安全,建议更改登录密码。

  • 引入依赖
1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
  • 通过 BCryptPasswordEncoder 类生成新的密码,注意盐值是随机的,所以生成的密码每次都可能不一样,请不要担心
1
2
3
4
5
6
7
8
9
10
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordEncoderUtil {

public static void main(String[] args) {
// 每次生成的密码都可能不一样
System.out.println(new BCryptPasswordEncoder().encode("newPassword"));
}

}
  • 更改 Nacos 的 users 表,指定新的密码

  • 若需要更改用户名称(比如 admin),则更改完用户名称之后,还需要往 roles 表中添加用户角色关联记录,如下图所示:

  • 若是添加新的 Nacos 用户,可以参考以下 SQL 语句
1
2
INSERT INTO users (username, password, enabled) VALUES ('administrator', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
INSERT INTO roles (username, role) VALUES ('administrator', 'ROLE_ADMIN');

配置 JVM

配置参数

JVM 参数说明
JVM_XMS=512m-Xms - JVM 启动时分配的堆内存大小
JVM_XMX=512m-Xmx - JVM 运行过程中分配的最大堆内存大小
JVM_XMN=256m-Xmn - JVM 堆内存中新生代的大小

配置方式

  • 第一种方式,启动 Docker 容器时指定 JVM 参数
1
docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m -p 8848:8848 -d nacos/nacos-server:latest
  • 第二种方式,在 Nacos Server 的 Env 配置文件中添加 JVM 参数
1
2
3
4
5
6
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
JVM_XMS=512m
JVM_XMX=512m
JVM_XMN=256m

三种常见配置方案

在以下三种配置方案中,推荐使用 Namespace 配置方案,因为该方案更灵活,同时可以应付日后不断变化的需求。

配置管理概念

对于 Nacos 的配置管理,是通过 Namespace、Group、Data ID 来定位到一个配置集。

nacos-data-model

  • 配置项:配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形式存在。例如经常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

  • 配置集(Data ID):在系统中,一个配置文件通常就是一个配置集,一个配置集可以包含了系统的各种配置信息,例如一个配置集可能包含了数据源、线程池、日志级别等配置项。每个配置集都可以定义一个有意义的名称,就是配置集的 ID,即 Data ID。

  • 配置分组(Group):配置分组是对配置集进行分组,通过一个有意义的字符串(如 Buy 或 Trade )来表示,不同的配置分组下可以有相同的配置集(Data ID)。当在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP。配置分组的常见场景:可用于区分不同的项目或应用,例如:学生管理系统的配置集可以定义一个 Group 为:STUDENT_GROUP。

  • 命名空间(Namespace):命名空间可用于进行不同环境的配置隔离。例如可以隔离开发环境、测试环境和生产环境,因为它们的配置可能各不相同,或者是隔离不同的用户,不同的开发人员使用同一个 Nacos 管理各自的配置,可通过 Namespace 隔离。当在 Nacos 上创建一个配置时,如果未填写命名空间的名称,则命名空间的名称默认为 public。不同的命名空间下,可以存在相同名称的配置分组(Group) 或 配置集。

配置最佳实践

Nacos 抽象定义了 Namespace、Group、Data ID 的概念,具体这几个概念代表什么,取决于把它们看成什么,这里推荐一种用法,如下图:

  • Namespace :代表不同环境,如开发、测试、生产环境
  • Group:代表某项目,如 XX 医疗项目、XX 电商项目、XX 校园项目
  • DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件

nacos-data-model-2

Namespace 与 Group 的其他最佳实践

除了上面介绍的一种最佳实践方法外,还可以为每个微服务创建自己的 namespace 进行隔离,然后利用 group 来区分 Dev、Beta、Prod 等环境。

DataID 配置方案

通过 Nacos 的 DataID 来实现环境区分,即通过指定 spring.application.namespring.profiles.active 来使不同环境下读取不同的配置信息。

  • 在 Nacos 中新建配置(DataID),并使用默认命名空间(PUBLIC)和默认分组(DEFAULT_GROUP

  • 可以为不同的环境(比如开发、测试、生产)新建配置(DataID)

  • application.yml 配置文件中,通过 spring.profiles.active 属性就可以进行多环境下配置文件的读取
1
2
3
4
5
6
7
server:
port: 8080

spring:
profiles:
active: dev # 表示开发环境
# active: test # 表示测试环境
  • bootstrap.yml 配置文件中,添加 Nacos 的配置信息,特别是需要指定 spring.application.name 属性
1
2
3
4
5
6
7
8
9
10
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 作为服务注册中心地址
config:
server-addr: 127.0.0.1:8848 # Nacos 作为配置中心地址
file-extension: yaml # 指定 yaml 格式的配置
  • 完成上面的配置后,Nacos 客户端就会使用 nacos-config-client-dev.yml 这个 DataID 去 Nacos 配置中心获取对应的配置信息

Nacos 中的 DataID 格完整式

  • 在 Nacos 中,DataID 的完整格式是:${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来指定
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来指定
  • spring.profiles.active 即为当前环境对应的 profile。特别注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式会变成 ${prefix}.${file-extension}

Group 配置方案

在上面 DataID 配置方案的基础上,通过 Nacos 的分组(Group)来实现环境区分。

  • 在 Nacos 中新建配置(DataID),同时指定分组(比如 PROD_GROUP),并使用默认命名空间(PUBLIC

  • 可以为不同的环境(比如开发、测试、生产)新建配置(DataID),并指定不同的分组

  • application.yml 配置文件中,通过 spring.profiles.active 属性指定需要激活哪个环境的配置
1
2
3
4
5
6
7
server:
port: 8080

spring:
profiles:
active: prod # 表示生产环境
# active: test # 表示测试环境
  • bootstrap.yml 配置文件中,添加 Nacos 的配置信息,特别是需要指定 spring.application.namespring.cloud.nacos.config.group 属性
1
2
3
4
5
6
7
8
9
10
11
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 作为服务注册中心地址
config:
server-addr: 127.0.0.1:8848 # Nacos 作为配置中心地址
file-extension: yaml # 指定 yaml 格式的配置
group: PROD_GROUP # 指定分组的名称
  • 完成上面的配置后,Nacos 客户端就会使用 PROD_GROUP 分组和 nacos-config-client-prod.yml 这个 DataID 去 Nacos 配置中心获取对应的配置信息

Namespace 配置方案

在上面 Group 配置方案的基础上,通过 Nacos 的命名空间(Namespace)来实现环境区分。

  • 在 Nacos 中创建命名空间(Namespace),用于区分不同的环境

  • 在指定的命名空间(比如 Prod_Namespace)下,新建配置(DataID),同时指定分组(比如 PROD_GROUP

  • 配置完成后的结果如下

  • application.yml 配置文件中,通过 spring.profiles.active 属性指定需要激活哪个环境的配置
1
2
3
4
5
6
7
server:
port: 8080

spring:
profiles:
active: prod # 表示生产环境
# active: test # 表示测试环境
  • bootstrap.yml 配置文件中,添加 Nacos 的配置信息,特别是需要指定 spring.application.namespring.cloud.nacos.config.groupspring.cloud.nacos.config.namespace 属性
1
2
3
4
5
6
7
8
9
10
11
12
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 作为服务注册中心地址
config:
server-addr: 127.0.0.1:8848 # Nacos 作为配置中心地址
file-extension: yaml # 指定 yaml 格式的配置
group: PROD_GROUP # 指定分组的名称
namespace: Prod_Namespace # 指定命名空间的 ID
  • 完成上面的配置后,Nacos 客户端就会使用 Prod_Namespace 命名空间、PROD_GROUP 分组和 nacos-config-client-prod.yml 这个 DataID 去 Nacos 配置中心获取对应的配置信息

不同版本配置方式的区别

  • 从 Spring Boot 的 2.4 版本开始

    • 提供两种配置方式导入外部配置文件,一种是使用 bootstrap.yml 文件,另一种是使用 application.yml 文件(基于 spring.config.import
    • 默认不再支持 bootstrap.yml 文件,若希望支持,需要显式手动引入 spring-cloud-starter-bootstrap 依赖才能使用 bootstrap.yml 文件。
    • 对于 application.yml 文件(基于 spring.config.import)这种配置方式,不需要使用 bootstrap.yml 文件,而是可以在 application.yml 文件中通过 import 语句来指定 Nacos Config 的配置参数。
  • 在 Spring Cloud Alibaba Nacos 的 2021.0.1.0 版本之前

    • 只支持将 Nacos Config 的参数配置在 bootstrap.yml 文件中,并且需要显式手动引入 spring-cloud-starter-bootstrap 依赖。
  • 从 Spring Cloud Alibaba Nacos 的 2021.0.1.0 版本开始

    • 支持将 Nacos Config 的参数配置在 application.yml 文件中(基于 spring.config.import)。这样,即使不使用 bootstrap.yml 文件,也可以在 application.yml 中配置 Nacos Config 的参数。
    • 因为 Spring Cloud 从 2020 版本开始移除了对 bootstrap 的默认支持,改为需要显式引入 spring-cloud-starter-bootstrap 才支持,或者直接在 application.yml 文件中配置。因此,Nacos Config 也相应调整以支持这种配置方式。

旧版本的配置方式

bootstrap.yml 文件中添加 Nacos Config 的配置参数(如下所示),并显式引入 spring-cloud-starter-bootstrap 依赖。

1
2
3
4
5
6
7
8
9
10
11
12
spring:
application:
name: user-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # 配置中心的地址
namespace: 73975db4-5c7f-4fef-9ea9-36492bd59f45 # 命名空间
group: DEV_GROUP # 配置分组
file-extension: yaml # 由于当前环境对应的 profile 为 dev,因此这里完整的 dataId 就是 user-service-dev.yaml

或者加载多个配置(即加载多个自定义 DataID 配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 73975db4-5c7f-4fef-9ea9-36492bd59f45
file-extension: yaml
# 父类配置要放在前面,相同的项会被后面的配置覆盖
extension-configs[0]:
data-id: extension-config-01.yaml
group: DEV_GROUP
refresh: true
extension-configs[1]:
data-id: extension-config-02.yaml
group: DEV_GROUP
refresh: true

新版本的配置方式

application.yml 文件中(基于 spring.config.import)添加 Nacos Config 的配置参数(如下所示),不需要显式引入 spring-cloud-starter-bootstrap 依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
application:
name: user-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
config:
import:
# 父类配置要放在前面,相同的项会被后面的配置覆盖
- nacos:shared-config.yaml # nacos 前缀表示该配置需要从 ‌Nacos 配置中心‌加载
- nacos:${spring.application.name}-${spring.profiles.active}.yaml # nacos 前缀表示该配置需要从 ‌Nacos 配置中心‌加载

或者设置配置项为可选

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
application:
name: user-service
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
config:
import:
# 父类配置要放在前面,相同的项会被后面的配置覆盖
- optional:nacos:shared-config.yaml # optional:nacos 前缀表示即使在 Nacos 配置中心未找到对应的配置文件,应用程序仍会正常启动,不会因缺失配置导致启动失败
- optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # optional:nacos 前缀表示即使在 Nacos 配置中心未找到对应的配置文件,应用程序仍会正常启动,不会因缺失配置导致启动失败

或者设置命名空间和分组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
config:
import:
# 父类配置要放在前面,相同的项会被后面的配置覆盖
- optional:nacos:default.yaml?refresh=true # 默认命名空间和分组:从默认命名空间(public)、分组 DEFAULT_GROUP 加载 default.yaml,并允许动态刷新
- optional:nacos:common.yaml?group=COMMON_GROUP&namespace=ns-002&refresh=true # 公共配置:从命名空间 ns-002、分组 COMMON_GROUP 加载 common.yaml,并允许动态刷新
- optional:nacos:user-service.yaml?group=APP_GROUP&namespace=ns-001&refresh=true # 主配置:从命名空间 ns-001、分组 APP_GROUP 加载 user-service.yaml,并允许动态刷新

optional: 前缀的作用

  • 当配置项添加 optional: 前缀时,表示该配置‌文件允许不存在‌。简而言之,即使在 Nacos 配置中心未找到对应的配置文件,应用程序仍会正常启动,不会因缺失配置而导致启动失败。
  • optional: 前缀适用于非核心配置或公共配置(如公共参数)的加载,可以避免因部分环境未部署特定配置导致服务无法启动。

常见使用问题

Maven 引入不生效

错误日志信息

Spring Cloud 项目引入 Nacos Config 的 Maven 依赖后,使用 @Value 注解无法读取 Nacos 配置中心的内容,抛出的异常信息如下

1
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'common.name' in value "${common.name}"

第一种错误原因

Spring Cloud 无法读取项目中的 bootstrap.yml 配置文件,此时需要额外引入 spring-cloud-starter-bootstrap 依赖来解决

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

第二种错误原因

项目中 bootstrap.yml 配置文件的内容有误,导致 Nacos Config Spring Cloud 无法通过正确的 dataId 去 Nacos 配置中心获取对应的配置信息,正确的配置示例如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8080

spring:
application:
name: seamall-coupon
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 # 配置中心的地址
namespace: 73975db4-5c7f-4fef-9ea9-36492bd59f45 # 命名空间
group: TEST_GROUP # 配置分组
file-extension: yaml # 由于当前环境对应的 profile 为 dev,因此这里完整的 dataId 就是 seamall-coupon-dev.yaml

上述 bootstrap.yml 配置文件对应的 Nacos Config 配置内容如下图所示

上述 bootstrap.yml 配置文件的详细说明如下

bootstrap.yaml 配置文件中,需要配置 spring.application.name,因为它是构成 Nacos Config 配置管理 dataId 字段的一部分。值得一提的是,在 Nacos Config Spring Cloud 中,dataId 的完整格式如下:

1
${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置,目前只支持 propertiesyaml 类型
  • spring.profiles.active 即为当前环境对应的 profile。特别注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式会变成 ${prefix}.${file-extension}

输出忽略空配置的警告信息

版本说明

组件版本
spring-boot2.5.12
spring-cloud2020.0.5
spring-cloud-alibaba2.2.9.RELEASE
Nacos Server2.5.0

配置信息

  • (1) 在 Nacos 配置中心的控制台中,提前添加了 user-application-dev.ymlcommon-dev.yml 这两个配置项。
  • (2) 基于以下 bootstrap.yml 配置文件的内容,在正常情况下,Nacos 客户端会加载 user-application-dev.yml(主配置) 和 common-dev.yml(公共配置)配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spring:
application:
name: user-application
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml
group: DEFAULT_GROUP
# 公共配置
extension-configs[0]:
data-id: common-dev.yml
group: DEFAULT_GROUP
refresh: true

警告日志

Spring Cloud 应用启动后,发现会输出以下警告信息,提示从 user-applicationuser-application.yml 中加载到空的配置内容。这是因为在 Nacos 配置中心的控制台中并没有添加过这两个配置项,Nacos 客户端也不应该额外加载这两个配置项才对。

1
2
3
4
5
6
7
8
9
10
2020-03-12 17:56:19.028  WARN 22960 --- [           main] c.a.c.n.c.NacosPropertySourceBuilder     : Ignore the empty nacos configuration and get it based on dataId[user-application] & group[DEFAULT_GROUP]
2020-03-12 17:56:19.038 WARN 22960 --- [ main] c.a.c.n.c.NacosPropertySourceBuilder : Ignore the empty nacos configuration and get it based on dataId[user-application.yml] & group[DEFAULT_GROUP]
2020-03-12 17:56:19.058 INFO 22960 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-user-application-dev.yml,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-user-application.yml,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-user-application,DEFAULT_GROUP'}, BootstrapPropertySource {name='bootstrapProperties-common-dev.yml,DEFAULT_GROUP'}]
......
2020-03-12 17:56:23.207 INFO 22960 --- [ main] CachingDelegateEncryptablePropertySource : Property Source bootstrapProperties-user-application-dev.yml,DEFAULT_GROUP refreshed
2020-03-12 17:56:23.207 INFO 22960 --- [ main] CachingDelegateEncryptablePropertySource : Property Source bootstrapProperties-user-application.yml,DEFAULT_GROUP refreshed
2020-03-12 17:56:23.207 INFO 22960 --- [ main] CachingDelegateEncryptablePropertySource : Property Source bootstrapProperties-user-application,DEFAULT_GROUP refreshed
2020-03-12 17:56:23.207 INFO 22960 --- [ main] CachingDelegateEncryptablePropertySource : Property Source bootstrapProperties-common-dev.yml,DEFAULT_GROUP refreshed
2020-03-12 17:56:23.208 INFO 22960 --- [ main] CachingDelegateEncryptablePropertySource : Property Source systemProperties refreshed
......

解决方案

  • (1) 首先通过 @value 注解验证 Spring Cloud 应用是否可以可以正常加载 Nacos 配置中心的配置内容。
  • (2) 如果应用无法正常从 Nacos 加载配置内容,请检查 bootstrap.yml 中的 Nacos 配置内容是否正确,尤其是 namespacegroupfile-extension 的配置。
  • (3) 如果应用可以正常从 Nacos 加载配置内容,则上述的警告信息可以忽略。因为较低版本的 Spring Cloud 和 Spring Cloud Alibaba 默认会轮询加载多个配置文件,包括加载不带扩展名和 profile 的配置文件。若条件允许,可以尝试将两者升级到较高的版本。

Nacos 中的 DataID 格完整式

  • 在 Nacos 中,DataID 的完整格式是:${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来指定
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来指定
  • spring.profiles.active 即为当前环境对应的 profile。特别注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式会变成 ${prefix}.${file-extension}

参考资料