SpringCloud Alibaba使用Nacos作为服务注册及配置中心

Nacos简介

Nacos是阿里巴巴开源的服务注册中心以及配置中心,致力于给开发者提供一款便捷、简单上手的开源框架。

nacos和eureka功能对比:

Nacos注册中心原理

注册流程

整个注册中心的注册和发现流程主要有三个方面来完成:服务的提供方(以下简称server)、服务的消费者(以下简称client)、注册中心(nacos)。首先我们来探讨server与nacos的交互过程。

server需要通过nacos官方的OpenApi提供的接口来发起服务注册请求,随后server会定时向nacos发送心跳信息来进行心跳检测,对于使用者来说这一步可以采用ScheduledExecutorService创建定时任务来完成。nacos会异步的处理注册请求任务和心跳任务。

nacos心跳机制

nacos和client之间采取推拉结合的交互方式,一方面client可以通过定时任务每隔10s向nacos发起查询请求,如果服务列表改变nacos就会返回新列表,另一方面当本地服务实例发生变化时(即server实例注册成功或者心跳停止断开链接),nacos会主动通过UDP协议推送到client,udp协议非常快,不需要保持长连接。在注册中心的场景中client数量往往多于server,如果每一次服务更新,nacos要和成千上万的服务消费者去建立Tcp的话性能肯定是不行的。而如果UDP通知失败,客户端每10秒还会主动去拉一次,客户端拉取和服务器推送是互补的,这样既能保证server实例更新的时效性,又能提高效率。

Nacos配置中心原理

  1. 在nacos上修改配置。
  2. nacos客户端中ClientWorker会每隔10ms异步读取一次配置中心文件md5值。
  3. 和本地md5值比较,有变化的从服务器拉取。
  4. 将文件保存/缓存到本地。
  5. 通知NacosContextRefresher配置文件有变化。
  6. NacosContextRefresher判断是否需要更新配置。
  7. 发送事件通知ContextRefresher去更新。
  8. 这里是更新配置的关键步骤。
  9. 准备一份before配置,然后通过构建新的Environment的方式拿到新的配置, 接着比较变化,得到有变化的keys。
  10. 构建Environment时会去读取配置文件,文件优先读本地,如果本地没有通过Http请求服务商。
  11. 构建NacosPropertiesSource,并重新生成ConfigurationProperties对象。
  12. 通知RefreshScope去更新。
  13. 销毁scope='refresh'的bean。
  14. 通知bean容器去构建新的bean(懒加载)。
  15. 将属性(@Value注解)注入到新的bean。

集成Nacos

安装Nacos Server

下载软件,安装完成后,访问地址:http://127.0.0.1:8848/nacos/index.html ,默认的账号密码:nacos/nacos

服务注册

前面我们已经搭建好Nacos Server。接下来我们新建module,名称alibaba-cloud-user。

1、引入相关依赖

<!--boot web-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- nacos -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2、启动类上可以不用写注解@EnableDiscoveryClient

3、配置文件

spring:
  application:
    name: alibaba-cloud-user
  cloud:
    nacos:
      discovery:
        enabled: true
        #nacos地址
        server-addr: http://localhost:8848
        #当前应用是否注册到注册中心
        register-enabled: true
        #注册到注册中心的服务名,不配置的话就是spring.application.name的值。一般我们不会特殊指定
        #service: alibaba-cloud-user

4、服务启动后可以在nacos管理界面查看注册成功的服务。

5、可以通过发现客服端搜索实例名的形式查看服务是否注册成功,并查看注册具体信息

@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    public DiscoveryClient discoveryClient;

    @RequestMapping("/getServiceList")
    public List<ServiceInstance> getServiceList(){
        return discoveryClient.getInstances("alibaba-cloud-user");
    }
}

项目启动后,访问:http://localhost:5555/user/getServiceList

配置中心

引入配置中心的目的

  • 配置属性的动态刷新
  • 配置文件的集中管理

接入配置中心

1、引入相关依赖

<!-- nacos config-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2、编写一个bootstrap.yml配置文件(不用application.yml配置了)

server:
  port: 5555

