一、Nacos简介

1.1、为什么叫Nacos?

前四个字母分别为Naming和Configuration的前两个字母,最后的s为Service。

1.2、是什么?

一个更易于构建云原生应用的动态服务发现,配置管理和服务管理中心

Nacos就是注册中心+配置中心的组合

1.3、能干嘛?

替代Eureka做服务注册中心

替代Config做微服务配置中心

二、安装并运行Nacos

进入Nacos的官网下载,地址:http://nacos.io

  • 启动,打开nacos/bin,windows环境下点击startup.cmd启动nacos

image-20210215154741130

  • 启动后访问localhost:8848/nacos启动nacos

image-20210215154854073

image-20210215154937350

  • 登录后页面如下

image-20210215155000197

三、Nacos作为服务注册中心演示

3.1、创建基于Nacos的服务提供者

1、新建Module

新建cloudalibaba-provider-payment9001

2、引入依赖

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
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<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.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>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>

3、编写yml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'

4、主启动类

在需要注册入注册中心的模块主启动类上添加@EnableDiscoveryClient注解

1
2
3
4
5
6
7
8
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class,args);
System.out.println("http://localhost:8848/nacos");
}
}

5、业务类

1
2
3
4
5
6
7
8
9
10
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;

@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id) {
return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}
}

6、启动9001微服务,查看nacos控制台

image-20210215161605817

7、仿照9001创建9002微服务,启动查看结果

image-20210215162714116

3.2、创建基于Nacos的服务消费者

1、新建Module

新建cloudalibaba-consumer-nacos-order83

2、引入依赖

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
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.cloudstudy</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<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.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>
</dependency>
</dependencies>

为什么Nacos支持负载均衡?

image-20210215164039536

3、编写yml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 消费者要访问的服务提供者。
service-url:
nacos-user-service: http://nacos-payment-provider

4、主启动类

1
2
3
4
5
6
7
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}

5、业务类

OrderNacosController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@Slf4j
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;

@Value("${service-url.nacos-user-service}")
private String serverURL;

@GetMapping(value = "/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Long id) {
return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
}

}

ApplicationContextConfig

1
2
3
4
5
6
7
8
@Configuration
public class ApplicationContextConfig{
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}

6、启动83微服务,查看nacos控制台

image-20210215165716365

7、使用83消费者调用服务提供方

访问http://localhost:83/consumer/payment/nacos/13

  • 第一次

image-20210215165922630

  • 第二次

image-20210215165950241

这样就实现了负载均衡和远程调用

3.3、各种服务注册中心对比

1、Nacos全景图

img

2、Nacos和CAP

image-20210215171729262

四、Nacos作为服务配置中心演示

4.1、Nacos作为配置中心–基础配置

1、新建Module

创建微服务模块:cloudalibaba-config-nacos-client3377

2、引入依赖

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
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</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-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

3、编写yml配置文件

bootstrap.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# nacos配置
server:
port: 3377

spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
# Nacos服务注册中心地址
server-addr: localhost:8848
# 指定Nacos配置中心的地址
config:
server-addr: localhost:8848
file-extension: yaml # 指定yaml格式的配置

application.yml

1
2
3
4
spring:
profiles:
# 表示开发环境
active: dev

为何编写两个配置文件?

Nacos同Spring Cloud Config一致,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置后,才能保证项目的正常启动。

Spring Boot中配置文件的加载是存在优先级顺序的,bootstrap(全局)优先级高于application(自定义)

4、主启动类

1
2
3
4
5
6
7
8
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientMain3377
{
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class, args);
}
}

5、业务类

@RefreshScope注解用于动态刷新,作用在Controller层

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;


@RestController
@RefreshScope
public class ConfigClientController
{
@Value("${config.info}")
private String configInfo;

@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}

6、Nacos的配置规则

  • 理论:Nacos中的dataid的组成格式与SpringBoot配置文件中的匹配规则

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

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

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

最后公式为:

1
${spring.application.name}-${spring.profile.active}.${file-extension}

根据上面的公式,我们可以得到cloudalibaba-config-nacos-client3377微服务配置的dataId为:nacos-config-client-dev.yaml

7、实操

在nacos控制台中选择配置管理-配置列表,点击“+”号添加配置

image-20210215203231682

添加的配置如下:

image-20210215203636355

8、测试

运行cloudalibaba-config-nacos-client3377微服务,调用接口查看配置信息,接口地址为:http://localhost:3377/config/info

  • 结果

image-20210215205027075

9、配置的动态刷新

修改下Nacos中的yaml配置文件,再次调用查看配置的端口,就会发现配置已经刷新。

image-20210215210048752

重新调用查看配置的接口,查看配置

image-20210215210140349

4.2、Nacos作为配置中心–分类配置

1、问题一

