微服务3——服务的配置(Nacos服务配置中心 )

在这里插入图片描述

 

一、什么是配置中心(面试分析)——概念+功能

存储项目配置信息的一个服务,将一些可能经常变化的数据写到配置中心里,集中管理配置信息,动态发布配置信息;当某个配置项发生变更时,不停机就可以动态刷新服务内部的配置项

二、市场上有哪些主流的配置中心?(面试分析)

市场上主流配置中心有Apollo(携程开源)--携程开源的阿波罗,nacos(阿里开源),Spring Cloud Config(Spring Cloud 全家桶成员)。

面试可能问的

什么是配置中心?(存储项目配置信息的一个服务,这个服务可以实现配置的动态发布和更新)
为什么要使用配置中心?(集中管理配置信息,动态发布配置信息,服务自动感知配置)
市场上有哪些主流的配置中心?(Apollo,nacos,……)
配置中心一般都会配置什么内容?(可能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则)
什么信息一般不会写到配置中心?(服务端口,服务名,服务的注册地址,配置中心地址)
项目中为什么要定义bootstrap.yml文件?(此文件被读取的优先级比较高,可以在服务启动时读取配置中心的数据)
Nacos配置中心宕机了,我们的服务还可以读取到配置信息吗?(可以从服务的本地内存读取)
微服务应用中客户端如何感知配置中心数据变化?(1.4.x版本的nacos客户端会基于长轮询机制从nacos获取配置信息)
服务启动后没有从配置中心获取我们的配置数据是什么原因?(依赖,bootstrap.yml,配置单词,格式,配置模型)
你项目中使用的日志规范是什么?(SLF4J~门面模式)
你了解项目中的日志级别吗?(debug,info,warn,error可以基于日志级别控制日志的输出)
Nacos配置管理模型的背景?(环境不同配置不同)
Nacos配置中的管理模型是怎样的?(namespace>group>service/data-id)
Nacos客户端(微服务)是否可以读取共享配置?(可以)

配置中心一般都会配置什么内容?(可能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则)
什么信息一般不会写到配置中心?(服务端口,服务名,服务的注册地址,配置中心)
项目中为什么要定义bootstrap.yml文件?(此文件被读取的优先级比较高,可以在服务启动时读取配置中心的数据)
Nacos配置中心宕机了,我们的服务还可以读取到配置信息吗?(可以从内存,客户端获取了配置中心的配置信息以后,会将配置信息在本地内存中存储一份.)
微服务应用中我们的客户端如何获取配置中心的信息?(我们的服务一般首先会从内存读取配置信息,同时我们的微服务还可以定时向nacos配置中心发请求拉取(pull)更新的配置信息)
微服务应用中客户端如何感知配置中心数据变化?(1.4.x版本的nacos客户端会基于长轮询机制从nacos获取配置信息,所谓的长轮询就是没有配置更新时,会在nacos服务端的队列进行等待.)
服务启动后没有从配置中心获取我们的配置数据是什么原因?(依赖,配置文件名字bootstrap.yml,配置中心的dataId名字是否正确,分组是否正确,配置的名字是否正确,缩进关系是否正确,假如是动态发布,类上是否有@RefreshScope注解)
你项目中使用的日志规范是什么?(SLF4J)
你了解项目中的日志级别吗?(debug,info,error,…,可以基于日志级别控制日志的输出)

为什么需要配置中心?(动态管理发布配置,无需重启服务,更好保证服务的可用)
配置中一般要配置什么内容?(经常变化的配置数据-日志级别,线程池、连接池、…)
市面上有哪些主流配置中心?(Nacos,….)
配置中心选型时要重点考虑哪些因素?(市场活跃度、稳定性、性能、易用)
Nacos客户端(微服务业务)如何动态感知配置中心数据变化的?(nacos2.0之前nacos客户端采用长轮询机制每隔30秒拉取nacos配置信息.)
Nacos配置管理模型是怎样的?(命名空间-namespace,分组-group,服务实例-dataId)


*************************************************************************

 此处以provider服务 配置日志级别 为例 演示(所有的操作都是在sca-provider里完成的,与其他sca-consumer等无关)

