目前 Spring-Cloud-Alibaba 已经被 Spring.Io 所推荐,对于我们开发者来说 Alibaba 的几大微服务中间件是必须要学习的这样才能提升。Aibaba 近几年开源了非常多中间件如:Nacos, Sentinel , RocketMQ, Seata, Dubbo 等。

今天我们就来一起学习下 Nacos 这个高性能、分布式服务发现注册中心中间件,而且它可以支持服务配置可以替代 Spring-Cloud 1.x 中的 Netflix Eureka + Spring Cloud Config 的一个组合, 并且支持 Spring-Cloud 2.x。本文为本人 Nacos 首篇文章主要为打架介绍 Nacos 的核心技术架构和一些名词以及基本使用。

在文章开始之前我还是先说明一下我的环境信息:​​Jdk 1.8​​​、​​nacos-1.4.2​​​、​​Spring-Cloud-Alibaba 2.2.5​​。

由于本篇为基础篇,为了更好的还原 Nacos 的核心概念和基础,本文部分素材来源于 Nacos 官方手册(参考文档部分包含所有参考信息原文入口)。

Nacos 是什么

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

核心目标

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

核心功能

  1. 动态配置服务, 动态配置服务让您能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。
  2. 服务发现及管理,动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos支持DNS-Based和RPC-Based(Dubbo、gRPC)模式的服务发现。Nacos也提供实时健康检查,以防止将请求发往不健康的主机或服务实例。借助Nacos,您可以更容易地为您的服务实现断路器。
  3. 动态DNS服务, 通过支持权重路由,动态DNS服务能让您轻松实现中间层负载均衡、更灵活的路由策略、流量控制以及简单数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以DNS协议为基础的服务发现,以消除耦合到厂商私有服务发现API上的风险。

Nacos 技术生态

Nacos 快速入门_spring

如 Nacos 全景图所示,Nacos 无缝支持一些主流的开源生态,例如

使用 Nacos 简化服务发现、配置管理、服务治理及管理的解决方案,让微服务的发现、管理、共享、组合更加容易。

Nacos 架构介绍

基本架构及概念

Nacos 快速入门_服务发现_02

服务 (Service)

服务是指一个或一组软件功能(例如特定信息的检索或一组操作的执行),其目的是不同的客户端可以为不同的目的重用(例如通过跨进程的网络调用)。Nacos 支持主流的服务生态,如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service.

服务注册中心 (Service Registry)

服务注册中心,它是服务,其实例及元数据的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求。

服务元数据 (Service Metadata)

服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由规则、安全策略等描述服务的数据

服务提供方 (Service Provider)

是指提供可复用和可调用服务的应用方

服务消费方 (Service Consumer)

是指会发起对某个服务调用的应用方

配置 (Configuration)

在系统开发过程中通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成这个步骤。配置变更是调整系统运行时的行为的有效手段之一。

配置管理 (Configuration Management)

在数据中心中,系统中所有配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等所有与配置相关的活动统称为配置管理。

名字服务 (Naming Service)

提供分布式系统中所有对象(Object)、实体(Entity)的“名字”到关联的元数据之间的映射管理服务,例如 ServiceName -> Endpoints Info, Distributed Lock Name -> Lock Owner/Status Info, DNS Domain Name -> IP List, 服务发现和 DNS 就是名字服务的2大场景。

配置服务 (Configuration Service)

在服务或者应用运行过程中,提供动态配置或者元数据以及配置管理的服务提供者。

逻辑架构及其组件介绍

Nacos 快速入门_spring_03

  • 服务管理:实现服务CRUD,域名CRUD,服务健康状态检查,服务权重管理等功能
  • 配置管理:实现配置管CRUD,版本管理,灰度管理,监听管理,推送轨迹,聚合数据等功能
  • 元数据管理:提供元数据CURD 和打标能力
  • 插件机制:实现三个模块可分可合能力,实现扩展点SPI机制
  • 事件机制:实现异步化事件通知,sdk数据变化异步通知等逻辑
  • 日志模块:管理日志分类,日志级别,日志可移植性(尤其避免冲突),日志格式,异常码+帮助文档
  • 回调机制:sdk通知数据,通过统一的模式回调用户处理。接口和数据结构需要具备可扩展性
  • 寻址模式:解决ip,域名,nameserver、广播等多种寻址模式,需要可扩展
  • 推送通道:解决server与存储、server间、server与sdk间推送性能问题
  • 容量管理:管理每个租户,分组下的容量,防止存储被写爆,影响服务可用性
  • 流量管理:按照租户,分组等多个维度对请求频率,长链接个数,报文大小,请求流控进行控制
  • 缓存机制:容灾目录,本地缓存,server缓存机制。容灾目录使用需要工具
  • 启动模式:按照单机模式,配置模式,服务模式,dns模式,或者all模式,启动不同的程序+UI
  • 一致性协议:解决不同数据,不同一致性要求情况下,不同一致性机制
  • 存储模块:解决数据持久化、非持久化存储,解决数据分片问题
  • Nameserver:解决namespace到clusterid的路由问题,解决用户环境与nacos物理环境映射问题
  • CMDB:解决元数据存储,与三方cmdb系统对接问题,解决应用,人,资源关系
  • Metrics:暴露标准metrics数据,方便与三方监控系统打通
  • Trace:暴露标准trace,方便与SLA系统打通,日志白平化,推送轨迹等能力,并且可以和计量计费系统打通
  • 接入管理:相当于阿里云开通服务,分配身份、容量、权限过程
  • 用户管理:解决用户管理,登录,sso等问题
  • 权限管理:解决身份识别,访问控制,角色管理等问题
  • 审计系统:扩展接口方便与不同公司审计系统打通
  • 通知系统:核心数据变更,或者操作,方便通过SMS系统打通,通知到对应人数据变更
  • OpenAPI:暴露标准Rest风格HTTP接口,简单易用,方便多语言集成
  • Console:易用控制台,做服务管理、配置管理等操作
  • SDK:多语言sdk
  • Agent:dns-f类似模式,或者与mesh等方案集成
  • CLI:命令行对产品进行轻量化管理,像git一样好用

Nacos 安装过程

这个快速开始手册是帮忙您快速在您的电脑上,下载、安装并使用 Nacos。

0.版本选择

我们可以在Nacos的​​release notes​​​及​​官方博客​​中找到每个版本支持的功能的介绍,当前官方推荐的稳定版本为1.4.2或2.0.1。

1.预备环境准备

Nacos 依赖 ​​Java​​​ 环境来运行。如果从代码开始构建并运行Nacos,还需要为此配置 ​​Maven​​环境,确保是在以下版本环境中安装使用:

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
  2. 64 bit JDK 1.8+;​​下载​​​ &​​配置​​。
  3. Maven 3.2.x+;​​下载​​​ &​​配置​​。

2.下载源码或者安装包

你可以通过源码和发行包两种方式来获取 Nacos。

从 Github 上下载源码方式

git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U
ls -al distribution/target/

// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin

下载编译后压缩包方式

您可以从 ​​最新稳定版本​​​ 下载 ​​nacos-server-$version.zip​​ 包。

unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin

3.启动服务器

Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式):

sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone

Windows

启动命令(standalone代表着单机模式运行,非集群模式):

startup.cmd -m standalone

4.服务注册&发现和配置管理

服务注册

curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

服务发现

curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'

发布配置

curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"

获取配置

curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

5.关闭服务器

Linux/Unix/Mac

sh shutdown.sh

Windows

shutdown.cmd

或者双击shutdown.cmd运行文件。

Nacos 在 Spring Cloud 微服务中的使用

本文主要面向 ​​Spring Cloud​​ 的使用者,通过两个示例来介绍如何使用 Nacos 来实现分布式环境下的配置管理和服务注册发现。

关于 Nacos Spring Cloud 的详细文档请参看:​​Nacos Config​​​ 和 ​​Nacos Discovery​​。

  • 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更。
  • 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。

前提条件

您需要先下载 Nacos 并启动 Nacos server。操作步骤参见 ​​Nacos 快速入门​

启动配置管理

启动了 Nacos server 后,您就可以参考以下示例代码,为您的 Spring Cloud 应用启动 Nacos 配置管理服务了。完整示例代码请参考:​​nacos-spring-cloud-config-example​

  1. 添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${latest.version}</version>
</dependency>

注意:版本 ​​2.1.x.RELEASE​​​ 对应的是 Spring Boot 2.1.x 版本。版本 ​​2.0.x.RELEASE​​​ 对应的是 Spring Boot 2.0.x 版本,版本 ​​1.5.x.RELEASE​​ 对应的是 Spring Boot 1.5.x 版本。

更多版本对应关系参考:​​版本说明 Wiki​

  1. 在​​bootstrap.properties​​ 中配置 Nacos server 的地址和应用名
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.application.name=example

说明:之所以需要配置 ​​spring.application.name​​​ ,是因为它是构成 Nacos 配置管理 ​​dataId​​字段的一部分。

在 Nacos Spring Cloud 中,​​dataId​​ 的完整格式如下:

${prefix}-${spring.profiles.active}.${file-extension}
  • ​prefix​​​ 默认为​​spring.application.name​​​ 的值,也可以通过配置项​​spring.cloud.nacos.config.prefix​​来配置。
  • ​spring.profiles.active​​​ 即为当前环境对应的 profile,详情可以参考​​Spring Boot文档​​。注意:当 spring.profiles.active 为空时,对应的连接符 ​-​ 也将不存在,dataId 的拼接格式变成 ​${prefix}.${file-extension}​
  • ​file-exetension​​​ 为配置内容的数据格式,可以通过配置项​​spring.cloud.nacos.config.file-extension​​​ 来配置。目前只支持​​properties​​​ 和​​yaml​​ 类型。
  1. 通过 Spring Cloud 原生注解​​@RefreshScope​​ 实现配置自动更新:
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {

@Value("${useLocalCache:false}")
private boolean useLocalCache;

@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
  1. 首先通过调用​​Nacos Open API​​​ 向 Nacos Server 发布配置:dataId 为​​example.properties​​​,内容为​​useLocalCache=true​
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example.properties&group=DEFAULT_GROUP&content=useLocalCache=true"
  1. 运行​​NacosConfigApplication​​​,调用​​curl http://localhost:8080/config/get​​​,返回内容是​​true​​。
  2. 再次调用​​Nacos Open API​​​ 向 Nacos server 发布配置:dataId 为​​example.properties​​​,内容为​​useLocalCache=false​
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example.properties&group=DEFAULT_GROUP&content=useLocalCache=false"
  1. 再次访问​​http://localhost:8080/config/get​​​,此时返回内容为​​false​​​,说明程序中的​​useLocalCache​​值已经被动态更新了。

启动服务发现

本节通过实现一个简单的 ​​echo service​​ 演示如何在您的 Spring Cloud 项目中启用 Nacos 的服务发现功能,如下图示:

Nacos 快速入门_配置管理_04

完整示例代码请参考:​​nacos-spring-cloud-discovery-example​

  1. 添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${latest.version}</version>
</dependency>

注意:版本 ​​2.1.x.RELEASE​​​ 对应的是 Spring Boot 2.1.x 版本。版本 ​​2.0.x.RELEASE​​​ 对应的是 Spring Boot 2.0.x 版本,版本 ​​1.5.x.RELEASE​​ 对应的是 Spring Boot 1.5.x 版本。

更多版本对应关系参考:​​版本说明 Wiki​

  1. 配置服务提供者,从而服务提供者可以通过 Nacos 的服务注册发现功能将其服务注册到 Nacos server 上。

i. 在 ​​application.properties​​ 中配置 Nacos server 的地址:

server.port=8070
spring.application.name=service-provider

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

ii. 通过 Spring Cloud 原生注解 ​​@EnableDiscoveryClient​​ 开启服务注册发现功能:

@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {

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

@RestController
class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
}
}
  1. 配置服务消费者,从而服务消费者可以通过 Nacos 的服务注册发现功能从 Nacos server 上获取到它要调用的服务。

i. 在 ​​application.properties​​ 中配置 Nacos server 的地址:

server.port=8080
spring.application.name=service-consumer

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

ii. 通过 Spring Cloud 原生注解 ​​@EnableDiscoveryClient​​​ 开启服务注册发现功能。给 ​​RestTemplate​​​ 实例添加 ​​@LoadBalanced​​​ 注解,开启 ​​@LoadBalanced​​​ 与 ​​Ribbon​​ 的集成:

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApplication {

@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

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

@RestController
public class TestController {

private final RestTemplate restTemplate;

@Autowired
public TestController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}

@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
}
}
}
  1. 启动​​ProviderApplication​​​ 和​​ConsumerApplication​​​ ,调用​​http://localhost:8080/echo/2018​​​,返回内容为​​Hello Nacos Discovery 2018​​。

参考文档

​nacos.io/zh-cn/docs/…​