一、Nacos配置中心基础
1.配置中心的选型
配置中心进行选型时重点要从产品功能、使用体验、实施过程和性能等方面进行综合考量。
在这里我们使用nacos作为配置中心
2.配置中心的准备
1)引入依赖
当我们在pom.xml引入以下依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
只要引入此依赖,系统会为我们注入一些API对象,基于这些对象可以读取配置中心数据。在其读取配置时,其读取的配置变为bootstrap.yml而不是application.yml。因为在引入此依赖后bootstrap.yml的启动优先级高于application.yml。
2)添加配置中心配置
在bootstrap.yml中添加以下代码
spring:
application:
name: sca-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml # Configure the data format of the content, default to properties
- 1)spring.application.name: 这个是指定服务名称。
- 2)cloud.nacos.表示引入nacos
- a)discovery表示配置服务中心发现地址 server-addr表示地址
- b) config表示配置服务配置中心地址 file-extension: yml配置中心的扩展名
3)创建ProviderLogController对象
此对象创建的路径com.jt.provider.controller
package com.jt.provider.controller;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 基于此controller演示配置中心的作用.
* 在这个controller中我们会基于日志对象
* 进行日志输出测试.
*/
//@Slf4j
@RestController
public class ProviderLogController {
//创建一个日志对象
private static Logger log=
LoggerFactory.getLogger(ProviderLogController.class);
@GetMapping("/provider/log/doLog01")
public String doLog01(){//trace<debug<info<warn<error
System.out.println("==doLog01==");
log.trace("===trace===");
log.debug("===debug===");
log.info("===info====");
log.warn("===warn===");
log.error("===error===");
return "log config test";
}
}
如在log对象所在的类上使用了@Slf4j注解,log不再需要我们手动创建,lombok会帮我们创建
如果没有引入那么就需要以下代码来创建一个日志对象
private static Logger log= LoggerFactory.getLogger(ProviderLogController.class);
1)引入org.slf4j.Logger包 (Java中的日志API规范,基于这个规范有Log4J,Logback等日志库)
创建一个Logger对象 log
2)引入org.slf4j.LoggerFactory包
3)log对象在哪个类中创建,getLogger方法中的就传入哪个类的字节码对象
ps:以后只要Java中使用日志对象,就可以采用上面之中方式创建即可
日志默认info级别的大小:
debug<info<warn<error
具体效果:如果日志级别为debug那么会显示debug,info,warn,error全部日志
如果日志级别为info那么会显示info,warn,error日志的内容
如果日志基本为error那么只会显示error的内容
4)打开nacos配置中心,新建配置,如图所示:
小结1:
配置中心的作用:在配置中心nacos来修改配置文件,且在不需要要重启服务的情况下,修改的部分能够直接生效。
注解解读
@RefreshScope注解的应用
测试例子
在ProviderLogController对象添加代码
public ProviderLogController(){
System.out.println("===ProviderLogController()===");
}
@Value("${logging.level.com.jt:info}")
private String logLevel;//构建对象时属性进行初始化
//http://localhost:8081/provider/log/doLog02
@GetMapping("/provider/log/doLog02")
public String doLog02(){
return "log level is "+logLevel;
}
代码解读
1)创建一个方法来进行测试
@GetMapping("/provider/log/doLog02") public String doLog02(){ return "log level is "+logLevel; }
2)申明logLevel对象
@Value("${logging.level.com.jt:info}") private String logLevel;//构建对象时属性进行初始化
使用@Value注解获取到日志的属性值,要获取值必须在()中添加属性值得的地址所以应该完整的应该写@Value("${logging.level.com.jt}"。
当此地址属性读取不到时,我们可以写为@Value("${logging.level.com.jt:info}")这样在logging.level.com.jt地址读取不到属性时,直接默认为info
3)写一个构造方法, 构建对象时默认调用无参构造函数
public ProviderLogController(){ System.out.println("===ProviderLogController()==="); }
显示结果:
在启动服务时显示了结果无参构造方法的输出,初始化了数据,然后通过@Value注解获得了此时的logging.level.com.jt属性,并且logLevel也获得对应的值。
但是在修改配置中心的logging.level.com.jt属性后,无参构造不被调用,因此logLevel也不会在发生变化,仍然为修改前的值。
结论:
虽然logLevel不发生变化但是doLog01()方法中输出显示日志文件级别已经变成修改后的文件,这个可以说明不仅有系统内部对配置变化的感知还有外部系统对配置的感知。
@RefreshScope的作用
当我们要让系统内部和系统外部同时要动态变化时,可以用注解@RefreshScope解决
@RefreshScope的作用:描述对象 当这个对象内部的属性值对应的配置中心的值发生变化时,在访问它时会重新构建一个这个类型的对象,然后重新对属性进行初始化。
1)在ProviderLogController类的上面添加一个@RefreshScope注解
@RefreshScope
@RestController
public class ProviderLogController{
//.....
}
2)运行http://localhost:8081/provider/log/doLog02
3)结果:
修改配置中心的logging.level.com.jt属性后,logLevel的值也变化为修改后的数据。
二、Nacos配置管理模型
概述
Nacos 配置管理模型由三部分构成,如图所示:
1) namespace:命名空间,对不同的环境进行隔离,比如隔离开发环境和生产环境
2)Group:分组,将若干个服务或者是若干个配置归集为一组
3)Service/DataId:某一个服务或者配置集,一般对应一个配置文件
命名空间(namespace)
我们默认的命名空间为public
创建新的开发环境
1)创建新命名空间,如图所示:
命名空间Id不写则会默认自己创建,下图可知默认创建的名字为5c27.....
2)命名空间成功创建以后,会在如下列表进行呈现。
3)在指定命名空间下添加配置,也可以直接取配置列表中克隆,例如:
4)克隆成功以后,我们会发现在指定的命名空间中有了我们克隆的配置,如图所示:
5)此时我们修改dev命名空间中Data Id的sca-provider配置,如图所示:
6)修改项目module中的配置文件bootstrap.yml,添加如下配置,关键代码如下:
spring:
cloud:
nacos:
config:
namespace: #你所有取的namespace的名字
7)结果
其中,namespace后面的字符串为命名空间的id,可直接从命名空间列表中进行拷贝.然后重启服务,继续刷新http://localhost:8081/provider/log/doLog02地址。检测输出,看看输出的内容是什么,是否为dev命名空间下配置的内容
知识点:
配置中心可以有多个命名空间,一个命名空间有多个分组(Group)每个分组下面,可以有多个DataId,虽然不同分组的DataId可以相同,但是同一个分组下面不能出现相同的DatatId。
分组设计及实现
当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于服务做分组配置,例如,一个服务在不同时间节点(节假日,活动等)切换不同的配置,可以在新建配置时指定分组名称:
1)新建
新建一个分组(Group)命名为:DEFAUL_GROUP_51
新建DataId sca-provider.yml
配置内容里填写useLocalCache:true
ps:这里的useLocalCache为自己定义的配置值,表示是否使用本地缓存
2)配置发布以后,修改boostrap.yml配置类,在其内部指定我们刚刚创建的分组,代码如下:
server:
port: 8081
spring:
application:
name: sca-provider
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
group: DEFAULT_GROUP_51
file-extension: yml
namespace: 7da4aa75-f64c-43c6-b101-9d77ad96f1c0
3)在指定的Controller类中添加属性和方法用于获取和输出DEFAULT_GROUP_51中的useLocalCache的值,代码如下:
package com.jt.provider.controller;
@RefreshScope
@RestController
public class ProviderCacheController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/provider/cache01")
public String doUseLocalCache01(){
return "useLocalCache'value is "+useLocalCache;
}
}
然后重启服务,进行访问测试,检测内容输出。
三、共享配置设计及读取
当同一个namespace的多个配置文件中都有相同配置时,可以对这些配置进行提取,然后存储到nacos配置中心的一个或多个指定配置文件,哪个微服务需要,就在服务的配置中设置读取即可。例如:
1)在nacos中创建一个共享配置文件,例如
在一个分组(Group):DEFAUL_GROUP中新建DataId:app-public.yml
格式配置为yaml
配置内容里填写app.secret:AAAAA
其中,这里的secret可以理解为一个密钥。
2)在指定的微服务配置文件(bootstrap.yml)中设置对共享配置文件的读取,例如
spring:
application:
name: sca-provider
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: 83ed55a5-1dd9-4b84-a5fe-a734e4a6ec6d
# group: DEFAULT_GROUP
file-extension: yml
shared-configs[0]:
data-id: app-public.yml
refresh: true
a) namespace : 自己命名 # 命名空间
b)group: DEFAULT_GROUP # 分组名
c)file-extension: yml # 配置中心文件扩展名
b)shared-configs[0]:# 共享配置
data-id: app-public.yml #文件名
refresh: true #默认false,共享配置更新,引用此配置的地方是否要更新
ps:不能把namespace写在shared-configs中
3)在指定的Controller类中读取和应用共享配置即可,例如:
package com.jt.provider.controller;
@RefreshScope
@RestController
public class ProviderSecretController {
@Value("${app.secret:123456}")
private String secret;
@GetMapping("/provider/secret")
public String doGetSecret(){
//return String.format()
return "The Secret is "+secret;
}
}
4)启动服务,然后打开浏览器进行访问测试
访问成功Controller类中读取到了此配置的内容
且refresh为false时,无论配置是否修改 则读取的配置不会在进行一个更新