Nacos Reference Documentation

1.0.0.RELEASE

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

版权说明-本文档根据阿里巴巴开源项目Nacos和spring-cloud-alibaba,以及公开沙龙内容整理而来,仅供个人学习使用。版权归阿里巴巴和原作者所有

http://nacos.net


Table of Contents

I. Nacos 简介
1. 什么是Nacos
2. Nacos架构剖析
II. Nacos Config 简介
3. 配置中心概述
4. Nacos Config概述
5. Nacos Config对比
III. Nacos Config Quick Start
6. Nacos Config 入门案例
IV. Nacos Config设计揭秘
V. Nacos Naming 简介
7. 配置中心概述
8. Nacos Naming概述
9. Nacos Naming对比
VI. Nacos Naming Quick Start
10. Nacos Naming 入门案例
VII. Nacos Naming设计揭秘
VIII. Spring Cloud Nacos Config
11. 快速开始
11.1. Nacos 服务端初始化
11.2. 客户端使用方式
11.3. 基于 dataid 为 yaml 的文件扩展名配置方式
11.4. 支持配置的动态更新
11.5. 可支持profile粒度的配置
11.6. 支持自定义 namespace 的配置
11.7. 支持自定义 Group 的配置
11.8. 支持自定义扩展的 Data Id 配置
12. Spring Cloud Nacos Config 共享配置方案设计
12.1. 基于域名的配置方式给应用分组
12.2. 自定义的方式来命名 Data Id
12.3. 通过类似面向对象方式的自定义配置
12.4. 最终的实现
IX. Spring Cloud Nacos Discovery
13. 服务注册发现: Nacos Discovery Starter
13.1. 启动一个 Provider 应用
13.2. 服务的 EndPoint
13.3. 启动一个 Consumer 应用
13.4. 关于 Nacos Starter 更多的配置项信息
X. Nacos FAQ
14. Nacos常见FAQ

Nacos产品release note https://github.com/alibaba/nacos/releases [《Nacos release》^]

联系我们:Software_King@qq.com

Part I. Nacos 简介

Nacos 是阿里巴巴今年2018年7月份开源的项目,如其名所示Naming Configuration Service ,专注于服务发现和配置管理领域。

Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

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

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

[Note]Note
Nacos Reference的编写

1. 什么是Nacos

服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理:

2. Nacos架构剖析

Nacos主要分为两部分,分别是Nacos Config和Nacos Naming。它集注册中心和配置中心为一体。

Part II. Nacos Config 简介

3. 配置中心概述

4. Nacos Config概述

Nacos Config真正将配置从应用中剥离出来,统一管理,优雅的解决了配置的动态变更、持久化、运维成本等问题。 应用自身既不需要去添加管理配置接口,也不需要自己去实现配置的持久化,更不需要引入“定时任务”以便降低运维成本。

Nacos 提供的配置管理功能,将配置相关的所有逻辑都收拢,并且提供简单易用的 SDK, 让应用的配置可以非常方便被 Nacos 管理起来。

5. Nacos Config对比

Part III. Nacos Config Quick Start

6. Nacos Config 入门案例

public List<GregorianCalendar> authorsBornAfter1980() {
    return this.create.selectFrom(AUTHOR)
        .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
        .fetch(AUTHOR.DATE_OF_BIRTH);
}

Part IV. Nacos Config设计揭秘

Part V. Nacos Naming 简介

7. 配置中心概述

8. Nacos Naming概述

9. Nacos Naming对比

Part VI. Nacos Naming Quick Start

10. Nacos Naming 入门案例

Part VII. Nacos Naming设计揭秘

Part VIII. Spring Cloud Nacos Config

Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。

Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案,客户端和服务器上的概念与 Spring Environment 和 PropertySource 有着一致的抽象,在特殊的 bootstrap 阶段,配置被加载到 Spring 环境中。当应用程序通过部署管道从开发到测试再到生产时,您可以管理这些环境之间的配置,并确保应用程序具有迁移时需要运行的所有内容。

11. 快速开始

11.1 Nacos 服务端初始化

