Nacos不仅具有注册中心的功能,还具有注册管理的功能
一、Nacos实现配置管理
可以使用统一配置管理,来配置更改热更新,整体结构如下
前提条件: 你已经把上面的 '实用篇-Nacos注册中心' 学完了,并且项目也跟着做了。我们下面会使用到上面的项目。具体操作如下
第一步: 浏览器访问http://localhost:8848/nacos/index.html,用户名和密码都是nacos,登录进管理面板
第二步: 在管理面板添加配置
注意上图中配置内容中的不是把项目中application.yml所有配置都写过来,而是只写有热更新需求的配置,配置完点击发布即可
上面我们只是把这个配置文件做出来了,至于微服务如何去读取我们做出来了的配置文件,下面会学习
二、Nacos微服务配置拉取
在微服务去获取上面Nacos做出来了的配置文件,步骤如下图
具体步骤如下
第一步: 在UserService微服务的pom.xml,添加如下,引入Nacos的配置管理客户端依赖
<!--读取nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
第二步: 在UserService微服务中的resources目录新建File,文件名是bootstrap.yml。注意bootstrap.yml文件是引导文件,优先级高于application.yml文件。添加如下
spring:
application:
# 服务名称
name: UserService
profiles:
# 环境,dev表示开发环境
active: dev
cloud:
nacos:
# nacos的服务地址
server-addr: localhost:8848
config:
# 我们创建的dev命名空间
namespace: d8ec5ecb-2268-4551-ac2d-f08953292b28
# 文件后缀名
file-extension: yaml
第三步: 把application.yml中删掉如下。跟刚刚的bootstrap.yml重复的代码给删掉,也就是如果代码重复的话只保留bootstrap.yml的代码,操作后application.yml文件如下
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
username: root
password:
driver-class-name: com.mysql.jdbc.Driver
# # 跨集群部署
# discovery:
# cluster-name: SH # 自定义集群的名字
mybatis:
type-aliases-package: cn.itcast.user.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
cn.itcast: debug
pattern:
dateformat: MM-dd HH:mm:ss:SSS
#eureka:
# client:
# service-url:
# # eureka的服务地址。如果有多个的话,逗号隔开。也就是把当前这个user-service微服务注册给哪个Eureka
# defaultZone: http://localhost:8686/eureka
第四步: 验证UserService微服务有没有拉取到配置文件。在UserService微服务的web目录的UserController类里面添加如下
//验证配置拉取是否成功,我们直接在这里去读取拉取过来的配置,如果能拉取就表示验证成功
@Value("${pattern.dateformat}")
private String dataformat;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dataformat));
}
第五步: 测试。重新启动UserService微服务,浏览器访问 http://localhost:8081/user/now
上面我们已经实现了读取Nacos上写的配置文件,但是存在一个问题,如果配置文件修改了那必须重启服务才能生效修改后的配置。
能不能让Nacos中写的配置文件实现热更新呢,也就是实时生效,不需要重新启动微服务
三、配置热更新
方式①
Nacos中的配置文件变更后,微服务无需重启就可以感知,实现的方式有两种,如下:
第一种: 在@Value注入的变量所在类(也就是我们上面的UserController类)上添加注解@RefreshScope
第一种的具体操作如下
第一步: 在UserService微服务的web目录的UserController类添加如下,并重新启动UserService微服务的实例
第二步: 修改浏览器上写的配置文件,修改为如下,点击发布
pattern:
dateformat: yyyy.MM.dd HH:mm:ss
第三步: 查看是否实现热更新,浏览器访问,可以看到,直接访问的是更新后的配置,而无需重启服务
方式②
第二种配置热更新方式是: 使用@ConfigurationProperties注解
第一步:在user-service项目下创建config/PatternProperties类
package cn.itcast.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "pattern") //配置属性前缀名
public class PatternProperties {
private String dateformat;
}
第二步: 在user-service微服务项目的web目录的UserController类修改为如下
package cn.itcast.user.web;
import cn.itcast.user.config.PatternProperties;
import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
//@RefreshScope
public class UserController {
@Autowired
private UserService userService;
@Autowired
private PatternProperties patternProperties;
/**
* 路径: /user/110
*
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
//验证配置拉取是否成功,我们直接在这里去读取拉取过来的配置,如果能拉取就表示验证成功
// @Value("${pattern.dateformat}")
// private String dataformat;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
}
}
第三步: 测试。重新启动UserService微服务,先访问一下能不能拿到配置文件里面的数据
修改nacos配置如下
点击发布,不重启项目,直接访问
总结
两种微服务热更新的方式,总结
- 第一种: 通过@Value注解注入,结合@RefreshScope注解来刷新
- 第二种: 通过@ConfigurationProperties注解注入,实现刷新
注意事项:
- 不是所有的配置都适合放到配置中心(nacos不仅是注册中心,还是配置中心),维护起来比较困难
- 建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置
四、多环境配置共享
场景: 有一个配置属性,该配置属性在开发、生产、测试等环境下的值是一样的,我们就不用在每个配置文件里面都写一份,而是使用多环境配置共享。简单说就是把配置写在一个地方,不管环境怎么变,配置都能被加载。下面将进入学习
微服务启动时会从nacos里自动读取两种配置文件。如下
注意除了这两种nacos '线上配置文件' ,微服务还有自身的application.yml配置文件(叫 '本地配置文件' )。所以微服务启动时会自动读取这三种
(1)、当微服务启动时,会根据环境加载对应的配置文件
- [spring.application.name]-[spring.profiles.active].yaml,例如: userservice-dev.yaml。格式: 服务名-环境.yaml
(2)、当微服务启动时,必然会加载这类的配置文件。我们可以把多环境共享配置写入这个文件
- [spring.application.name].yaml,例如: userservice.yaml。格式: 服务名.yaml
(3)、微服务自身的application.yml配置文件(叫 '本地配置文件' )
案例如下
第一步: 在浏览器的nacos管理界面添加一个新的配置文件,作为我们下面要学的多环境配置文件
第二步: 读取我们刚写的配置文件(共享配置文件)的属性。把user-service微服务项目的config目录的PatternProperties类,修改为如下
package cn.itcast.user.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "pattern") //配置属性前缀名
public class PatternProperties {
private String dateformat;
private String envSharedValue;
}
第三步: 为方便直观的展示是否读取到 '共享配置文件' 的配置,我们在user-service微服务项目的web目录的UserController类,修改为如下
package cn.itcast.user.web;
import cn.itcast.user.config.PatternProperties;
import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Slf4j
@RestController
@RequestMapping("/user")
//@RefreshScope
public class UserController {
@Autowired
private UserService userService;
@Autowired
private PatternProperties patternProperties;
/**
* 路径: /user/110
*
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
//验证配置拉取是否成功,我们直接在这里去读取拉取过来的配置,如果能拉取就表示验证成功
// @Value("${pattern.dateformat}")
// private String dataformat;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
}
@GetMapping("prop")
public PatternProperties properties(){
return patternProperties;
}
}
第四步: 为方便直观的展示是否读取到 '共享配置文件' 的配置,我们在user-service微服务项目的8082端口改成test
第五步: 启动8081和8082端口
访问8081端口
访问8081端口
思考:
对于8081和8082端口的dev环境的实例来说,是能够同时读取到本地配置文件、当前环境的配置文件、共享配置文件。后两者配置文件我们都是在浏览器配置的,其实本身项目代码里有一个配置文件(application.yml)。当本身的yml配置文件跟这俩浏览器配置的冲突了,以谁为准呢
1、本地的application.yml配置文件跟当前环境的配置文件冲突时,当前环境的配置文件(UserService-dev.yaml)优先级更高
2、本地的application.yml配置文件跟共享配置文件冲突时,共享配置文件(UserService.yaml)优先级更高
3、当前环境的配置文件跟共享配置文件冲突时,当前环境的配置文件(UserService-dev.yaml)优先级更高
优先级排序。profile表示环境的意思,可以是dev开发环境,也可以是test测试环境。排序如下:
服务名-profile.yaml > 服务名.yaml > 本地配置
五、Nacos集群搭建
① 搭建MySQL集群并初始化数据库表
②下载解压nacos
③修改集群配置(节点信息)、数据库配置
④分别启动多个nacos节点
⑤nginx反向代理