实际开发中,通常一个系统会准备

  • dev开发环境
  • test测试环境
  • prod生产环境

如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?

2、问题二

一个大型分布式微服务系统会有很多个微服务子项目

每个微服务又有对应的开发环境、预发环境、测试环境、正式环境…

那么又怎么对这些配置进行处理呢?

3、什么是分类配置?

类似Java中的package + 类名

最外层的namespace用于区别部署环境,Group和DataId从逻辑上区分两个对象

image-20210215212745121

默认情况下

  • Namespace=public
  • Group=DEFAULT_GROUP

Nacos默认的命名空间为public,Namespace主要用来隔离,比如说我们有三个(生产、开发、测试)环境,那么我们就可以创建三个Namespace,不同的Namespace之间是隔离的。

Group默认是DEFAULT_GROUP,Group可以把不同微服务划分到一个分组中。

Service就是微服务,一个Service可以包括多个Cluster(集群),Nacos默认Cluster是Default,Cluster是对指定微服务的一个虚拟划分。

比如说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,这个时候给杭州机房的Service微服务起一个集群名称(HZ),给广州计方的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房中的微服务相互调用,提升性能。

Instance:微服务实例

4、通过DataId读取不同配置

默认空间+默认分组+新建dev和test两个DataId

image-20210215233719100

  • 修改3377微服务的application.yml配置文件,指定记载环境
1
2
3
4
5
6
spring:
profiles:
# 配置什么环境就加载什么配置
active: test
# 表示开发环境
# active: dev

此时读取的配置的DataId为 nacos-config-client-test.yaml ,配置为

image-20210215234528455

  • 结果

image-20210215234506773

5、通过Group读取不同配置

新建一个开发组DEV_GROUP

image-20210215235657328

新建一个测试组TEST_GROUP

image-20210216000114864

此时配置列表如下,两个不同组有相同DataId的配置

image-20210216000529294

在bootstrap.yml配置文件中添加一条配置,指定要加载的配置组

1
2
3
4
5
6
spring:
cloud:
nacos:
config:
# 配置哪个组就加载哪个组
group: TEST_GROUP

同时修改application.yml配置文件中启动的环境

1
2
3
4
5
6
spring:
profiles:
# 配置什么环境就加载什么配置
active: info
# 表示开发环境
# active: dev

重启3377,访问http://localhost:3377/config/info ,结果如下

image-20210216001128542

修改bootstrap.yml配置文件,重启

1
2
3
4
5
6
spring:
cloud:
nacos:
config:
# 配置哪个组就加载哪个组
group: DEV_GROUP

结果为:

image-20210216001326298

6、通过Namespace读取不同配置

默认的namespace不能删除,新建DEV/TEST命名空间

image-20210216001648259

image-20210216001734240

image-20210216002033214

切换到dev namespace,新建三个分组,分组中配置DataId一致。

image-20210216002615825

切换namespace,在bootstrap.yml配置文件中添加如下配置,同时修改application.yml中配置环境为dev:

1
2
3
4
5
spring:
cloud:
nacos:
config:
namespace: a9ec0b1e-e254-4b99-84ec-fa4ca62bf5a6
  • 结果

image-20210216003211534

五、Nacos集群和持久化配置(重要)

5.1、官网说明

1、官网文档

https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

2、官网架构图

VIP:virtual IP,虚拟IP,也就是nginx

img

3、根据官网翻译,我们可得以下架构图

未命名文件 (1)

4、说明

按照上面的架构图,我们需要Mysql数据库;

默认Nacos使用嵌入式数据库实现了数据的存储。所以,如果启动多个默认配置的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式支持集群体部署,目前只支持MySQL的存储。

5.2、Nacos持久化配置解释

1、Nacos自带了嵌入式数据库

Nacos默认自带嵌入式数据库derby,打开Nacos的依赖坐标:https://github.com/alibaba/nacos/blob/develop/config/pom.xml

image-20210216114401758

但当我们做Nacos集群时,每个Nacos都各自带着一个derby嵌入式数据库,此时会出现持久化数据不一致的问题,此时我们引入外部的MySQL数据库,将配置数据持久化到MySQL中。

2、derby到MySQL切换配置步骤

nacos-server-1.1.4\nacos\conf目录下找到并执行 nacos-mysql.sql 脚本

image-20210216115406872

nacos-server-1.1.4\nacos\conf目录下找到application.properties,增加支持mysql数据源配置,添加mysql数据库的url、用户名和密码

注:nacos默认不支持mysql8.0,如需支持8.0,需要下载mysql8.0驱动进行更换。

1
2
3
4
5
6
7
# 将持久化配置从derby迁移到mysql配置
spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?&connectTimeout=10000&socketTimeout=30000&serverTimezone=GMT%2B8
db.user=root
db.password=tianxin1230.

重启Nacos,可以看到是个全新的空记录页面