文章目录
一、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所有监控点