Nacos 入门教程 - 配置管理基础篇

配置中心介绍

什么是配置中心

在集中式开发时代,配置文件已经基本足够了,因为那时配置的管理通常不会成为一个很大的问题。但是在互联网时代,应用都是分布式系统,部署在 N 台服务器上,想要去线上一台台地重启机器肯定不靠谱,并且维护成本也很高,所以配置中心应运而生。配置中心被用作集中管理不同环境(Dev、Test、Stage、Prod)和不同集群配置,以及在修改配置后将实时动态推送到应用上进行刷新。配置中心应具备的功能如下:

  • Open API
  • 业务无关性
  • 高可用集群
  • 配置生效监控
  • 配合灰度与更新
  • 一致性 K-V 存储
  • 统一配置实时推送
  • 配置全局恢复、备份与历史

主流配置中心对比

  • Spring Cloud Config、Netflix Archaius、Apollo、Disconf(已停止维护) 对比图一
  • Spring Cloud Config、Netflix Archaius、Apollo、Disconf(已停止维护) 对比图二

config-server-vs-4

Nacos 简介

Nacos 概述

Nacos 是构建以 “服务” 为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施,可以更敏捷和容易地构建、交付和管理微服务平台。Nacos 提供了一组简单易用的特性集,致力于快速实现动态服务发现、服务配置、服务元数据及流量管理。更多资料可参考:Nacos 项目Nacos 官网Nacos 官方中文文档Nacos 官方示例代码Nacos 官方博客

Nacos 功能

动态配置服务

动态配置服务能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。

服务发现与服务健康监测

动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos 支持 DNS-Based 和 RPC-Based(Dubbo、gRPC) 模式的服务发现。Nacos 也提供实时健康检查,以防止将请求发往不健康的主机或服务实例。借助 Nacos,可以更容易地为服务实现断路器。

动态 DNS 服务

通过支持权重路由,动态 DNS 服务能够轻松实现中间层负载均衡、更灵活的路由策略、流量控制以及简单数据中心内网的简单 DNS 解析服务。动态 DNS 服务还能更容易地实现以 DNS 协议为基础的服务发现,以消除耦合到厂商私有服务发现 API 上的风险。

服务及其元数据管理

Nacos 能从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。

Nacos 特性

易于使用

  • 动态配置管理、服务发现和动态的一站式解决方案
  • 20 多种开箱即用的以服务为中心的架构特性
  • 基本符合生产要求的轻量级易用控制台

生产等级

  • 脱胎于历经阿里巴巴 10 年生产验证的内部产品
  • 支持具有数百万服务的大规模场景
  • 具备企业级 SLA 的开源产品

更适应云架构

  • 无缝支持 Kubernetes 和 Spring Cloud
  • 在主流公共云上更容易部署和运行(例如阿里云和 AWS)
  • 多租户和多环境支持

丰富的应用场景

  • 支持限流、大促销预案和异地多活
  • 直接支持或稍作扩展即可支持大量有用的互联网应用场景
  • 流量调度和服务治理

Nacos 生态图

如 Nacos 生态图所示,Nacos 无缝支持一些主流的开源生态,包括 Spring Cloud、Apache Dubbo、Dubbo Mesh、gRPC、Kubernetes 、CNCF 等。

spring-cloud-alibaba-ecology

Nacos 安装

安装 Nacos

安装环境准备

Nacos 依赖 Java 环境运行,因此需要提前安装并配置 JDK,如果是从源码开始构建并运行 Nacos,还需要为此配置 Maven 环境,Nacos 依赖的软件环境如下:

  • 64 Bit OS,支持 Unix/Linux/Mac/Windows
  • 64 Bit JDK 1.8+
  • Maven 3.2.x+
  • Nacos 1.4.0

通过源码编译安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 拉取源码
$ git clone git@github.com:alibaba/nacos.git

# 进入源码目录
$ cd nacos

# 编译打包
$ mvn -Prelease-nacos clean install -U