spring:
  application:
    name: alibaba-cloud-user
  cloud:
    nacos:
      #服务注册
      discovery:
        enabled: true
        #nacos地址
        server-addr: http://localhost:8848
        #当前应用是否注册到注册中心,默认是true
        register-enabled: true
      #配置中心
      config:
        enabled: true
        #nacos地址
        server-addr: http://localhost:8848
        #配合文件后缀
        file-extension: yaml

nacos配置中心默认是拿文件名与spring.application.name值一样的文件。例如,上面我们匹配的文件名就是:alibaba-cloud-user.yml。

3、我们在nacos server上创建一个alibaba-cloud-user.yml文件

Data Id类似于文件名。

内容如下:

user:
  name: linhongwei
  password: 123456

4、创建controller获取配置文件的user.name和user.password

@RequestMapping("/user")
@RestController
public class UserController {

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

    @Value("${user.password}")
    private String password;

    //private String userName;
    //@Value("${user.name}")
    //public void setUserName(String userName) {
    //    this.userName = userName;
    //}

    @RequestMapping("/getUserInfo")
    public String getUserInfo() {
        return "userName:" + userName + ", password:" + password;
    }
}

项目启动后,访问:http://localhost:5555/user/getUserInfo

配置文件的匹配规则

1、配置微服务配置中⼼⽂件

在 Nacos Spring Cloud 中,数据集(Data Id) 的配置完整格式如下:

{prefix}-${spring.profile.active}.${file-extension}

1)prefix:就是配置的服务名,默认是你配置的,通俗的说就是服务注册时注册到服务中⼼的服务名的值

spring:
  application:
    name: alibaba-cloud-user

2)spring.profile.active:是配置开发环境的值,⼀个程序不可能总是在开发环境,可能需要切换到测试环境,上线环境,它们的配置⽂件都是不同的,所以为了⽅便环境切换,我们配置不同的开发环境⽂档。⽐如在bootstrap.yml中有配置dev,就是开发环境:

spring:
  profiles:
    active: dev #表⽰开发环境

生效的文件就是alibaba-cloud-user-dev.yml。

我们在nacos再创建一个名为alibaba-cloud-user-dev.yml的配置文件

内容如下:

user:
  name: zhangsan
  password: 654321

访问 http://localhost:5555/user/getUserInfo 

说明环境的切换生效了。

3)最后我们需要指定配置⽂件类型,默认是properties。我们可以⾃⼰指定⽂件类型,⽐如配置:

spring:
  cloud:
    nacos:
      config:
        file-extension: yaml #指定配置⽂件类型为yaml⽂件

命名空间的隔离

public是保留空间,默认新增的所有配置都在public空间。常用来隔离开发,测试,⽣产环境。

可以添加命名空间,然后在bootstrap.yml配置⽂件添加命名空间的id即可切换到对应的命名空间,使⽤对应空间下的配置⽂件:

spring:
  cloud:
    nacos:
      config:
        namespace: 2f7930c8-ccae-4577-bdcd-0cf874cf1297 #对应创建的命名空间的ID

也可以基于微服务来创建命名空间,⽤每⼀个微服务名来命名,达到隔离每⼀个微服务的⽬的,哪⼀个微服务需要配置直接去对应的微服务空间下找配置即可,使得项⽬更加结构化。

配置分组Group

按时间等因素影响,可以去分组配置,⽐如双11组,双12组等等。

默认所有的配置集都属于: DEFAULT_ GROUP。我们也可以⾃⼰适配。

⼀般的建议是使⽤命名空间来隔离服务,即每个微服务创建⼀个命名空间,使⽤配置分组来区分环境:dev、test、prod等。

从⼀个配置中⼼加载多个配置集

将⼀个配置⽂件按功能拆分成不同的⽂件,然后在程序组合加载到⼀起组成⼀个完整的配置⽂件。

⽐如拆分⼀下配置:

pring:
  profiles:
    active: dev #表⽰开发环境
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://139.224.67.81:3306/zunhui_sms?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
  application:
    name: shop-coupon
spring:
  application:
    name: shop-coupon
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml #指定配置⽂件类型为yaml⽂件
      discovery:
        server-addr: 127.0.0.1:8848
mybatis-plus:
  mapper-locations: classpath/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto #配置id⾃增

