当微服务部署的实例越来越多,达到数十、数百时,逐个修改微服务配置就会让人抓狂,而且很容易出错。我们需要一种统一配置管理方案,可以集中管理所有实例的配置。Nacos中也可以进行配置管理,即将配置写到Nacos当中。
点击配置列表的 +
进行配置文件的配置。
配置文件的列表如下所示:
上述的 Data ID
命名是 [服务名称]-[profile].后缀名
,其中的 profile
为开发环境,开发环境有 dev,test,provided
等,表示其生效的阶段,注意,该字段不是命名空间, 然后在配置内容中写上需要配置的内容即可。
注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。
上面我们学习了怎么配置信息,但是,这个配置信息必须要给项目读取到才能发挥作用,那么,springboot的项目中怎么读取到我们写在Nacos中的配置信息呢?
微服务的配置读取一般是如下图所示:
微服务首先读取Nacos配置文件中的配置,再读取application.yml中的配置,然后将两者的配置文件进行合并,这就会产生一个问题,既然application.yml是在Nacos之后读的,那么,微服务是怎么得到的Nacos配置文件的地址的呢?
SpringBoot加载时会有一个叫做 bootstrap.yml
的文件首先加载,其优先级比 application.yml大得多,所以我们可以重写这个文件,在这个文件中读取Nacos的配置文件信息。
但是在springboot 2.4.x版本以后,就已经移除了 bootstrap.yml
的配置,想要使用 bootstrap.yml
文件就必须引入相应的依赖,而且逐个写上配置的方法太过麻烦,这里我们演示一下使用Nacos的注解来读取Nacos中的配置文件。
而且在这一步中,非常重要的就是版本问题,必须保证SpringBoot、SpringCloudAlibaba、SpringCloud、Nacos的版本能够兼容,在这里,我使用的版本如下:
SpringBoot | SpringCloudAlibaba | SpringCloud | Nacos |
---|---|---|---|
2.3.2.RELEASE | 2.2.6.RELEASE | Hoxton.SR9 | 1.4.4 |
我们以在 user-service
中配置为例,假设我们在Nacos配置的信息内容为:
pattern:
dateformat: MM-dd HH:mm:ss:SSS
在user-service服务中,引入nacos注解需要的依赖:
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>nacos-config-spring-boot-starterartifactId>
<version>0.2.5version>
dependency>
首先在启动类上面添加注解 @NacosPropertySource
,写明 dataID
,这里的 dataID
就是在Nacos中写的配置文件的名称,注意,是全部名称,包含后缀名,比如上面我在Nacos中的配置文件名称是 userservice-dev.yaml
,那么这里也写上 dataId = "userservice-dev.yaml"
,示例如下:
@NacosPropertySource(dataId = "userservice-dev.yaml", autoRefreshed = true)
@MapperScan("cn.itcast.user.mapper")
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
第一行即是我们添加的Nacos的注解。
然后,在需要使用到Nacos中配置文件的信息上面添加注解 @NacosValue
读取信息即可,示例如下,
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@NacosValue(value = "${pattern.dateformat}", autoRefreshed = true)
private String dateformat;
@GetMapping("now")
public String now(){
System.out.println(dateformat);
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
}
}
例如上面的示例,注入Nacos配置文件中的 pattern.dateformat
内容,即可获取相对应的配置文件的信息。
至于添加的两个注解 @NacosPropertySource, @NacosValue
都添加了一个 autoRefreshed = true
的字段,那是指定配置信息可以进行热更新的字段,配置了这个属性之后,如果在Nacos中修改配置信息,提交修改后,再刷新一下网页,其能够将修改的信息立刻返回到修改的网页上,而不需要重新启动项目。
比如将上述在Nacos中的配置信息修该为
pattern:
dateformat: yyyy年MM月dd日 HH:mm:ss:SSS
然后提交修改后再刷新一次网页,修改的内容就会马上呈现在网页上。
当然,还有一种获取配置信息的方式就是将配置信息注入到一个写好的类中,使用的注解时 @ConfigurationProperties
,在Nacos中也提供了一个注解 @NacosConfigurationProperties
,其可以实现与 @ConfigurationProperties
相似的作用,但是其注入的配置信息时Nacos中的配置信息,我们仍以上面的例子为例。
创建一个 MyProperty
的类,在类中定义我们指定的日期的格式的字符串,该类的格式如下:
@Data
@NacosConfigurationProperties(dataId = "userservice-dev.yaml", prefix = "pattern", autoRefreshed = true)
@Component
public class MyProperty {
private String dateformat;
}
其中,使用了 @NacosConfigurationProperties
指定了注入的配置信息所在的文件,也就是 dataId
属性,也指定了该信息可以热更新,也就是 autoRefreshed
属性。
使用注入的信息测试如下:
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private MyProperty myProperty;
@GetMapping("now")
public String now(){
System.out.println(myProperty.getDateformat());
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(myProperty.getDateformat()));
}
}
微服务在启动时会从nacos读取多个配置文件:
[spring.application.name]-[spring.profiles.active].yaml
,如 userservice-dev.yaml, userservice-test.yaml
等,[spring.application.name].yaml
,如 userservice.yaml
,如果没有则不进行读取所以,不管环境怎么变,微服务都会对 [spring.application.name].yaml
文件进行读取,故我们可以将在开发过程中不管是 dev,prod
还是 test
都会用到的环境信息放到一个名为 userservice.yaml
的文件中。
注意,注解模式下无法进行多环境共享配置,所以以下演示时我们使用另一种配置方式,在
bootstrap.yml
文件中进行配置,故请先清除Nacos注解再进行以下配置。
例如,我们在Nacos创建一个名为 userservice.yaml
的文件,该文件中的内容如下:
pattern:
envShare: 环境的共享值
在springboot中想要使用 bootstrap
文件,则必须引入如下依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
<version>3.1.3version>
dependency>
然后New一个名为 bootstrap.yml
的文件,其层级与 application.yml
相同,其中配置的内容如下:
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: localhost:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
因为我们需要的是既读取 userservice-dev.yaml
中的内容,又读取 userservice.yaml
中的内容,所以,我们的注入类就不能只有 dateformat
一个属性了,还需要增加一个读取了 userservice.yaml
中的 envShare
属性,即将 MyProperty
类增加一个属性,修改如下:
@Data
@ConfigurationProperties(prefix = "pattern")
@Component
public class MyProperty {
private String dateformat;
private String envShare;
}
对注入的配置信息中的属性进行测试如下,
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private MyProperty myProperty;
@GetMapping("now")
public String now(){
System.out.println(myProperty.getDateformat());
return myProperty.toString();
}
}
打印的内容输出如下
可以看到,我们没有在 userservice-dev.yaml
中写上 envShare
属性,只在 userservice.yaml
中写了 envShare
属性,但还是可以读取到该属性的值,这就证明了多环境共享。
引入了多环境的共享配置后,我们可能起效果的配置文件就达到了三种,一个是当前开发模式下的配置文件,一个是共享配置文件,一个是本地的配置文件,那么这三种的优先级是怎样的呢?
其优先级如上面所示,当前开发模式下的配置文件 > 共享配置文件 > 本地配置文件,所以,如果在这三个文件中出现了一个三个文件中都有的配置信息,那么,起效的肯定是当前开发模式下的配置文件。