Nacos

一、什么是Nacos

  英文全称Dynamic Naming and Configuration Service,Na为naming/nameServer即注册中心,co为configuration即注册中心,service是指该注册/配置中心都是以服务为核心

  Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理

二、Nacos原理

  

  Nacos注册中心分为server与client,server采用Java编写,为client提供注册发现服务与配置服务。而client可以用多语言实现,client与微服务嵌套在一起,nacos提供sdk和openApi,如果没有sdk也可以根据openApi手动写服务注册与发现和配置拉取的逻辑

  

  Nacos服务领域模型主要分为命名空间、集群、服务。在下图的分级存储模型可以看到,在服务级别,保存了健康检查开关、元数据、路由机制、保护阈值等设置,而集群保存了健康检查模式、元数据、同步机制等数据,实例保存了该实例的ip、端口、权重、健康检查状态、下线状态、元数据、响应时间

  

注册中心原理

  

  服务注册方法:以Java nacos client v1.0.1 为例子,服务注册的策略的是每5秒向nacos server发送一次心跳,心跳带上了服务名,服务ip,服务端口等信息。同时 nacos server也会向client 主动发起健康检查,支持tcp/http检查。如果15秒内无心跳且健康检查失败则认为实例不健康,如果30秒内健康检查失败则剔除实例

配置中心原理

  

三、 Nacos使用方法

创建命名空间

  不同的命名空间逻辑上是隔离的,不特殊设置的情况下,服务不会跨命名空间请求,命名空间主要的作用是区分服务使用的范围,比如开发、测试、生产、灰度可以分别设置四个命名空间来互相隔离  

   如图所示,在控制台的 服务管理-命名空间-新建命名空间按钮可以创建新的命名空间,命名空间创建后,会在列表显示命名空间ID,这个ID后面会用在服务的配置文件中

在服务上配置注册、配置中心

  以springcloud为例,首先用maven导入nacos clinet的依赖:

     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>0.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>0.2.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     

  先导入springcloud的alibaba-nacos-config和alibaba-nacos-discovery两个依赖,这两个依赖是用于nacos clinet与cloud结合的工具,0.2.x对应springboot 2.x.x ,0.1.x对应springboot 1.x.x。这两个组件可以和各种版本的nacos-client结合。把其中的nacos-clinet依赖给排除,引入想要引入的nacosclinet版本,如下:

   <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.0.1</version>
        </dependency>

  在bootstrap.properties上添加配置中心的配置,如果springboot启动类没有@EnableDiscover注解则加上,完成如上更改,即可使用Nacos注册/配置服务

spring.cloud.nacos.discovery.server-addr=nacos.e.189.cn:80
spring.cloud.nacos.discovery.namespace=命名空间id

通过配置更改动态刷新参数

  普通application参数在配置中心直接配置皆可,如果需要可以动态刷新的配置,需要在相应类上加上@RefreshScope注解,示例如下,当在nacos配置中心更改配置后,方法getId的值也会刷新

@RefreshScope
public class IdEntity {
    @Value("${id}")
    private int id;
    public int getId(){
        return this.id;
    }
}

配置中心参数修改/设置

  如下两张图:在nacos控制台的配置管理-配置列表中顶部选择相应的命名空间,点击列表右上角的加号新增配置,Data ID 为 项目名-{spring.profiles.active}.properties,Group如果在bootstrap.properties中不指定则填默认的DEFAULT_GROUP,描述写该配置的描述,配置内容填写Properties格式或者Yaml格式
  

 

nacos其他功能使用与介绍

控制台手动上下线实例

  在控制台的服务管理-服务列表选择一个服务点击详情,在下方的集群列表可以看到有上线/下线按钮,点击即可以对该实例执行上线/下线操作,下线后的实例不会被请求

配置实例权重

  可以通过手动配置权重来控制流量,当一个集群内两个实例,权重越高,到达该实例的请求比例越多,权重的初始值是1

  

配置保护阈值

  保护阈值的范围是0~1
  服务的健康比例=服务的健康实例/总实例个数
  当服务健康比例<=保护阈值时候,无论实例健不健康都会返回给调用方
  当服务健康比例>保护阈值的时候,只会返回健康实例给调用方
  在服务管理-服务列表选择一个服务点击详情可以配置

