Nacos & Spring Cloud

1. 概念

Nacos这个名字是从Dynamic Naming and Configuration ServiceNaming & Configuration & Service部分首字母结合得来

Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理的平台,主要面向的是微服务化的平台系统,以便提供一系列简单易用的特性

Nacos支持以下系列特性:

  • 服务发现和服务健康监测:基于DNS协议和RPC实现了服务发现,并且提供对服务的实时健康检查
  • 动态配置服务:动态配置能够使得各个服务实时获取到自身最新的配置项,最大的优势是在毫秒级别内能够获取到最新的配置,并且服务无需重启即可应用,同时Nacos的DashBoard还提供了一系列服务配置相关的UI入口,比如配置版本变更,配置回滚等
  • 动态DNS服务:支持针对服务的权重配置,能够基于此实现负载均衡,另一方面可以进行流量控制等
  • 服务与元数据管理:能够获取和管理各个服务的状态,同时也能够获取和配置每个服务的元数据信息
  • ……

nacos_map

2. 引入

Nacos分为客户端和服务端,服务端充当了Nacos中心平台的角色,提供了上述所提到的重要特性,而客户端则是一个一个的服务,将自身服务注册至Nacos中或者从Nacos中心平台拉取对应属于自己服务的配置信息

目前Nacos最新版本为2.x,后续会逐步停止1.x版本的维护,因此目前使用主要是2.x版本为主

  • 服务端搭建:可参考Nacos官网进行安装,需要注意的是Nacos官网提到的服务端搭建主要是以本地环境为主

  • 客户端搭建:Nacos可以融合不同的生态,比如Spring, Spring Boot, Spring Cloud, Dubbo等等,可参照Nacos官网进行引入

3. 配置中心

Tips: 本文主要会采用Spring Cloud生态进行引入使用

a. 依赖

在成功启动Nacos服务端后,客户端中引入以下nacos-config依赖项

  • Maven
1
2
3
4
5
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${latest.version}</version>
</dependency>
  • Gradle
1
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:{version}'

Tips: 版本 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 版本

如果涉及到详细的版本对应关系,可以参考Nacos的版本说明

b. 客户端配置

完成以上依赖引入后,可前往application.yaml / bootstrap.properties文件中进行以下配置:

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

配置spring.cloud.nacos.config.server-addr是为了能够识别配置中心的地址,使其能够通过该地址获取有关该服务的动态配置项,而spring.application.name则表示服务的名称,实际上也是Nacos会从服务端获取对应配置的标识之一(即Nacos配置管理中的dataId组成的一部分字段)

c. 服务端创建配置

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

1
${prefix}-${spring.profiles.active}.${file-extension}

Tips: 当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}

  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置

  • spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档

  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置,目前只支持 propertiesyaml 类型


由上已知客户端配置的application.namenacosDemo,同时我们没有设置profiles.active属性,配置项为properties的格式,因此可通过以下两种方式创建属于该服务的配置项:

  • Nacos Open API
1
2
// 创建配置项
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacosDemo.properties&group=DEFAULT_GROUP&content=useLocalCache=false"
  • Nacos Dashboard

进入Nacos Dashboard后,前往ConfigManagement -> Configurations -> Create Configuration进行配置的创建,如下所示:

image-20231002120239609

d. 使用配置

在上述创建的nacosDemo项目中初始化一个endpoint用于直接获取配置项并返回,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
public class TestController {
@Value(value = "${useLocalCache:true}")
private String value;


@GetMapping("/test")
public String test() {
return value;
}
}

通过调用该接口可以实时获取useLocalCache的值为false

image-20231002121417864

如果Nacos中useLocalCache的值发生了变化,服务中的值也会实时刷新,其中实时刷新机制主要得益于Nacos支持了Spring Cloud原生的的@RefreshScope注解

4. 服务注册与发现

a. 依赖

客户端中引入以下nacos-discovery依赖项与open-feign依赖项

  • Maven
1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${latest.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • Gradle
1
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

b. 服务注册

Tips: 默认配置中服务发现和配置中心的地址都为127.0.0.1:8848

Nacos服务注册主要依赖spring.cloud.nacos.discovery.server-addr确定Nacos服务端的地址,无需额外配置项

在服务中加入以上配置项后,前往Application启动类中加入@EnableDiscoveryClient注解用于启用服务发现功能

启动服务后,通过Nacos Dashboard -> ServiceManagement -> Service List服务列表查看服务是否已经注册成功,如下所示

image-20231002212754835

c. 服务发现

服务发现依赖的是Spring Cloudopen-feign组件,在使用@FeignClient注解进行标识的同时,直接标识serviceName:port作为对应Feign的名称即可由Nacos实现默认的服务发现与调用

对应nacosDemo服务部署在8080端口,endpoint代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RestController
public class TestController {
private NacosDemoClient nacosDemoClient;

public TestController(NacosDemoClient nacosDemoClient) {
this.nacosDemoClient = nacosDemoClient;
}

@GetMapping("/test")
public String test() {
return nacosDemoClient.ask();
}


@FeignClient(value = "nacosDemo1:8081")
public interface NacosDemoClient {
@GetMapping("/ask")
String ask();
}
}

nacosDemo1服务部署在8081端口,endpoint代码如下所示:

1
2
3
4
5
6
7
@RestController
public class TestController {
@GetMapping("/ask")
public String ask() {
return "Hello, this message is answer by nacos-demo-1 project.";
}
}

以上,通过访问nacosDemo服务的8080端口请求/test接口,即可调用nacosDemo1的API实现服务发现

5. 相关链接