就可以拆分成三个⽂件,⼀个关务数据源的datasource.yml的,⼀个关于mybatis的,剩下的⼀个other配置:

只需要在配置⽂件中使⽤ext-config就可以加载多个配置⽂件:

spring:
  cloud:
    nacos:
      #配置中心
      config:
        # 扩展配置 老版本是 ext-config,其余的没什么变化
        extension-configs:
          - dataId: datasource.yml
            group: dev
            refresh: true #是否刷新, 默认是false
          - dataId: mybatis.yml
            group: dev
            refresh: true
          - dataId: other.yml
            group: dev
            refresh: true

不同服务存在相同的配置

通过spring.cloud.nacos.config.shared-configs ,配置文件中增加各个微服务共享的配置,注意越排到后面的公共配置yml优先级越高

注:extension-configs的优先级高于shared-configs

扩展的配置文件加载优先级

Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置

  1. 通过 spring.cloud.nacos.config.shared-configs[n].data-id 支持多个共享 Data Id 的配置;
  2. 通过 spring.cloud.nacos.config.extension-configs[n].data-id 的方式支持多个扩展 Data Id 的配置;
  3. 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置;

当三种方式共同使用时,总的来说 他们的一个优先级关系是:A < B < C

 1)以老版本来说:

  • shared-dataids中越靠后,优先级越高;
  • ext-config中n越大、或越靠后,优先级越高;
  • shared-dataids < ext-config < 内部;

 2)以新版本来说:

  • shared-configs中n越大、或越靠后,优先级越高;
  • extension-configs中n越大、或越靠后,优先级越高;
  • shared-configs < extension-configs < 内部; 

本地和远程配置优先级

SpringCloud中,nacos是借助SpringCloud的Config来加载属性源的,所以是否覆盖系统属性和配置文件属性的设置也是通过SpringCloud的配置进行触发。

默认情况下nacos属性源配置优先级最高,会覆盖系统属性源和配置属性源(本地文件)

可以通过在远程配置中心(Nacos服务中)中做如下配置,设置本地配置覆盖远程配置:

spring:  
  cloud:
    config:
      # Nacos远程配置是否不覆盖其他属性源(文件、系统),默认为false,即覆盖其他源(文件、系统),当allow-override:为true时才会生效
      override-none: true
      # 是否允许Nacos远程配置被本地文件覆盖,默认为true
      allow-override: true
      # Nacos远程配置是否可以覆盖系统属性源(系统环境变量或系统属性),默认为true,即允许
      override-system-properties: false

spring.cloud.nacos配置说明

注册中心

配置中心

# nacos 配置中心信息
spring:
  cloud:
    nacos:
      server-addr: 39.103.194.102:8848         # nacos 服务端地址
      username: nacos                          # nacos 用户名
      password: nacos                          # nacos 用户密码
      config:
        file-extension: yaml                  # 配置文件类型   默认 properties 类型
        # namespace: public                   # 命名空间  默认 public  如果配置了 public  循环打印clientWork日志, public 默认不配置
        # group: DEFAULT_GROUP                # 分组 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:
        # enabled: true                       # 通过设置 spring.cloud.nacos.config.enabled = false 来完全关闭 Spring Cloud Nacos Config
        # refresh-enabled: false              # nacos  客户端无法感知
        shared-configs:                       # 使用自定义配置文件时,data-id 必须加文件类型,否则报错
          - data-id: com.mj.dataid-1.yaml
            #group 默认分组 DEFAULT_GROUP
            refresh: true
        extension-configs:
          - data-id: com.mj.dataid-2.yaml
            #group 默认分组 DEFAULT_GROUP
            refresh: true
# 配置文件的优先级
# profile 方式 >  默认配置文件 > extension-configs ( 扩展配置,下标越大 优先级越大)> shared-configs(共享配置)

Nacos使用细节

1、如果我们需要不停机改变我们的生产环境的某个值(例如文件保存地址)来控制业务逻辑。我们需要在对应的类上添加@RefreshScope 进行动态刷新。

 

posted @ 2022-05-05 14:08  残城碎梦  阅读(567)  评论(0编辑  收藏  举报