1-1、Nacos服务 配置(日志级别在控制台打印的 配置)——系统内部对配置变化的感知

1、原理:当配置了日志级别后,只能在控制台打印出我们调整到的日志级别以及比它高的日志级别

我们调整日志级别,那么只有我们调整到的日志级别以及比它高的才会输出               输出

                 error                                                                                                              error

                debug                                                                                                  debug info warn error

日志级别的配置-日志级别 trace<debug<info<warn<error


2、实际操作:

1)第一步:创建ProviderLogController对象

@Slf4j   //注意,只要下面用到log输出日志级别或其他东西,都要用这个注解生成log对象

package com.jt.provider.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j   //注意,只要下面用到log输出日志级别或其他东西,都要用这个注解生成log对象
@RestController
public class ProviderLogController {
     /* org.slf4j.Logger 是一组日志API规范,
     * 作者推出这组规范最主要的目的是 希望别人都要按他的标准来写日志
     * 只要使用日志,都使用下面的两个:
     * import org.slf4j.Logger;————Logger 导的包  不能错了
     * import org.slf4j.LoggerFactory;————LoggerFactory 导的包  不能错了*/

    //加static:我们希望在类加载的时候就创建出来  这个接口对象
    //加final:我们不希望再对其进行赋值
    /*写法一:类名.class——假如 这个接口对象 是定义在某个类(此处就是在ProviderLogController类)里的,推荐用这个*/
    private static final Logger log=
            LoggerFactory.getLogger(ProviderLogController.class);//类名.class——表名希望输出哪个类的日志,此处是ProviderLogController类的日志
    /*写法二:类的全路径
        注释:类的全路径复制:双击选中类,右键-Copy Reference即可
     private static final Logger log=
            LoggerFactory.getLogger("com.jt.provider.controller.ProviderLogController");//类的全路径——表名希望输出哪个类的日志,此处是ProviderLogController类的日志*/

    //在控制台输出日志
    @GetMapping("/provider/log/doLog01")
    public String doLog01(){//日志级别 trace<debug<info<warn<error
        //输出各种日志级别
        log.trace("===trace==");
        log.debug("===debug==");
        log.info("===info==");
        log.warn("===warn==");
        log.error("===error==");
        return "test log level";
    }
}

2)在sca-provider项目pom.xml中添加如配置依赖

<!--这个依赖添加后,项目启动时会读取第三步bootstrap.yml文件中的配置信息-->
  <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>

 3)将项目sca-provider的application.yml的名字修改为bootstrap.yml(启动优先级最高),并添加配置中心配置

spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
      config:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
        file-extension: yml # 配置中心 服务名后缀

 4)在Nacos http://localhost:8848/nacos中新建 (日志级别的)配置

 

5)测试日志级别的配置是否成功

启动sca-provider主启动类/服务

打开 Http Client 工具或者postman等模拟前端浏览器请求的工具

 我们配置的是error,只能打印error和级别比他高的

如果我们配置的是debug,那么打印出来的就是

 6)常见问题

如果在配置中心配置了,但是却没有效果:重启Nacos看看行不行

7)我们上面配置的日志级别 存在了Nacos的数据库中了

1-2、Nacos服务 配置(日志级别在浏览器上显示的 配置)——外部系统/外界 对配置的感知:我们在浏览器中能看到日志级别的变化

@RefreshScope注解的应用

1步:

在1-1的ProviderLogController类的上面添加一个@RefreshScope注解:@RefreshScope的作用是在配置中心的相关配置发生变化以后,能够及时看到类中属性值的更新(底层是通过重新创建Controller对象的方式,对属性进行了重新初始化)。

2步:

添加ProviderLogController中添加一个获取日志级别(debug<info<warn<error)的的属性和方法

3步:测试

*************************************************************************

三、Nacos服务 配置管理  整体结构

1、命名空间

        1)新建命名空间

默认的是public,默认存在,如果我们没有配置命名空间,我们写的配置就默认存在public这个命名空间

我们平常新建的命名空间命名  示例如图:开发环境...

