Nacos2.1.1配置中心详解

Nacos除了可以做注册中心,也可以做统一配置管理(配置中心)。

当微服务部署的实例越来越多,达到数十、数百时。

逐个修改微服务配置非但工作量巨大,而且很容易出错。

Nacos就提供了一种统一配置管理方案,可以集中管理所有实例的配置。

我们可以把经常需要变更的配置,交由Nacos管理。

nacos配置中心配置的redis不生效 nacos 配置中心_spring cloud

Nacos一方面可以将配置集中管理,另一方可以在配置变更时,及时通知微服务,实现配置的热更新。

一、在Nacos中添加配置文件

nacos配置中心配置的redis不生效 nacos 配置中心_linux_02

进入Nacos控制台的配置列表中,点击右上角的+号开始添加配置。

nacos配置中心配置的redis不生效 nacos 配置中心_linux_03

目前,Springboot中能识别的配置格式只支持YAMLProperties两个格式。

注意:

项目的核心配置,需要热更新的配置才有放到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

nacos配置中心配置的redis不生效 nacos 配置中心_服务器_04

发现成功读取到了配置文件中的数据。

3)修改admin的pwd为99

nacos配置中心配置的redis不生效 nacos 配置中心_spring boot_05

进入编辑页面,修改完成后,记得点击发布才会生效。

4)此时我们并没有重启服务器,再去去访问刚才的接口

nacos配置中心配置的redis不生效 nacos 配置中心_服务器_06

依旧可以访问到。

但是有时候经常变化的配置项可能比较多。这时候可以使用下面的方式来读取变化的配置。

方式二、使用@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

nacos配置中心配置的redis不生效 nacos 配置中心_java_07

4)修改admin的pwd为25

nacos配置中心配置的redis不生效 nacos 配置中心_spring cloud_08

5)此时我们并没有重启服务器,再去去访问刚才的接口

nacos配置中心配置的redis不生效 nacos 配置中心_服务器_09

四、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配置

nacos配置中心配置的redis不生效 nacos 配置中心_spring cloud_10

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

nacos配置中心配置的redis不生效 nacos 配置中心_spring cloud_11

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配置中心配置的redis不生效 nacos 配置中心_java_12

由于并没有在Nacos配置userservice-test.yaml,所以namepwd属性都为空。

但是共享数据依旧是读取到了。

五、配置共享的优先级

Nacos配置、服务本地配置同时出现相同属性时,优先级有高低之分:

nacos配置中心配置的redis不生效 nacos 配置中心_服务器_13