1、启动Nacos Server。启动方式可见 Nacos 官网

2、启动好Nacos之后,在Nacos添加如下的配置:

Data ID:    nacos-config.properties

Group  :    DEFAULT_GROUP

配置格式:    Properties

配置内容:   user.name=nacos-config-properties
            user.age=90
[Note]Note

注意dataid是以 properties(默认的文件扩展名方式)为扩展名。

11.2 客户端使用方式

为了能够在应用程序中使用 Nacos 来实现应用的外部化配置,在构建应用的同时添加一个Spring Boot Starter org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config。以下是一个基本的 maven 依赖配置:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/>
</parent>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.2.BUILD-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

 <dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

现在就可以创建一个标准的 Spring Boot 应用。

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        String userName = applicationContext.getEnvironment().getProperty("user.name");
        String userAge = applicationContext.getEnvironment().getProperty("user.age");
        System.err.println("user name :"+userName+"; age: "+userAge);
    }
}

在运行此 Example 之前, 必须使用 bootstrap.properties 配置文件来配置Nacos Server 地址,例如:

bootstrap.properties. 

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

[Note]Note

注意当你使用域名的方式来访问 Nacos 时,spring.cloud.nacos.config.server-addr 配置的方式为 域名:port。 例如 Nacos 的域名为abc.com.nacos,监听的端口为 80,则 spring.cloud.nacos.config.server-addr=abc.com.nacos:80。 注意 80 端口不能省略。

启动这个 Example,可以看到如下输出结果:

2018-11-02 14:24:51.638  INFO 32700 --- [main] c.a.demo.provider.ProviderApplication    : Started ProviderApplication in 14.645 seconds (JVM running for 15.139)
user name :nacos-config-properties; age: 90
2018-11-02 14:24:51.688  INFO 32700 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@a8c5e74: startup date [Fri Nov 02 14:24:51 CST 2018]; root of context hierarchy
2018-11

11.3 基于 dataid 为 yaml 的文件扩展名配置方式

spring-cloud-starter-alibaba-nacos-config 对于 yaml 格式也是完美支持的。这个时候只需要完成以下两步:

1、在应用的 bootstrap.properties 配置文件中显示的声明 dataid 文件扩展名。如下所示

bootstrap.properties. 

spring.cloud.nacos.config.file-extension=yaml

2、在 Nacos 的控制台新增一个dataid为yaml为扩展名的配置,如下所示:

Data ID:        nacos-config.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        user.name: nacos-config-yaml
                user.age: 68

这两步完成后,重启测试程序,可以看到如下输出结果。

2018-11-02 14:59:00.484  INFO 32928 --- [main] c.a.demo.provider.ProviderApplication:Started ProviderApplication in 14.183 seconds (JVM running for 14.671)
user name :nacos-config-yaml; age: 68
2018-11-02 14:59:00.529  INFO 32928 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@265a478e: startup date [Fri Nov 02 14:59:00 CST 2018]; root of context hierarchy

11.4 支持配置的动态更新