四 Nacos作为注册中心

  我们创建一个springcloud父工程,只包含web依赖。然后基于该父工程,分别创建服务提供者Provider和消费者Consumer工程。

服务提供者Provider

  需要的依赖如下:

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

  配置文件如下:

server:
  port: 8091
spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      server-addr: localhost:8848

  创建一个controller来模拟Provider对外提供服务:

@RestController
public class HelloController {

    @GetMapping("/getHello")
    public String getHello(){
        return "hello from nacos provider!";
    }

}

  到此,我们服务提供者就创建好了,在localhost:8091端口等待被调用提供服务

服务消费者Consumer

  需要的依赖如下:

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

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    <version>3.0.3</version>
</dependency>

  配置文件如下:

server:
  port: 8092
spring:
  application:
    name: nacos-consumer
  cloud:
    nacos:
      server-addr: localhost:8848

  创建一个Controller类,对外提供调用的接口,然后在Controller中通过OpenFeign转发调用请求给到Provider

@RestController
public class HelloController {

    @Autowired
    private FeignService feignService;

    @GetMapping("/getHello")
    public String getHello(){
        return feignService.getHello();
    }

}
@FeignClient("nacos-provider")
public interface FeignService {

    @GetMapping("/getHello")
    String getHello();

}

  如上Service表示需要请求注册中心中服务名称为nacos-provider的/getHello接口。最后,我们需要在启动类上加上启动注解

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class DiscoveryConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DiscoveryConsumerApplication.class, args);
    }

}

  到此,消费者Consumer也创建好了,在localhost:8092提供调用服务。我们访问Consumer的/getHello接口,获得的返回内容为:

  hello from nacos provider!

五 Nacos作为配置中心

入门案例

  首先我们需要引入必要的依赖包:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2021.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

  我们在启动配置文件bootstrap.properties中配置如下的内容:

spring.application.name=nacos-provider
spring.cloud.nacos.server-addr=127.0.0.1:8848

  然后我们创建一个Controller就可以演示从远端获取配置内容了:

@RefreshScope
@RestController
public class ConfigController {

    @Value("${provider.name}")
    private String providerName;

    @GetMapping("/getDevConfig")
    public String getDevConfig(){
        return this.providerName;
    }

}

  代码层面的示例都已经写好了,我们在远端nacos服务端,切换到配置管理的配置列表界面,需要点击+号新建一个:

  • DataID,该字段的取名是有规则的,一般而言分为三个部分,{1}-{2}.{3},其中第一部分应该和刚才本地bootstrap.properties中配置的spring.application.name完全一样;第二部分表示生效的环境名称,比如dev、stg等;第三部分表示配置文件后缀,只支持properties或者yaml类型。在这里,我们的值应该为nacos-provider.properties
  • Group,这里先设置默认的DEFAULT_GROUP即可;
  • 配置内容,把需要保存在远端Nacos的配置内容写在里面即可,这里为provider.name=nacos123

  配置点击发布后,我们启动本地的nacos-provider服务,访问Controller,就会发现读取到了nacos123的配置内容。

配置文件的环境区分

  在实际使用时,我们一般都是区分dev、stg、prd三套环境来维护各个环境的配置文件内容的。在这样的情况下,我们的应用程序如何读取不同环境下的配置内容呢

通过profile区分

  首先我们在Nacos配置中心再增加两个DataID,分别如下:

# nacos-provider-dev.properties
# DEFAULT_GROUP
provider.name=nacos-dev
# nacos-provider-stg.properties
# DEFAULT_GROUP
provider.name=nacos-stg

  为了让这两个配置文件生效,我们在本地应用端的bootstrap.properties中指定生效配置文件的环境名称即可:

spring.application.name=nacos-provider
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.profiles.active=dev
# spring.profiles.active=stg

  再重启我们的应用,就能读取到各自环境的配置文件了

通过namespace区分

  默认我们会到public这个命名空间下去读取配置文件,此时我们新建两个命名空间,分别命名为dev和stg,然后将public命名空间下的nacos-provider.properties克隆到dev和stg命名空间下,并修改provider.name的配置内容:

# namespace dev
provider.name=nacos-dev-123
# namespace stg
provider.name=nacos-stg-123

  我们在本地的应用中增加一个配置项,表明想要引用的namespace:

spring.cloud.nacos.config.namespace=0a6be74a-426e-45eb-8531-6d7230f26af6

  然后重启应用,就能读取到对应namespace下面的配置内容了

加载多配置文件

  默认情况下,本地应用会去nacos服务端读取对应namespace下面的以应用名称开头的配置文件,在本例子中就是nacos-provider.properties,因为我们本地应用配置的spring.application.name=nacos-provider,在实际开发中,往往会有多个配置文件,那么如何同时加载多个配置文件中的配置内容呢?

  首先,我们在public命名空间下再新建两个配置文件:

# redis.properties
redis.server=127.0.0.1
# mq.properties
mq.nameserver=localhost

  同时,我们需要在本地项目的bootstrap.properties配置文件中增加如下的配置内容:

spring.cloud.nacos.config.ext-config[0].data-id=redis.properties
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true

spring.cloud.nacos.config.ext-config[0].data-id=mq.properties
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true

  对应的yml配置形式为:

spring:
  cloud:
    nacos:
      config:
        extension-configs:
          - refresh: true
            group: DEFAULT_GROUP
            data-id: redis.properties
          - refresh: true
            group: DEFAULT_GROUP
            data-id: mq.properties

  然后,修改我们的controller,引用nacos服务器上的不同配置文件里面的配置项:

@RefreshScope
@RestController
public class ConfigController {

    @Value("${provider.name}")
    private String providerName;
    @Value("${redis.server}")
    private String redisServer;
    @Value("${mq.nameserver}")
    private String mqServer;

    @GetMapping("/getDevConfig")
    public String getDevConfig() {
        return this.providerName + "/" + this.redisServer + "/" + this.mqServer;
    }

}

  重启应用后,就能成功访问不同配置文件里面的配置项了。

配置文件的分组区分

  如上我们注意到,分组Group一直都是DEFAULT_GROUP,其实我们可以在不同的Group里面创建相同名称的配置文件。比如在微服务环境中,多个微服务组件都有redis.properties的配置文件,那么如何区分哪个微服务该使用哪个Group下面的配置文件呢,其实也很简单,只要在配置文件中指定Group即可。

本实例比较简单,就不演示了,其实对于同一个应用也可以读取不同Group下面的配置文件配置内容,我们完全也可以用Group来作为dev、stg和prd的区分。

  总之,Nacos为我们提供了三个维度来做区分,即profile、namespace和Group,开发者可以灵活应用来做自己想要的区分。

共享配置

  很多时候,多个微服务中有相同的配置内容,比如大家连结的是同一个redis服务,同一个mq服务,那么就需要在各自的配置文件中都写上相同的配置内容,显得比较繁琐,我们完全可以将这些共同的配置内容抽取出来,形成另一个配置文件,然后大家共享它。

  比如,我们在public命名空间下新建DEFAULT_GROUP的配置文件share.properties

provider.share=share123

  然后本地配置文件中新增如下配置内容:

# 如果有多个共享配置文件,相互之间用逗号分隔即可
spring.cloud.nacos.config.shared_dataids: share.properties
spring.cloud.nacos.config.refreshable-dataids: share.properties

  然后在Controller中增加共享配置的读取内容,此处就省略了,重启应用就可以生效了。

  注意,如果共享配置不是DEFAULT_GROUP下面的,就不能使用如上的方式,而是采用2.3节中讲述的方式

配置内容的优先级

  有些时候,我们在加载的配置文件中都配置了同一个配置项的值,而且相互之间都不相同,那么本地应用最终以哪个配置文件中的内容为准呢

  • A:使用spring.cloud.nacos.config.prefixspring.cloud.nacos.config.file-extensionspring.cloud.nacos.config.group这几个参数拼接出来的配置文件;
  • B:使用2.3节中extension-configs指定的配置间件;
  • C:使用2.5节中共享配置指定的配置文件;
  • D:本地配置的配置内容;

  优先级顺序为:D>A>B>C

posted on 2022-03-01 22:55  胡子就不刮  阅读(1290)  评论(0编辑  收藏  举报

导航