# 或者指定编译时跳过测试
$ mvn -Prelease-nacos clean install -U -f pom.xml -Dmaven.test.skip=true

# 进入编译后的bin目录
$ cd distribution/target/nacos-server-1.4.0/nacos/bin

# 单机模式下启动Nacos服务,默认端口为8848,默认使用内置数据源
$ sh startup.sh -m standalone

# 查看Nacos的进程状态
$ ps -aux|grep nacos

# 查看Nacos的端口状态
$ netstat -anp|grep 8848

# 关闭Nacos服务
$ sh shutdown.sh

# 提示: Nacos启动的日志文件路径为: nacos/distribution/target/nacos-server-1.4.0/nacos/logs/start.out

通过下载二进制包安装

Nacos 下载地址点这里,下载后解压即可运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 解压
$ tar -xvf nacos-server-1.4.0.tar.gz

# 进入bin目录
$ cd nacos/bin

# 单机模式下启动Nacos服务,默认端口为8848,默认使用内置数据源
$ sh startup.sh -m standalone

# 查看Nacos的进程状态
$ ps -aux|grep nacos

# 查看Nacos的端口状态
$ netstat -anp|grep 8848

# 关闭Nacos服务
$ sh shutdown.sh

# 提示: Nacos启动的日志文件路径为: nacos/logs/start.out

访问 Nacos 的 Web 控制台

浏览器访问 http://127.0.0.1:8848/nacos,默认登录的用户名和密码为 nacos/nacos

nacos-server-web-ui

Open API 配置管理测试

Nacos 启动成功后,可通过 Nacos 提供的 HTTP API 验证 Nacos 服务运行是否正常。

1
2
3
# 新增配置信息到Nacos
$ curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
true

刷新 Nacos 的 Web 控制台,可以看到刚新增的配置信息如下:

nacos-add-config

1
2
3
# 从Nacos获取配置信息
$ curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
HelloWorld

外部 MySQL 数据库支持(持久化配置)

单机模式下 Nacos 默认使用嵌入式数据库 derby 来存储数据,若想使用外部 MySQL 数据库存储 Nacos 的数据,需要进行以下操作:

  • 安装 MySQL 5.6.5+
  • 下载 Nacos Server 的二进制安装包并解压
  • 创建数据库 nacos_config,执行 SQL 初始化脚本,数据库初始化脚本的路径为:${nacos-home}/conf/nacos-mysql.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 创建数据库
mysql> create database nacos_config default character set utf8;

# 切换数据库
mysql> use nacos_config;

# 执行SQL初始化脚本
mysql> source ${nacos-home}/conf/nacos-mysql.sql;

# 查看数据库表
mysql> show tables;
+------------------------+
| Tables_in_nacos_config |
+------------------------+
| config_info |
| config_info_aggr |
| config_info_beta |
| config_info_tag |
| config_tags_relation |
| group_capacity |
| his_config_info |
| permissions |
| roles |
| tenant_capacity |
| tenant_info |
| users |
+------------------------+
12 rows in set (0.00 sec)
  • 修改 ${nacos-home}/conf/application.properties 配置文件,增加支持 MySQL 数据源的配置信息(目前只支持 MySQL),并添加 MySQL 数据库的 URL、用户名、密码,最后重新启动 Nacos 服务即可,配置示例如下:
1
2
3
4
5
6
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=123456
  • 若希望使用 Nacos Server 内置的数据源(嵌入式数据库),可以使用 -p embedded 参数来启动 Nacos Server
1
sh startup.sh -p embedded

Nacos 配置入门案例

第一步:点击新增配置按钮

浏览器访问 http://127.0.0.1:8848/nacos,打开 Nacos 的 Web 控制台,并找到菜单 配置管理 > 配置列表,然后点击 新增 按钮:

![nas-web-click-add-button](../../../asset/2020/12/nas-web-click-add-button.png)

第二步:新增配置信息

在新增配置信息的表单里,填写如下的内容,然后点击 发布 按钮即可。特别注意的是,DataId 默认是以 properties 作为默认的文件扩展名。

nacos-web-add-config

第三步:查询配置信息

nacos-web-select-config

第四步:调用 Java API 获取 Nacos 的配置信息

1
2
3
4
5
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;

import java.util.Properties;

/**
* 从Nacos读取配置信息
* @author clay
*/
public class NacosDemoApplicaton {

public static void main(String[] args) throws NacosException {
String serverAddr = "127.0.0.1:8848";
String dataId = "nacos_simple_demo.yaml";
String group = "DEFAULT_GROUP";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 1000);
System.out.println(content);
}
}

程序运行输出结果如下:

1
2
common:
config: something

Nacos 配置管理基础

Nacos 配置管理模型

Nacos 配置管理概念

对于 Nacos 的配置管理,是通过 Namespace、Group、Data ID 来定位到一个配置集。

nacos-data-model

配置项

配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形式存在。例如经常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

配置集(Data ID)

在系统中,一个配置文件通常就是一个配置集,一个配置集可以包含了系统的各种配置信息,例如一个配置集可能包含了数据源、线程池、日志级别等配置项。每个配置集都可以定义一个有意义的名称,就是配置集的 ID,即 Data ID。

配置分组(Group)

配置分组是对配置集进行分组,通过一个有意义的字符串(如 Buy 或 Trade )来表示,不同的配置分组下可以有相同的配置集(Data ID)。当在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP。配置分组的常见场景:可用于区分不同的项目或应用,例如:学生管理系统的配置集可以定义一个 Group 为:STUDENT_GROUP。

命名空间(Namespace)

命名空间可用于进行不同环境的配置隔离。例如可以隔离开发环境、测试环境和生产环境,因为它们的配置可能各不相同,或者是隔离不同的用户,不同的开发人员使用同一个 Nacos 管理各自的配置,可通过 Namespace 隔离。当在 Nacos 上创建一个配置时,如果未填写命名空间的名称,则命名空间的名称默认为 public。不同的命名空间下,可以存在相同名称的配置分组(Group) 或 配置集。

Nacos 配置管理最佳实践

Nacos 抽象定义了 Namespace、Group、Data ID 的概念,具体这几个概念代表什么,取决于把它们看成什么,这里推荐一种用法,如下图:

  • Namespace :代表不同环境,如开发、测试、生产环境
  • Group:代表某项目,如 XX 医疗项目、XX 电商项目、XX 校园项目
  • DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件

nacos-data-model-2

Namespace 与 Group 的其他最佳实践

除了上面介绍的一种最佳实践方法外,还可以为每个微服务创建自己的 namespace 进行隔离,然后利用 group 来区分 Dev、Beta、Prod 等环境。

Nacos 命名空间管理

Namespace 隔离设计

Namespace 的设计是 Nacos 基于此做多环境以及多租户(多个用户共同使用 Nacos)数据(配置和服务)隔离的。从一个租户 (用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的 Namespace,以此来实现多环境的隔离。例如可能有开发、测试和生产三个不同的环境,那么使用一套 Nacos 集群可以分别建以下三个不同的 Namespace,如下图所示:

nacos-namespace

从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 Namespace,每个租户(用户)的配置数据以及注册的服务数据都会归属到自己的 Namespace 下,以此来实现多租户间的数据隔离。例如超级管理员分配了三个租户(用户),分别为张三、李四和王五。分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名空间。如下图所示:

nacos-namespace-2

Nacos 创建命名空间

第一步:菜单栏选中命名空间,然后点击页面上的新建命名空间按钮

nacos-create-namespace

第二步:在表单内填写必要的命名空间信息,然后点击确定按钮提交

nacos-create-namespace-2

第三步:菜单栏选中配置管理 > 配置列表,可以通过 Tab 按钮切换到不同的命名空间,接着就可以在对应的命名空间下新增配置信息

nacos-create-namespace-3

代码示例

1
2
3
4
5
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.0</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;

import java.util.Properties;

/**
* 从Nacos读取特定命名空间下的配置信息
* @author clay
*/
public class NacosDemoApplicaton {

public static void main(String[] args) throws NacosException {
String serverAddr = "127.0.0.1:8848";
String namespace = "7ec71a71-6ee5-4f87-a387-0d29d9e8fe51";
String group = "DEFAULT_GROUP";
String dataId = "nacos_simple_demo.yaml";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("namespace", namespace);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 1000);
System.out.println(content);
}
}

Nacos 常见配置管理操作

配置集导出

勾选若干配置集,点击导出选中的配置按钮,即可自动下载一个压缩包,压缩包内包含了选中配置集所转换的配置文件。

nacos-export-configs

配置集导入

点击右上角的导入配置按钮,选择之前导出的配置文件压缩包,可以将压缩包内的文件恢复为 Nacos 配置集。

nacos-inport-configs

配置集克隆

勾选若干配置集,点击克隆按钮,可以将选中的配置集批量复制到指定的命名空间内。

nacos-clone-configs

nacos-clone-configs-2

历史版本

Nacos 通过提供配置版本管理及其一键回滚能力,帮助用户改错配置的时候能够快速回滚,降低微服务系统在配置管理上的可用性风险。

nacos-config-history

nacos-config-rollback

监听查询

Nacos 提供配置订阅者(即监听者)查询能力,同时提供客户端当前配置的 MD5 校验值,以便帮助用户更好的检查服务器的配置变更是否推送到 Nacos 客户端,其中 Nacos 客户端监听的示例代码如下:

nacos-listener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
* Nacos客户端监听服务器的配置信息是否变更
* @author clay
*/
public class NacosDemoApplicaton {

public static void main(String[] args) throws NacosException, IOException {
String serverAddr = "127.0.0.1:8848";
String group = "DEFAULT_GROUP";
String dataId = "nacos_simple_demo.yaml";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 1000);
System.out.println(content);

configService.addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
return null;
}

@Override
public void receiveConfigInfo(String configInfo) {
System.out.println(configInfo);
}
});
System.in.read();
}
}

登录管理

Nacos 支持简单的登录功能,默认用户名 / 密码为: nacos/nacos

生成密码

1
2
3
4
5
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.4.1</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
/**
* 由于采用BCrypt加密方法在每次生成密码时会加随机盐,因此生成的密码每次都可能不一样
* @author clay
*/
public class PasswordEncoderUtil {

public static void main(String[] args) {
String password = new BCryptPasswordEncoder().encode("123456");
System.out.println(password);
}
}

创建登录用户

当 Nacos 使用 MySQL 数据库存储数据时,可以使用以下 SQL 来创建新用户,其中密码就是上面通过 Java 代码生成的字符串。同理,若需要更改旧用户的登录密码,只需要通过 SQL 更新对应的数据库表数据即可,这里不再累述。

1
2
INSERT INTO users (username, password, enabled) VALUES ('admin','$2a$10$kCRcD31fYzYUhfvCSUqQ9u/IAKbq4yTWi1z3l6kTrKL5exGSNbSUK', TRUE);
INSERT INTO roles (username, role) VALUES ('admin', 'ROLE_ADMIN');

关闭登录功能

由于部分公司自己开发控制台,不希望被 Nacos 的安全 Filter 拦截。因此 Nacos 支持定制关闭登录功能,只需要找到配置文件 ${nacos-home}/conf/application.properties,替换以下内容即可,最后重启 Nacos 服务使更改生效。特别注意,以下更改只适合 Nacos 1.2.0 以下的版本。

1
2
3
4
5
6
spring.security.enabled=false
management.security=false
security.basic.enabled=false
nacos.security.ignore.urls=/**

# nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**

下篇 - Nacos 入门教程 - 配置管理(中级篇)