2)修改项目module中的配置文件bootstrap.yml,添加如下配置

namespace: ab4dbcc9-0d91-4d95-8ac0-06c2eff11524  #要使用的命名空间的ID,指定要使用哪个命名空间

server:
  port: 8081
spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
      config:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
        file-extension: yml # 配置中心 服务名后缀
        namespace: ab4dbcc9-0d91-4d95-8ac0-06c2eff11524  #要使用的命名空间的ID

重启服务

2、克隆

克隆:将一个命名空间的某个配置克隆到另一个命名空间

要求:将public命名空间中的sca-provider.yml配置 克隆到我们新建的那个  开发环境dev 命名空间里

3、分组

1)同一个命名空间下的分组:比如五一、国庆使用不同组的配置--此处在dev命名空间下示例

一个服务在不同时间节点(节假日,活动等)切换不同的配置,可以在新建配置时指定分组名称,如图

 2)配置发布以后,修改boostrap.yml配置类,在其内部指定我们刚刚创建的分组

group:DEFAULT_GROUP_51 #要使用的时哪个分组,指定要使用哪个分组——默认为group:DEFAULT_GROUP

server:
  port: 8081
spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
      config:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
        file-extension: yml # 配置中心 服务名后缀
        namespace: ab4dbcc9-0d91-4d95-8ac0-06c2eff11524  #要使用的命名空间的ID
        group:DEFAULT_GROUP_51 #要使用的时哪个分组

3)测试:新建一个Controller类中添加属性和方法用于获取和输出DEFAULT_GROUP_51中的useLocalCache的值,代码如下

package com.jt.provider.controller;

@Slf4j   //注意,只要下面用到log输出日志级别或其他东西,都要用这个注解生成log对象
@RefreshScope
@RestController
public class ProviderCacheController {
    @Value("${useLocalCache:false}")
    private boolean useLocalCache;

    @GettingMapping("/provider/cache01")
    public String doUseLocalCache01(){
        return String.format("useLocalCache's value is %s",useLocalCache);
    }
    @GetMapping("/provider/doLog02")
    public String doUseLocalCache02(){
       if(!useLocalCache){
           log.info("select data from database");
           return "the data of database";//从数据库中取配置——1)中本地缓存useLocalCache未开启,是false时
       }
        log.info("select data from cache");
        return "the data of cache";//从本地缓存中取配置——1)中本地缓存useLocalCache开启时,是true时
    }
}

然后重启服务,进行访问测试,检测内容输出-浏览器/postman/Http Client 工具

4、共享配置

当同一个  namespace/命名空间  的多个配置文件中都有相同配置时,可以对这些配置进行提取,然后存储到nacos配置中心的一个或多个指定配置文件,哪个微服务需要,就在服务的配置中设置读取即可

1)在nacos中 的一个命名空间 创建一个共享配置文件

2)在指定的微服务配置文件(bootstrap.yml)中引用共享配置

此处是在 group:DEFAULT_GROUP_51这个分组引用共享配置;

若是没有写 group:DEFAULT_GROUP_51,就是默认的 group:DEFAULT_GROUP这个分组引用共享配置

# 共享配置
        shared-configs[0]:
                data-id: app-public.yml
                refresh: true #默认false,共享配置更新,引用此配置的地方是否要更新
server:
  port: 8081
spring:
  application:
    name: sca-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
      config:
        server-addr: 127.0.0.1:8848  #本机时改成下面图片中的localhost
        file-extension: yml # 配置中心 服务名后缀
        namespace: ab4dbcc9-0d91-4d95-8ac0-06c2eff11524  #要使用的命名空间的ID
        group:DEFAULT_GROUP_51 #要使用的时哪个分组
        # 共享配置
        shared-configs[0]:     #[0],下标0对应一个配置文件,下标1对应一个配置文件;0、1、2...这样去写
                data-id: app-public.yml
                refresh: true #默认false,共享配置更新,引用此配置的地方是否要更新

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;
    }
}

启动服务,然后打开浏览器进行访问测试

********************************************************************
 


版权声明:本文为fhefhffg原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。