Nacos2.1.1配置中心详解
Nacos
除了可以做注册中心,也可以做统一配置管理(配置中心)。
当微服务部署的实例越来越多,达到数十、数百时。
逐个修改微服务配置非但工作量巨大,而且很容易出错。
而Nacos
就提供了一种统一配置管理方案,可以集中管理所有实例的配置。
我们可以把经常需要变更的配置,交由Nacos
管理。
Nacos
一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。
一、在Nacos中添加配置文件
进入Nacos
控制台的配置列表中,点击右上角的+号开始添加配置。
目前,Springboot
中能识别的配置格式只支持YAML
和Properties
两个格式。
注意:
项目的核心配置,需要热更新的配置才有放到Nacos
管理的必要。
基本不会变更的一些配置还是保存在微服务本地比较好。
二、从微服务拉取配置
微服务要拉取Nacos
中管理的配置,并且与本地的application.yml
配置合并,才能完成项目启动。
否则项目启动时就会报错。
但是现在有个问题?
未读取application.yml
,又如何得知nacos
地址呢?
解决方案:
Spring
引入了一种新的配置文件:bootstrap.yaml
文件,会在application.yml
之前被读取。
1)在需要读取Nacos
配置的服务中,引入nacos-config
依赖
<!--nacos配置管理依赖 起步依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2) 创建bootstrap.yaml
(或者bootstrap.yml
)
server:
port: 8081
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
# 服务名称+发环境+文件后缀名 决定了使用哪个Nacos配置
# userservice + dev + yaml 就指向了 userservice-dev.yaml
完成以上两步就完成了拉去指定的Nacos
配置。
三、 配置的热更新
修改Nacos
中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新。
这里的测试承接上面,已经读取了userservice-dev.yaml
这个配置。
方式一、使用@RefreshScope + @Value注解实现配置热更新
1)新建一个AdminController用作测试
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/admin")
@RefreshScope //实现读取nacos配置的热更新,无需重启为服务,就可以实时更新到nacos配置
public class AdminController {
//读取nacos配置的热更新
//方式一:在@Value注入的变量所在类上添加注解@RefreshScope (需要@RefreshScope )
@Value("${admin.name}")
private String name;
@Value("${admin.pwd}")
private String pwd;
@GetMapping("getInfo")
public Map<String, String> now(){
Map<String, String> map = new HashMap<>();
map.put("name", name);
map.put("pwd", pwd);
return map;
}
}
2) 浏览器访问127.0.0.1:8081/admin/getInfo
发现成功读取到了配置文件中的数据。
3)修改admin的pwd为99
进入编辑页面,修改完成后,记得点击发布才会生效。
4)此时我们并没有重启服务器,再去去访问刚才的接口
依旧可以访问到。
但是有时候经常变化的配置项可能比较多。这时候可以使用下面的方式来读取变化的配置。
方式二、使用@ConfigurationProperties注解代替@Value注解。
1)定义一个类Admin
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component //此类交由spring管理
@Data //lombok注解 生成get/set、toString、等实体类犯方法
@ConfigurationProperties(prefix = "admin") //把配置文件中admin下的属性注入到当前类的同名属性上
public class Admin {
private String name;
private String pwd;
}
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2)编写测试controller如下
import cn.itcast.user.pojo.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/admin")
@RefreshScope //实现读取nacos配置的热更新,无需重启为服务,就可以实时更新到nacos配置
public class AdminController {
//读取nacos配置的热更新
@Autowired
private Admin admin;
@GetMapping("getInfo")
public Map<String, Object> now(){
Map<String, Object> map = new HashMap<>();
map.put("admin", admin);
return map;
}
}
3) 浏览器访问127.0.0.1:8081/admin/getInfo
4)修改admin的pwd为25
5)此时我们并没有重启服务器,再去去访问刚才的接口
四、Nacos 配置共享
一个微服务,一般可能会有三种(或者三种以上)配置文件在Nacos
中,比如:
userService-dev.yaml
开发环境配置userService-pro.yaml
生产环境配置userService-test.yaml
测试环境配置
那么对于有些相同的配置,修改的时候,可能需要所有环境下的配置文件都生效。那应该怎么办呢?
解决方案:
微服务启动时,会去Nacos
读取多个配置文件,例如:
[spring.application.name]-[spring.profiles.active].yaml
,例如:userservice-dev.yaml
[spring.application.name].yaml
,例如:userservice.yaml
而[spring.application.name].yaml
不包含环境,因此可以被多个环境共享。
1)新建多环境共享的Nacos配置
2)实体类如下
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component //此类交由spring管理
@Data //lombok注解 生成get/set、toString、等实体类犯方法
@ConfigurationProperties(prefix = "admin") //把配置文件中admin下的属性注入到当前类的同名属性上
public class Admin {
private String name;
private String pwd;
private String SharedValue;
}
3) Controller不变
import cn.itcast.user.pojo.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/admin")
@RefreshScope //实现读取nacos配置的热更新,无需重启为服务,就可以实时更新到nacos配置
public class AdminController {
//读取nacos配置的热更新
@Autowired
private Admin admin;
@GetMapping("getInfo")
public Map<String, Object> now(){
Map<String, Object> map = new HashMap<>();
map.put("admin", admin);
return map;
}
}
4) 此时的bootstrap.yaml
读取的是dev环境的数据
server:
port: 8081
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
# 服务名称+发环境+文件后缀名 决定了使用哪个Nacos配置
# userservice + dev + yaml 就指向了 userservice-dev.yaml
5)浏览器访问127.0.0.1:8081/admin/getInfo
6)修改bootstrap.yaml
,读取test环境的数据
server:
port: 8081
spring:
application:
name: userservice # 服务名称
profiles:
active: test #测试环境,这里是test
cloud:
nacos:
server-addr: 127.0.0.1:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
# 服务名称+发环境+文件后缀名 决定了使用哪个Nacos配置
# userservice + dev + yaml 就指向了 userservice-dev.yaml
7)重启服务,再去访问getInfo接口
由于并没有在Nacos
配置userservice-test.yaml
,所以name
和pwd
属性都为空。
但是共享数据依旧是读取到了。
五、配置共享的优先级
当Nacos
配置、服务本地配置同时出现相同属性时,优先级有高低之分: