一、前言

Nacos 是一款集服务发现、服务健康监测、动态配置服务、动态 DNS 服务、服务及其元数据管理于一身的开源软件,这节主要记录Nacos的服务注册发现功能的使用。借助Spring Cloud Alibaba Nacos Discovery,我们可以轻松地使用Spring Cloud编程模型体验Nacos的服务注册发现功能。本节使用的Spring Cloud Alibaba版本为2.2.3.RELEASE,Spring Boot版本为2.3.2.RELEASE。

二、Nacos简介

官方参考文档

2.1 基本架构及概念

2.2 逻辑架构及其组件

  • 服务管理:实现服务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一样好用

2.3 构建物、部署及启动模式

两种交付工件

Nacos 支持标准 Docker 镜像(TODO: 0.2版本开始支持)及 zip(tar.gz)压缩包的构建物。

两种启动模式

Nacos 支持将注册中心(Service Registry)与配置中心(Config Center) 在一个进程合并部署或者将2者分离部署的两种模式。

免费的公有云服务模式

除了您自己部署和启动 Nacos 服务之外,在云计算时代,Nacos 也支持公有云模式,在阿里云公有云的商业产品(如ACM, EDAS) 中会提供 Nacos 的免费的公有云服务。也欢迎和支持其他的公有云提供商提供 Nacos 的公有云服务。

2.4 版本说明

官方文档参考

2.4.1 组件版本关系

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE1.8.01.3.34.4.02.7.81.3.0
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE1.7.11.2.14.4.02.7.61.2.0
2.2.0.RELEASE1.7.11.1.44.4.02.7.4.11.0.0
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE1.7.01.1.44.4.02.7.30.9.0
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE1.6.31.1.14.4.02.7.30.7.1

2.4.2 版本依赖关系

Spring Cloud VersionSpring Cloud Alibaba VersionSpring Boot Version
Spring Cloud Hoxton.SR82.2.3.RELEASE2.3.2.RELEASE
Spring Cloud Greenwich.SR62.1.3.RELEASE2.1.13.RELEASE
Spring Cloud Hoxton.SR82.2.2.RELEASE2.3.2.RELEASE
Spring Cloud Hoxton.SR32.2.1.RELEASE2.2.5.RELEASE
Spring Cloud Hoxton.RELEASE2.2.0.RELEASE2.2.X.RELEASE
Spring Cloud Greenwich2.1.2.RELEASE2.1.X.RELEASE
Spring Cloud Finchley2.0.2.RELEASE2.0.X.RELEASE
Spring Cloud Edgware1.5.1.RELEASE(停止维护,建议升级)1.5.X.RELEASE

三、Nacos安装

3.1 下载解压

Nacos下载地址: https://github.com/alibaba/nacos/releases ,选择最新版本 nacos-server-1.3.1.zip 下载并解压。

3.2 数据源配置

打开conf目录下的配置文件,在application.properties中添加数据源配置:

1
2
3
4
5
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacosdb?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=nacos
db.password=nacos123

3.3 数据导入

安装数据库,版本要求:5.6.5+,我的本地是5.7.23,创建数据库和用户:

1
2
3
4
5
6
    create database nacosdb default character set utf8 collate utf8_general_ci;
create user 'nacos'@'%' identified by 'nacos123';
create user 'nacos'@'localhost' identified by 'nacos123';
grant all privileges on nacosdb.* to 'nacos'@'%' identified by 'nacos123';
grant all privileges on nacosdb.* to 'nacos'@'localhost' identified by 'nacos123';
flush privileges;

导入Nacos解压包conf目录下的nacos-mysql.sql脚本,导入后,库表如下图所示:

3.4 启动测试

数据层准备好后,我们就可以启动Nacos了。本地使用windows10 64bit,直接点击bin目录下startup.cmd。linux环境下执行sh startup.sh -m standalone启动单机版Nacos。

注意:1.3.2版本在windows上启动,单机模式双击startup.cmd可能会报错,建议启动时候使用startup.cmd -m standalone这样启动

浏览器访问: http://127.0.0.1:8848/nacos

说明Nacos启动成功,账号密码都为nacos。

四、框架搭建

使用IDEA创建一个maven项目,artifactId为spring-cloud-alibaba-nacos-register,然后在其下面创建两个Module(Spring Boot项目),artifactId分别为consumer和provider,充当服务消费端和服务提供端,项目结构如下图所示:

spring-cloud-alibaba-nacos-register的pom内容:

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wno704</groupId>
<artifactId>spring-cloud-alibaba-nacos-register</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Alibaba-Nacos-Register</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>

<modules>
<module>consumer</module>
<module>provider</module>
</modules>

<properties>
<java.version>1.8</java.version>
<spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version>
</properties>

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

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

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

</project>

因为本节演示的是Nacos的服务注册发现功能,所以引入的是spring-cloud-alibaba-nacos-discovery依赖。

provider的pom的内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wno704</groupId>
<artifactId>spring-cloud-alibaba-nacos-register</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>provider</artifactId>
<name>Alibaba-Provider</name>
<description>Demo project for Spring Boot</description>

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

</project>

consumer的pom内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wno704</groupId>
<artifactId>spring-cloud-alibaba-nacos-register</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>consumer</artifactId>
<name>Alibaba-Consumer</name>
<description>Demo project for Spring Boot</description>

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

</project>

五、Nacos作为注册中心

5.1 provider

在provider的com.wno704.alibaba目录下新建controller包,然后在该包下新建HelloController:

1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("provide")
public class HelloController {

@GetMapping("{message}")
public String hello(@PathVariable String message) {
return String.format("hello %s", message);
}
}

提供了一个REST接口,供consumer调用。

然后在provider的项目配置文件application.yml里添加如下配置:

1
2
3
4
5
6
7
8
server:
port: 8900
spring:
application:
name: provider
cloud:
nacos:
server-addr: 127.0.0.1:8848

server.port,provider服务端口为8001;
spring.application.name,服务名称为provider
spring.cloud.nacos.server-addr,指定Nacos注册中心的地址。

5.2 consumer

provider代码准备好后,接着在consumer项目的com.wno704.alibaba目录下新建controller包,然后在该包下新建ConsumeController:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
@RequestMapping("consume")
public class ConsumeController {

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

@GetMapping("hello/{message}")
public String hello(@PathVariable String message) {
ServiceInstance serviceInstance = loadBalancerClient.choose("provider");
String path = String.format("http://%s:%s/provide/%s", serviceInstance.getHost(), serviceInstance.getPort(), message);
String result = restTemplate.getForObject(path, String.class);
return String.format("%s from %s %s", result, serviceInstance.getHost(), serviceInstance.getPort());
}
}

因为spring-cloud-alibaba-nacos-discovery内置了Ribbon,所以我们可以直接注入LoadBalancerClient,RestTemplate我们稍后再配置。hello()方法中我们通过服务提供者的名称provider(即provider项目配置的spring.application.name)从Nacos注册中心中获取对应的服务实例,然后访问其提供的/provide/{message} GET服务。这些在 《Spring Cloud Ribbon客户端负载均衡》 一节中都介绍过了,有不懂的可以参阅下。

接着在consumer项目的com.wno704.alibaba目录下新建config包,然后在该包下新建ConsumerConfig:

1
2
3
4
5
6
7
8
9
@Configuration
public class ConsumerConfig {

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

}

上面代码配置了RestTemplate Bean。

最后在consumer项目的配置文件application.yml中添加如下配置:

1
2
3
4
5
6
7
8
server:
port: 8901
spring:
application:
name: consumer
cloud:
nacos:
server-addr: 127.0.0.1:8848

配置和provider项目类似,不再赘述。

5.3 启动测试

分别启动provider和consumer项目:

观察Nacos控制台服务列表:

可以看到,两个服务都注册进来了。接着浏览器访问: http://localhost:8901/consume/hello/nacos

调用成功,说明服务发现成功。

六、负载均衡

我们启动多个provider服务

服务名启动参数端口
AlibabaProviderApplication-8905server.port=89058905
AlibabaProviderApplication-8906server.port=89058906
AlibabaProviderApplication-8907server.port=89058907

把原来启动AlibabaProviderApplication服务关掉,启动新建的三个服务:

观察Nacos控制台,可以看到provider已经有三个实例了:

然后多次访问: http://localhost:8901/consume/hello/nacos ,可以看到请求是均衡的(默认为轮询算法):

七、Nacos注册中心配置

更多可用Nacos Descovery配置:

配置项Key默认值说明
服务端地址spring.cloud.nacos.discovery.server-addrNacos Server 启动监听的ip地址和端口
服务名spring.cloud.nacos.discovery.service${spring.application.name}给当前的服务命名
服务分组spring.cloud.nacos.discovery.groupDEFAULT_GROUP设置服务所处的分组
权重spring.cloud.nacos.discovery.weight1取值范围 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常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产
环境的资源(如配置、服务)隔离等。
AccessKeyspring.cloud.nacos.discovery.access-key当要上阿里云时,阿里云上面的一个云账号名
SecretKeyspring.cloud.nacos.discovery.secret-key当要上阿里云时,阿里云上面的一个云账号密码
Metadataspring.cloud.nacos.discovery.metadata使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关
的元数据信息
日志文件名spring.cloud.nacos.discovery.log-name
集群spring.cloud.nacos.discovery.cluster-nameDEFAULT配置成Nacos集群名称
接入点spring.cloud.nacos.discovery.enpointUTF-8地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbonribbon.nacos.enabledtrue一般都设置成true即可
是否开启Nacos Watchspring.cloud.nacos.discovery.watch.enabledtrue可以设置成false来关闭 watch