【Spring Cloud Alibaba】Nacos 分布式配置

一、Nacos 分布式配置

1、Nacos概念

Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。

Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象,在特殊的 bootstrap 阶段,配置被加载到 Spring 环境中。当应用程序通过部署管道从开发到测试再到生产时,您可以管理这些环境之间的配置,并确保应用程序具有迁移时需要运行的所有内容。Nacos 的获取和启动方式可以参考 Nacos 官网。

2、Nacos安装

  • Nacos官网文档:https://nacos.io/zh-cn/docs/quick-start.html
  • 下载Nacos:https://github.com/alibaba/nacos/releases/tag/1.3.2(推荐下载1.3.2的版本)

下载之后修改bin/startup.cmd,找到MODE,修改模式从集群修改为单击模式

set MODE="cluster"

修改为

set MODE="standalone"

双击startup.cmd则启动Nacos,直接访问提示的地址,默认账号密码都是nacos

在这里插入图片描述
我这里的访问地址就是:http://192.168.10.3:8848/nacos/index.html
在这里插入图片描述

二、Nacos实战

1、搭建项目

项目名字设置为:spring-cloud-alibaba-learn,后面需要用到配置

使用官网提供的脚手架(https://start.aliyun.com/bootstrap.html),选择以下几个组件:

  • Nacos Config
  • Spring Web
  • Spring Boot Actuator
    在这里插入图片描述

2、配置Nacos

在Nacos的命名空间增加一个空间配置:sandbox-configuration
并且新增配置,配置的DataID为:spring-cloud-alibaba-learn.properties

在这里插入图片描述
然后编辑该配置,增加两个属性

在这里插入图片描述

3、项目配置

修改bootstrap.properties文件

# 应用名称
spring.application.name=spring-cloud-alibaba-learn

# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=localhost:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
spring.cloud.nacos.config.namespace=sandbox-configuration
spring.cloud.nacos.config.file-extension=properties

4、读取配置属性

package cn.tellsea;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.PostConstruct;

/**
 * @author Tellsea
 * @date 2021/12/17
 */
@SpringBootApplication
public class SpringCloudAlibabaLearnApplication {

    @Value("${user.name}")
    private String userName;
    @Value("${user.age}")
    private int userAge;

    @PostConstruct
    public void init() {
        System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudAlibabaLearnApplication.class, args);
    }

}

控制台输出以下信息,则表示配置完成了

[init] user name : Tellsea , age : 22

5、实现 Bean @Value 属性动态刷新

修改上一节的启动类,增加@RestController、@RefreshScope注解,并增加一个访问接口

package cn.tellsea;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

/**
 * @author Tellsea
 * @date 2021/12/17
 */
@SpringBootApplication
@RestController
@RefreshScope
public class SpringCloudAlibabaLearnApplication {

    @Value("${user.name}")
    private String userName;
    @Value("${user.age}")
    private int userAge;

    @PostConstruct
    public void init() {
        System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
    }

    @RequestMapping("/user")
    public String user() {
        return String.format("[HTTP] user name : %s , age : %d", userName, userAge);
    }

    @PreDestroy
    public void destroy() {
    	// 这里可以观察到,修改了配置之后,调用了销毁的方法
        System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
    }
  
    public static void main(String[] args) {
        SpringApplication.run(SpringCloudAlibabaLearnApplication.class, args);
    }

}

我们可以看到控制台一样你的输出信息,使用浏览器访问接口http://localhost:8080/user,同样的输出相同的配置

然后我们修改nacos的配置,将user.age=20,修改为user.age=99,然后再请求user接口,查看配置信息,已经是修改后的配置参数了。这里需要注意一点,这种方式刷新Bean,是通过销毁Bean重新初始化的方式,来实现属性值的修改

6、实现@ConfigurationProperties Bean 属性动态刷新

创建一个User的实体类

package cn.tellsea.nacosconfig;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;

/**
 *
 * @author Tellsea
 * @date 2021/12/20
 */
@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

修改启动类的配置

package cn.tellsea;

import cn.tellsea.nacosconfig.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * @author Tellsea
 * @date 2021/12/17
 */
@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class SpringCloudAlibabaLearnApplication {

    @Value("${user.name}")
    private String userName;
    @Value("${user.age}")
    private int userAge;

    @Autowired
    private User user;

    @PostConstruct
    public void init() {
        System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
    }

    @RequestMapping("/user")
    public String user() {
        return String.format("[HTTP] user name : %s , age : %d", userName, userAge);
    }

    @RequestMapping("/user2")
    public String user2() {
        return "[HTTP] " + user;
    }

    @PreDestroy
    public void destroy() {
        System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
    }


    public static void main(String[] args) {
        SpringApplication.run(SpringCloudAlibabaLearnApplication.class, args);
    }

}

然后将nacos的配置的参数修改了,再访问user2的接口,一样的拿到了修改之后的Bean

[HTTP] User{name='Tellsea', age=99}

7、监听实现 Bean 属性动态刷新

package cn.tellsea;

import cn.tellsea.nacosconfig.User;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.AbstractListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;

/**
 * @author Tellsea
 * @date 2021/12/17
 */
@SpringBootApplication
@RestController
@RefreshScope
@EnableConfigurationProperties(User.class)
public class SpringCloudAlibabaLearnApplication {

    @Autowired
    private User user;
    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Bean
    public ApplicationRunner runner() {
        return args -> {
            String dataId = "spring-cloud-alibaba-learn.properties";
            String group = "DEFAULT_GROUP";
            nacosConfigManager.getConfigService().addListener(dataId, group, new
                    AbstractListener() {
                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            System.out.println("[Listener] " + configInfo);
                            System.out.println("[Before User] " + user);
                            Properties properties = new Properties();
                            try {
                                properties.load(new StringReader(configInfo));
                                String name = properties.getProperty("user.name");
                                int age = Integer.valueOf(properties.getProperty("user.age"));
                                user.setName(name);
                                user.setAge(age);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            System.out.println("[After User] " + user);
                        }
                    });
        };
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudAlibabaLearnApplication.class, args);
    }

}

观察日志输出结果

user.age=22, type=properties
[Listener] user.name=Tellsea
user.age=22
[Before User] User{name='Tellsea', age=99}
[After User] User{name='Tellsea', age=22}

8、Nacos提供了断点监控

配置文件中有以下断点监控信息

# Actuator Web 访问端口
management.server.port=8081
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

访问http://127.0.0.1:8081/actuator,查看actuator所有监控点
在这里插入图片描述访问http://127.0.0.1:8081/actuator/nacos-config,查看actuator所有监控点
在这里插入图片描述

微信公众号

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tellsea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值