spring-cloud-starter-alibaba-nacos-config 也支持配置的动态更新,启动 Spring Boot 应用测试的代码如下:

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        while(true) {
            //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            System.err.println("user name :" + userName + "; age: " + userAge);
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

如下所示,当变更user.name时,应用程序中能够获取到最新的值:

user name :nacos-config-yaml; age: 68
user name :nacos-config-yaml; age: 68
user name :nacos-config-yaml; age: 68
2018-11-02 15:04:25.069  INFO 32957 --- [-127.0.0.1:8848] o.s.boot.SpringApplication               : Started application in 0.144 seconds (JVM running for 71.752)
2018-11-02 15:04:25.070  INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10c89124: startup date [Fri Nov 02 15:04:25 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7
2018-11-02 15:04:25.071  INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7: startup date [Fri Nov 02 15:04:24 CST 2018]; root of context hierarchy
//从 Enviroment 中 读取到更改后的值
user name :nacos-config-yaml-update; age: 68
user name :nacos-config-yaml-update; age: 68
[Note]Note

你可以通过配置 spring.cloud.nacos.config.refresh.enabled=false 来关闭动态刷新

11.5 可支持profile粒度的配置

spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,还加载了dataid为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 ${spring.profiles.active} 这个配置项来配置。

spring.profiles.active=develop
[Note]Note

${spring.profiles.active} 当通过配置文件来指定时必须放在 bootstrap.properties 文件中。

Nacos 上新增一个dataid为:nacos-config-develop.yaml的基础配置,如下所示:

Data ID:        nacos-config-develop.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        current.env: develop-env

启动 Spring Boot 应用测试的代码如下:

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
        while(true) {
            String userName = applicationContext.getEnvironment().getProperty("user.name");
            String userAge = applicationContext.getEnvironment().getProperty("user.age");
            //获取当前部署的环境
            String currentEnv = applicationContext.getEnvironment().getProperty("current.env");
            System.err.println("in "+currentEnv+" enviroment; "+"user name :" + userName + "; age: " + userAge);
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

启动后,可见控制台的输出结果:

in develop-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:34:25.013  INFO 33014 --- [ Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f1c29b7: startup date [Fri Nov 02 15:33:57 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@63355449

如果需要切换到生产环境,只需要更改 ${spring.profiles.active} 参数配置即可。如下所示:

spring.profiles.active=product

同时生产环境上 Nacos 需要添加对应 dataid 的基础配置。例如,在生成环境下的 Naocs 添加了dataid为:nacos-config-product.yaml的配置:

Data ID:        nacos-config-product.yaml

Group  :        DEFAULT_GROUP

配置格式:        YAML

配置内容:        current.env: product-env

启动测试程序,输出结果如下:

in product-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:42:14.628  INFO 33024 --- [Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6aa8e115: startup date [Fri Nov 02 15:42:03 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@19bb07ed
[Note]Note

此案例中我们通过 spring.profiles.active=<profilename> 的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=<profile> 参数指定其配置来达到环境间灵活的切换。

11.6 支持自定义 namespace 的配置

首先看一下 Nacos 的 Namespace 的概念, Nacos 概念

用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。如果需要使用自定义的命名空间,可以通过以下配置来实现:

spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7
[Note]Note

该配置必须放在 bootstrap.properties 文件中。此外 spring.cloud.nacos.config.namespace 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespae,否则将会导致读取不到正确的配置。

11.7 支持自定义 Group 的配置

在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下, 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:

spring.cloud.nacos.config.group=DEVELOP_GROUP
[Note]Note

该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 spring.cloud.nacos.config.group 的配置值一致。

11.8 支持自定义扩展的 Data Id 配置

Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 这里。 一个完整的配置案例如下所示:

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

# config external configuration
# 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新
spring.cloud.nacos.config.ext-config[0].data-id=ext-config-common01.properties

# 2、Data Id 不在默认的组,不支持动态刷新
spring.cloud.nacos.config.ext-config[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.ext-config[1].group=GLOBALE_GROUP

# 3、Data Id 既不在默认的组,也支持动态刷新
spring.cloud.nacos.config.ext-config[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.ext-config[2].group=REFRESH_GROUP
spring.cloud.nacos.config.ext-config[2].refresh=true

可以看到:

  • 通过 spring.cloud.nacos.config.ext-config[n].data-id 的配置方式来支持多个 Data Id 的配置。
  • 通过 spring.cloud.nacos.config.ext-config[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
  • 通过 spring.cloud.nacos.config.ext-config[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。
[Note]Note

多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.ext-config[n].data-id 其中 n 的值越大,优先级越高。

[Note]Note

spring.cloud.nacos.config.ext-config[n].data-id 的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。

通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件。

为了更加清晰的在多个应用间配置共享的 Data Id ,你可以通过以下的方式来配置:

spring.cloud.nacos.config.shared-dataids=bootstrap-common.properties,all-common.properties
spring.cloud.nacos.config.refreshable-dataids=bootstrap-common.properties

可以看到:

  • 通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享 Data Id 的配置,多个之间用逗号隔开。
  • 通过 spring.cloud.nacos.config.refreshable-dataids 来支持哪些共享配置的 Data Id 在配置变化时,应用中是否可动态刷新, 感知到最新的配置值,多个 Data Id 之间用逗号隔开。如果没有明确配置,默认情况下所有共享配置的 Data Id 都不支持动态刷新。
[Note]Note

通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享配置的 Data Id 时, 多个共享配置间的一个优先级的关系我们约定:按照配置出现的先后顺序,即后面的优先级要高于前面。

[Note]Note

通过 spring.cloud.nacos.config.shared-dataids 来配置时,Data Id 必须带文件扩展名,文件扩展名既可支持 properties,也可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。

[Note]Note

spring.cloud.nacos.config.refreshable-dataids 给出哪些需要支持动态刷新时,Data Id 的值也必须明确给出文件扩展名。

12. Spring Cloud Nacos Config 共享配置方案设计

随着社区的回馈,发现 Spring Cloud Alibaba Nacos Config Starter 目前不能完美的来支持多个应用间的一些共享配置。 在实际的业务场景中应用和共享配置间的关系可能如下图所示:

sca shared 01
  • 从单个应用的角度来看: 应用可能会有多套(develop/beta/product)发布环境,多套发布环境之间有不同的基础配置,例如数据库。
  • 从多个应用的角度来看:多个应用间可能会有一些共享通用的配置,比如多个应用之间共用一套zookeeper集群。

目前 SCA Nacos Config 可以灵活的支持单个应用间在多套环境可灵活的切换,但是在多个应用间共享一些通用的配置支持的还不是很完美。 本方案设计的目标就是来解决这个问题。目前有三种设计方案,分别是:

  • 新增一个应用分组的配置,分组命名的格式是 通过域名的命名方式,来自动的生成共享配置的 Data Id。
  • 自定义命名的方式来命名 Data Id 。
  • 通过类似面向对象的方式自定义配置(相对于第二种的升级版)。

下面分别来分析三种方案的具体实现和优缺点。

12.1 基于域名的配置方式给应用分组

通过一个配置参数(例如:${spring.application.group}) 来指明当前应用所属的分组(或者说所属的域)。 例如我有两个应用分别为Order_Application和Auth_Application,给这两个应用配置的分组名(域)是:

bootstrap.properties. 

spring.application.group=com.alibaba.aliware.edas

那对于Spring Cloud Alibaba Nacos Config 来说,多个应用可以属于 com.alibaba 这个应用分组(域),也可以属于 com.alibaba.aliware 这个应用分组(域),当然也可以属于 com.alibaba.aliware.edas 这个应用分组(域)。 罗里吧嗦了这么多,目的就是 Data Id 通过以这个分组(域)来命名,从而实现多个应用间在某个分组(域)下的共享配置。如下图所示:

sca shared 02

以这种方式来实现多个应用间的配置共享,可以看出他具有天然的局限性。

  • 受到 ${spring.application.group }配置的影响,Data Id 的表现力是非常有限的(当然85%的场景应该够用了)。

    • 一方面是Data Id 的命名个数受到了限制。
    • 另一方面如果两个应用的 file-extension 不一致(一个是properties,一个是yaml),那这个时候共享配置的Data Id 必须同时要含有 properties 和 yaml 为扩展名的配置。
    • Data Id 的命名也受到了 ${spring.application.group } 配置的束缚。
  • 学习成本偏高(当然还是可以学会的)。学习成本偏高体现在:

    • 要知道Data Id 的命名规则,才能在项目实施过程中对 Data Id 的命名运用自如。
    • 此外对于域名命名的层次个数也不太好把握。少了的话,担心dataid的个数不够用,多了的话看上去有显得的比较冗余。
    • 还需要学习并理解这里配置的优先级,不然在程序中有可能就会拿到意想不到的配置。
  • 易出错(当然是可以克服的)。对于多级应用分组的配置共享,这个时候Data Id 的命名要格外注意了。注意他们的层次关系,Data Id 书写时不要张冠李戴。
  • 实现起来稍微复杂

当然他的好处也非常明显,当你理解了他背后的设计理念时,这个共享配置的层次也非常明显。因为层次的关系天然依托于域名的层次关系。

12.2 自定义的方式来命名 Data Id

这种方式实现简单易懂,即 SCA Nacos Config 会新增加一个配置,用来配置可实现共享配置所有的 Data Id。如下所示:

bootstrap.properties. 

spring.cloud.nacos.shared.dataids=global.yaml,app-common.yaml,app-local-common.yaml

[Note]Note

为了尽可能的和Nacos使用方式(即Data Id 是一个带有额外文件扩展名的)保持一致,这里配置的Data Id 是一定需要带上文件扩展名的。

这个时候两个应用(或多个应用)之间共享配置的 Data Id 关系如下图所示:

sca shared 03

Spring Boot 提倡约定大于配置。当使用这种方式来实现应用间的共享配置时,我们也继承了Spring Boot的这个优良传统,多个共享配置间的一个优先级的关系我们约定:按照配置出现的先后顺序,即后面的优先级要高于前面的。 这种方式的优点在于:

  • dataid的命名方式完全交给业务方本身,不受 SCA Nacos Config Starter 实现的束缚。
  • dataid的命名方式既可以参考第一种方式来命名,又可以充分的发挥主观能动性,结合自己实际的业务给dataid命名。
  • 减少了多个应用间如果file-extension不一致,为每个 file-extension 多加这么一个配置的麻烦。
  • 当使用这种方式时,不会为这些共享配置强制绑定一个 file-extenson,即可以直接在我们暴露出来的一个变量中 dataid以file-extension 结尾。如果没有显示的说明,这个时候就会以file-extenson为准。

当然这种方案的缺点在于扩展性不强。即如果对于某个共享配置需要做额外的配置,例如额外配置Group/是否需要刷新/是否需要从本地缓存加载等等。因此为了应对这种类型的场景,小组内讨论出了第三种方案。

12.3 通过类似面向对象方式的自定义配置

说明:Spring 可以支持在加了 ConfigurationProperties 注解配置类的内部某个对象实例来注入应用中的一些配置。 这种使用方式查了一下官方和网络上没有一个大的标题总结,结合这种方式很像给某个实例中的字段赋值,所以这里先暂时取名: 类似面向对象方式的自定义配置(有更好能够形象的标明其含义的命名可以在下面留下评论-_-)。

这种方案沿用了第二种设计方案的优点,同时又弥补了第二种方案的不足。我们通过内部定义一个对象,来支持一些灵活的扩展配置。 我们给这个对象可以预留一些可扩展的配置字段。例如:

Config.java. 

public class Config{
    private String dataId;
    private String group = "DEFAULT_GROUP";
    private Boolean refresh = false;
    //.....后期可能还有其他的一些配置

    //省略 set/get 方法
}

最终在实现时是可以支持以list的方式来配置其值。如下是两个扩展配置的实例:

bootstrap.properties. 

spring.cloud.nacos.config.ext-config[0].data-id=global-shared.properties # group 和referesh 使用默认值
spring.cloud.nacos.config.ext-config[1].data-id=app-common.properties
spring.cloud.nacos.config.ext-config[1].group=DEVELOP_GROUP #配置自定义所在的组
spring.cloud.nacos.config.ext-config[1].refresh=true #需要刷新

[Note]Note

为了尽可能的和Nacos使用方式(即data id是一个带有额外文件扩展名的)保持一致,这里配置的dataid是一定需要带上文件扩展名的。

12.4 最终的实现

SCA Nacos Config 在第二种方案和第三种方案的实现上是并存的。如果你觉得第三种方案配置的比较麻烦,同时第二种方案就可以满足你的需求,这个时候就可以选择第二种方案。 如果你需外可读性好、层级感比较明显、后期的扩展性更强,那这个时候第三种方案也是OK的。

Part IX. Spring Cloud Nacos Discovery

该项目通过自动配置以及其他 Spring 编程模型的习惯用法为 Spring Boot 应用程序在服务注册与发现方面提供和 Nacos 的无缝集成。 通过一些简单的注解,您可以快速来注册一个服务,并使用经过双十一考验的 Nacos 组件来作为大规模分布式系统的服务注册中心。

13. 服务注册发现: Nacos Discovery Starter

服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于 服务的动态扩缩容。Nacos Discovery Starter 可以帮助您将服务自动注册到 Nacos 服务端并且能够动态感知和刷新某个服务实例的服务列表。除此之外,Nacos Discovery Starter 也将服务实例自身的一些元数据信息-例如 host,port,健康检查URL,主页等-注册到 Nacos 。Nacos 的获取和启动方式可以参考 Nacos 官网

===如何引入 Nacos Discovery Starter

为了能够在你的工程下引入 Nacos Discovey Starter,使用group ID 为 org.springframework.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-nacos-discovery。 pom.xml 示例如下所示:

<!-- dependency management-->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.2.BUILD-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- dependencies -->
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

13.1 启动一个 Provider 应用

如果您使用的 Spring Cloud 版本是 Finchley.SR1 版本,那么这个时候您的Spring Boot版本的选择可需要额外的小心了,因为版本的不匹对,可能会导致许多意外的效果。 Spring Cloud 的 Finchley.SR1 版本最佳实践的 Spring Boot 版本是 2.0.6.RELEASE。在启动您的一个 Provider 应用时请检查依赖的 Spring Boot 版本是否是 1.X.Y.RELEASE 或者 2.1.0.RELEASE 的版本。如果不是,请更正到 2.0.6.RELEASE 版本。

以下步骤向您展示了如何将一个服务注册到 Nacos。

  1. pom.xml的配置。一个完整的 pom.xml 配置如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>open.source.test</groupId>
    <artifactId>nacos-discovery-test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>nacos-discovery-test</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>0.2.2.BUILD-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  1. application.properties 配置。一些关于 Nacos 基本的配置也必须在 application.properties(也可以是application.yaml)配置,如下所示: application.properties
server.port=8081
spring.application.name=nacos-producer
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
management.endpoints.web.exposure.include=*
[Note]Note

如果不想使用 Nacos 作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery 设置为 false

  1. 启动 Provider 示例。如下所示:
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderDemoApplication {

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

    @RestController
    public class EchoController {
        @GetMapping(value = "/echo/{string}")
        public String echo(@PathVariable String string) {
            return "Hello Nacos Discovery " + string;
        }
    }
}

这个时候你就可以在 Nacos的控制台上看到注册上来的服务信息了。

[Note]Note

再启动 Provider 应用之前 请先将 Nacos 服务启动。具体启动方式可参考 Naco 官网

13.2 服务的 EndPoint

spring-cloud-starter-alibaba-nacos-discovery 在实现的时候提供了一个EndPoint,EndPoint的访问地址为 http://ip:port/actuator/nacos-discovery。 EndPoint 的信息主要提供了两类:

1、subscribe: 显示了当前有哪些服务订阅者
2、NacosDiscoveryProperties: 显示了当前服务实例关于 Nacos 的基础配置

一个服务实例访问 EndPoint 的信息如下所示:

{
  "subscribe": [
    {
      "jsonFromServer": "",
      "name": "nacos-provider",
      "clusters": "",
      "cacheMillis": 10000,
      "hosts": [
        {
          "instanceId": "30.5.124.156#8081#DEFAULT#nacos-provider",
          "ip": "30.5.124.156",
          "port": 8081,
          "weight": 1.0,
          "healthy": true,
          "enabled": true,
          "cluster": {
            "serviceName": null,
            "name": null,
            "healthChecker": {
              "type": "TCP"
            },
            "defaultPort": 80,
            "defaultCheckPort": 80,
            "useIPPort4Check": true,
            "metadata": {

            }
          },
          "service": null,
          "metadata": {

          }
        }
      ],
      "lastRefTime": 1541755293119,
      "checksum": "e5a699c9201f5328241c178e804657e11541755293119",
      "allIPs": false,
      "key": "nacos-producer",
      "valid": true
    }
  ],
  "NacosDiscoveryProperties": {
    "serverAddr": "127.0.0.1:8848",
    "endpoint": "",
    "namespace": "",
    "logName": "",
    "service": "nacos-provider",
    "weight": 1.0,
    "clusterName": "DEFAULT",
    "metadata": {

    },
    "registerEnabled": true,
    "ip": "30.5.124.201",
    "networkInterface": "",
    "port": 8082,
    "secure": false,
    "accessKey": "",
    "secretKey": ""
  }
}

13.3 启动一个 Consumer 应用

Consumer 的应用可能还没像启动一个 Provider 应用那么简单。因为在 Consumer 端需要去调用 Provider 端提供的REST 服务。例子中我们使用最原始的一种方式, 即显示的使用 LoadBalanceClient 和 RestTemolate 结合的方式来访问。 pom.xml 和 application.properties 的配置可以参考 1.2 小结。启动一个 Consumer应用的示例代码如下所示:

[Note]Note

通过带有负载均衡的RestTemplate 和 FeignClient 也是可以访问的。

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApp {

    @RestController
    public class NacosController{

        @Autowired
        private LoadBalancerClient loadBalancerClient;
        @Autowired
        private RestTemplate restTemplate;

        @Value("${spring.application.name}")
        private String appName;

        @GetMapping("/echo/app-name")
        public String echoAppName(){
            //使用 LoadBalanceClient 和 RestTemolate 结合的方式来访问
            ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");
            String path = String.format("http://%s:%s/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
            System.out.println("request path:"+path);
            return restTemplate.getForObject(path,String.class);
        }

    }

    //实例化 RestTemplate 实例
    @Bean
    public RestTemplate restTemplate(){

        return new RestTemplate();
    }

    public static void main(String[] args) {

        SpringApplication.run(NacosConsumerApp.class,args);
    }
}

这个例子中我们注入了一个 LoadBalancerClient 的实例,并且手动的实例化一个 RestTemplate,同时将 spring.application.name 的配置值 注入到应用中来, 目的是调用 Provider 提供的服务时,希望将当前配置的应用名给显示出来。

[Note]Note

在启动 Consumer 应用之前请先将 Nacos 服务启动好。具体启动方式可参考 Nacos 官网

启动后,访问 Consumer 提供出来的 http://ip:port/echo/app-name 接口。我这里测试启动的 port是 8082。访问结果如下所示:

访问地址:http://127.0.0.1:8082/echo/app-name
访问结果:Hello Nacos Discovery nacos-consumer

13.4 关于 Nacos Starter 更多的配置项信息

更多关于 spring-cloud-starter-alibaba-nacos-discovery 的 starter 配置项如下所示:

配置项Key默认值说明

服务端地址

spring.cloud.nacos.discovery.server-addr

Nacos Server 启动监听的ip地址和端口

服务名

spring.cloud.nacos.discovery.service

${spring.application.name}

给当前的服务命名

权重

spring.cloud.nacos.discovery.weight

1

取值范围 1 到 100,数值越大,权重越大

网卡名

spring.cloud.nacos.discovery.network-interface

当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址

注册的IP地址

spring.cloud.nacos.discovery.ip

优先级最高

注册的端口

spring.cloud.nacos.discovery.port

-1

默认情况下不用配置,会自动探测

命名空间

spring.cloud.nacos.discovery.namespace

常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

AccessKey

spring.cloud.nacos.discovery.access-key

当要上阿里云时,阿里云上面的一个云账号名

SecretKey

spring.cloud.nacos.discovery.secret-key

当要上阿里云时,阿里云上面的一个云账号密码

Metadata

spring.cloud.nacos.discovery.metadata

使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息

日志文件名

spring.cloud.nacos.discovery.log-name

 

接入点

spring.cloud.nacos.discovery.enpoint

UTF-8

地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址

是否集成Ribbon

ribbon.nacos.enabled

true

一般都设置成true即可

Part X. Nacos FAQ

Table of Contents

14. Nacos常见FAQ

14. Nacos常见FAQ