第二章 SpringCloudAlibaba之Nacos笔记

一、Nacos服务注册与发现

1、Nacos简介

Nacos是阿里开源的易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

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

通俗来说,Nacos是一个注册中心& 配置中心 ——作为注册中心,Nacos可用于替代Spring Cloud中的Eureka、Spring Cloud Zookeeper Discovery、Spring Cloud Consul Discovery;作为配置中心,Nacos可用于替代Spring Cloud Config、Spring Cloud Zookeper Config、Spring Cloud Consul Config。

服务发现的领域模型:

TIPS:其实从Nacos命名的由来:Dynamic Naming and Configuration Service 即可顾名思义了。

1.1、Nacos服务端安装&启动

前往 https://github.com/alibaba/nacos/releases ,下载安装包并解压。

1.2、Nacos支持三种部署模式

  • 单机模式 - 用于测试和单机试用。
  • 集群模式 - 用于生产环境,确保高可用。
  • 多集群模式 - 用于多数据中心场景。

1.3、单机模式下运行Nacos

Linux/Unix/Mac启动Standalone means it is non-cluster Mode

启动命令:. * sh startup.sh -m standalone

Windows启动

根据您的操作系统,到 bin 目录执行cmd startup.cmd或者双击startup.cmd文件,即可启动Nacos。

启动后,访问 http://127.0.0.1:8848/nacos 即可看到登录界面。

输入账号密码:nacos/nacos ,即可登录Nacos,并看到类似如下界面:

特别注意:

linux环境默认启动的是集群模式,所以如果启动单机模式,一定要添加参数-m standalone

1.4、集群模式下运行Nacos

集群模式下运行Nacos

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

1)多集群模式

Nacos支持NameServer路由请求模式,通过它您可以设计一个有用的映射规则来控制请求转发到相应的集群,在映射规则中您可以按命名空间或租户等分片请求...

2)多网卡IP选择

当本地环境比较复杂的时候,Nacos服务在启动的时候需要选择运行时使用的IP或者网卡。Nacos从多网卡获取IP参考Spring Cloud设计,通过nacos.inetutils参数,可以指定Nacos使用的网卡和IP地址。目前支持的配置参数有:

ip-address参数可以直接设置nacos的ip

nacos.inetutils.ip-address=10.11.105.155

use-only-site-local-interfaces参数可以让nacos使用局域网ip,这个在nacos部署的机器有多网卡时很有用,可以让nacos选择局域网网卡

nacos.inetutils.use-only-site-local-interfaces=true

ignored-interfaces支持网卡数组,可以让nacos忽略多个网卡

nacos.inetutils.ignored-interfaces[0]=eth0

nacos.inetutils.ignored-interfaces[1]=eth1

preferred-networks参数可以让nacos优先选择匹配的ip,支持正则匹配和前缀匹配

nacos.inetutils.preferred-networks[0]=30.5.124.

nacos.inetutils.preferred-networks[0]=30.5.124.(25[0-5]|2[0-4]\\d|((1d{2})|([1-9]?\\d))),30.5.124.(2

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

服务注册

curl -X PUT '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/instances?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"

关闭服务器Linux/Unix/Mac

sh shutdown.sh

1.6、如何自定义Nacos默认的账号密码?

默认启动的Nacos,所使用的数据库是Derby。而Derby是一款内嵌式数据库,因此本文所搭建的Nacos显然是不适用生产的,生产环境中的数据库又改如何配置呢?

1)修改nacos\conf目录下面application.properties配置文件

### If user MySQL as datasource:

spring.datasource.platform=mysql

db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true

db.user=root

db.password=root

2)初始化数据库脚本

schema.sql、nacos-mysql.sql

如何搭建高可用集群?

2、使用Nacos实现服务注册与发现

1)新建项目springcloudalibaba-provider-user作为服务提供者

2)添加pom依赖:



org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-actuator


com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery






org.springframework.cloud
spring-cloud-dependencies

Greenwich.SR5
pom
import


com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.2.RELEASE
pom
import


3)添加配置application.properties

注意配置nacos注册中心地址:192.168.41.241:8848

server.port=8081
spring.application.name=springcloudalibaba-provider-user
spring.cloud.nacos.discovery.server-addr=192.168.41.241:8848
# Value range: 1 to 100. The bigger the value, the greater the weight
#spring.cloud.nacos.discovery.weight=1
# default value is ture
# ribbon.nacos.enabled=ture
management.endpoints.web.exposure.include=*

4)添加启动测试类ProviderUserApplication:

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderUserApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderUserApplication.class, args);
}
@RestController
public class EchoController {
@GetMapping(value = "/echo/{string}")
public String echo(@PathVariable String string) {
return "Hello Nacos Discovery " + string;
}
@GetMapping("/hello")
public String hello(@RequestParam(name = "name") String name){
return "Hello Nacos Discovery " + name;
}
}
}

5)启动测试:

访问http://192.168.41.241:8848/nacos/查看注册服务列表信息

3、支持的几种服务消费方式

Nocas支持RestTemplate、WebClient、Feign等几种服务通信方式

1)新建服务消费项目springcloudalibaba-consumer

2)添加pom依赖



org.springframework.boot
spring-boot-starter-web


org.springframework.cloud
spring-cloud-starter-netflix-ribbon
2.1.5.RELEASE


org.springframework.cloud
spring-cloud-starter-openfeign
2.1.5.RELEASE


com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery


com.alibaba.nacos
nacos-client




com.alibaba.nacos
nacos-client





org.springframework.cloud
spring-cloud-dependencies

Greenwich.SR5
pom
import


com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.2.RELEASE
pom
import


3)添加配置application.properties

server.port=8082
spring.application.name=springcloudalibaba-consumer
spring.cloud.nacos.discovery.server-addr=192.168.41.241:8848

4)编写启动测试类:

@SpringBootApplication
@EnableDiscoveryClient
public class NacosConsumerApp {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApp.class,args);
}
}

使用RestTemplate方式访问服务提供者

/**
* 使用RestTemplate
* http://192.168.41.241:8082/echo/app-name
* Hello Nacos Discovery springcloudalibaba-consumer
*/
@RestController
public class NacosController{
@Autowired
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@Value("${spring.application.name}")
private String appName;

@GetMapping("/echo/app-name")
public String echoAppName(){
//Access through the combination of LoadBalanceClient and RestTemplate
ServiceInstance serviceInstance = loadBalancerClient.choose("springcloudalibaba-provider-user");
String path = String.format("http://%s:%s/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
System.out.println("request path:" +path);
return restTemplate.getForObject(path,String.class);
}
//Instantiate RestTemplate Instance
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

访问地址:http://192.168.41.241:8082/echo/app-name

返回结果:Hello Nacos Discovery springcloudalibaba-consumer

使用Feign方式访问服务提供者

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class OpenfeignConsumerApp {
@RestController
static class TestController {
@Autowired
Client client;
@GetMapping("/test/feign")
public String test() {
String result = client.hello("test openfeign");
return "Return : " + result;
}
}
@FeignClient("springcloudalibaba-provider-user")
interface Client {
@GetMapping("/hello")
String hello(@RequestParam(name = "name") String name);
}
}

访问地址:http://192.168.41.241:8082//test/feign

返回结果:Return : Hello Nacos Discovery test openfeign

4Nacos元数据

4.1、什么是元数据?

Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。

级别:服务级别、集群级别、实例级别

4.2、元数据的作用?

提供描述信息

让微服务调用更加灵活(例如:微服务版本控制)

v1 --->v1

4.3、如何配置元数据

方式一:通过Nacos控制台方式配置

方式二:通过配置文件方式配置,如下所示:

cloud:
nacos:
discovery:
# 指定nacos server的地址
server-addr: localhost:8848
# 指定namespace
# namespace: 56116141-d837-4d15-8842-94e153bb6cfb
# NJ
# 指定集群名称
cluster-name: BJ
metadata:
instance: c
haha: hehe
version: v1

4、深入思考

如果之前已经用过Spring Cloud,肯定会这样的感受:不论我用的是RestTempalte也好、还是用的WebClient也好,还是用的Feign也好,似乎跟我用不用Nacos没啥关系?我们在之前介绍Eureka和Consul的时候,也都是用同样的方法来实现服务调用的,不是吗?

确实是这样,对于Spring Cloud老手来说,就算我们更换了Nacos作为新的服务注册中心,其实对于我们应用层面的代码是没有影响的。那么为什么Spring Cloud可以带给我们这样的完美编码体验呢?实际上,这完全归功于Spring Cloud Common的封装,由于在服务注册与发现、客户端负载均衡等方面都做了很好的抽象,而上层应用方面依赖的都是这些抽象接口,而非针对某个具体中间件的实现。所以,在Spring Cloud中,我们可以很方便的去切换服务治理方面的中间件。

二、使用Nacos作为配置中心

1、简介

Nacos除了实现了服务的注册发现之外,还将配置中心功能整合在了一起。通过Nacos的配置管理功能,我们可以将整个架构体系内的所有配置都集中在Nacos中存储。这样做的好处,在以往的教程中介绍Spring Cloud Config时也有提到,主要有以下几点:

  • 分离的多环境配置,可以更灵活的管理权限,安全性更高。
  • 应用程序的打包更为纯粹,以实现一次打包,多处运行的特点。
  • 配置动态刷新(可以在读取配置的类上面添加注解@RefreshScope来实现动态刷新)
  • 配置回滚(可以再历史版本里面查看到配置文件修改的记录,可以选择对应的版本回滚)。

Nacos的配置管理模型与淘宝开源的配置中心Diamond类似,基础层面都通过DataId和Group来定位配置内容,除此之外还增加了很多其他的管理功能。

2、创建应用

第一步:创建一个Spring Boot应用springcloud-nacos-config。

第二步:添加pom依赖





org.springframework.cloud
spring-cloud-dependencies

Greenwich.SR5
pom
import


com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.2.RELEASE
pom
import





org.springframework.boot
spring-boot-starter-web


com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config

第三步创建应用

@SpringBootApplication
public class NacosConfigApp {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApp.class, args);
}
@RestController
@RefreshScope // 配置内容支持动态刷新
static class TestController {
// 读取配置文件中的配置 didispace.title=spring-cloud-alibaba-learning
@Value("${didispace.title:}")
private String title;
@GetMapping("/test")
public String hello() {
return title;
}
}
}

注意:这里还有一个比较重要的注解@RefreshScope主要用来让这个类下的配置内容支持动态刷新,也就是当我们的应用启动之后,修改了Nacos中的配置内容之后,这里也会马上生效。

第四步:创建配置文件bootstrap.properties

server.port=8001
spring.application.name=springcloud-nacos-config
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

注意:这里必须使用bootstrap.properties。同时spring.application.name值必须与上一阶段Nacos中创建的配置Data Id匹配(除了.properties或者.yaml后缀)。

第五步:启动应用

日志打印会有如下信息

LOCAL_SNAPSHOT_PATH:C:\Users\Administrator\nacos\config

[fixed-127.0.0.1_8848] [subscribe] springcloud-nacos-config.properties+DEFAULT_GROUP

[fixed-127.0.0.1_8848] [add-listener] ok, tenant=, dataId=springcloud-nacos-config.properties, group=DEFAULT_GROUP, cnt=1

第六步:验证配置获取和验证动态刷新

访问:http://192.168.41.241:8001/test

返回结果:spring-cloud-alibaba-learning

然后,再通过Nacos页面,修改这个内容后面追加002,点击发布之后,再访问接口,可以看到返回结果变了,返回spring-cloud-alibaba-learning002。

3、Nacos配置的加载规则详解

3.1、默认配置解析

首先,回顾一下,我们在入门例子中,Nacos中创建的配置内容是这样的:

Data ID:springcloud-nacos-config.properties

Group:DEFAULT_GROUP

拆解一下,主要有三个元素,它们与具体应用的配置内容对应关系如下:

  • Data ID中的springcloud-nacos-config:对应客户端的配置spring.cloud.nacos.config.prefix,默认值为${spring.application.name},即:服务名。
  • Data ID中的properties:对应客户端的配置spring.cloud.nacos.config.file-extension,默认值为properties
  • Group的值DEFAULT_GROUP:对应客户端的配置spring.cloud.nacos.config.group,默认值为DEFAULT_GROUP。

在采用默认值的应用要加载的配置规则就是:

Data ID=${spring.application.name}.properties,Group=DEFAULT_GROUP。

3.2、自定义配置规则

1)如果我们不想通过服务名来加载,那么可以增加如下配置,就会加载到Data ID=example.properties,Group=DEFAULT_GROUP的配置内容了:

spring.cloud.nacos.config.prefix=example

2)如果我们想要加载yaml格式的内容,而不是Properties格式的内容,那么可以通过如下配置,实现加载Data ID=example.yaml,Group=DEFAULT_GROUP的配置内容了:

spring.cloud.nacos.config.prefix=example

spring.cloud.nacos.config.file-extension=yaml

3)如果我们对配置做了分组管理,那么可以通过如下配置,实现加载Data ID=example.yaml,Group=DEV_GROUP的配置内容了:

spring.cloud.nacos.config.prefix=example

spring.cloud.nacos.config.file-extension=yaml

spring.cloud.nacos.config.group=DEV_GROUP

Nacos配置中心添加example.yaml

didispace.title: test example.yaml

访问:http://192.168.41.241:8001/test

返回结果:test example.yaml

4、多环境管理

在Nacos中,本身有多个不同管理级别的概念,包括:Data ID、Group、Namespace。只要利用好这些层级概念的关系,就可以根据自己的需要来实现多环境的管理。

4.1、使用Data ID与profiles实现

Data ID在Nacos中,我们可以理解为就是一个Spring Cloud应用的配置文件名。我们知道默认情况下Data ID的名称格式是这样的:${spring.application.name}.properties,即:以Spring Cloud应用命名的properties文件。

实际上,Data ID的规则中,还包含了环境逻辑,这一点与Spring Cloud Config的设计类似。我们在应用启动时,可以通过spring.profiles.active来指定具体的环境名称,此时客户端就会把要获取配置的Data ID组织为:${spring.application.name}-${spring.profiles.active}.properties。

实际上,更原始且最通用的匹配规则,是这样的:

${spring.cloud.nacos.config.prefix}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}。而上面的结果是因为${spring.cloud.nacos.config.prefix}和${spring.cloud.nacos.config.file-extension}都使用了默认值。

先在Nacos中,根据这个规则,在同一个GROUP下面创建两个不同环境的配置内容。比如:

启动访问:http://192.168.41.241:8001/env

返回结果:it is springcloud-nacos-config-dev.properties

修改bootstrap.yml配置文件指定profiles为test

spring:
application:
name: springcloud-nacos-config
cloud:
nacos:
config:
server-addr: 192.168.41.241:8848
# 指定group
# group: DEV
# # 文件后缀,默认为properties
# file-extension: yaml
prefix: springcloud-nacos-config
profiles:
active: test

启动运行继续访问测试,返回结果如下:

it is springcloud-nacos-config-test.properties

4.2、使用Group实现

Group在Nacos中是用来对Data ID做集合管理的重要概念。所以,如果我们把一个环境的配置视为一个集合,那么也就可以实现不同环境的配置管理。对于Group的用法并没有固定的规定,所以我们在实际使用的时候,需要根据我们的具体需求,可以是架构运维上对多环境的管理,也可以是业务上对不同模块的参数管理。为了避免冲突,我们需要在架构设计之初,做好一定的规划。这里,我们先来说说如何用Group来实现多环境配置管理的具体实现方式。

第一步:增加DEV、TEST分组:

Group为DEV的配置文件添加如下内容:

didispace.title=DEV env test title

test.env=it's DEV environment

Group为TEST的配置文件添加如下内容:

didispace.title=TEST env test title

test.env=it's TEST environment

第二步:在springcloud-nacos-config应用的bootstrap.yml配置文件中,增加Group的指定配置:

spring.cloud.nacos.config.group=DEV

spring:
application:
name: springcloud-nacos-config
cloud:
nacos:
config:
server-addr: 192.168.41.241:8848
# 指定group
group: DEV
# # 文件后缀,默认为properties
# file-extension: yaml
prefix: springcloud-nacos-config
# profiles:
# active: test

第三步:启动应用,我们可以看到日志中打印了,加载的配置文件:

访问:http://192.168.41.241:8001/env

返回结果:it's DEV environment

然后修改 group: TEST后继续测试:

返回结果:it's TEST environment

4.3、使用Namespace实现

Namespace在本系列教程中,应该还是第一次出现。先来看看官方的概念说明:用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之一是不同环境的配置的区分隔离,例如:开发测试环境和生产环境的资源(如配置、服务)隔离等。

在官方的介绍中,就介绍了利用其可以作为环境的隔离使用,下面我们就来试一下吧!

第一步:先在Nacos中,根据环境名称来创建多个Namespace。比如:

第二步:添加配置文件springcloud-nacos-config.properties

didispace.title=the Namespace DEV and Group is DEFAULT_GROUP

test.env=it's DEV Namespace and Group is DEFAULT_GROUP

第三步:在springcloud-nacos-config应用的配置文件中,增加Namespace的指定配置

比如:namespace: 06678e35-7b4d-4fa7-ac09-2e75487dc57f # 指定namespace=DEV

spring:
application:
name: springcloud-nacos-config
cloud:
nacos:
config:
server-addr: 192.168.41.241:8848
# 指定group
group: DEFAULT_GROUP
# # 文件后缀,默认为properties
# file-extension: yaml
prefix: springcloud-nacos-config
namespace: 06678e35-7b4d-4fa7-ac09-2e75487dc57f # 指定namespace=DEV
# profiles:
# active: test

第四步:启动应用,通过访问localhost:8001/test接口,验证一下返回内容是否正确。

这种方式下,目前版本的日志并不会输出与Namespace相关的信息,所以还无法以此作为加载内容的判断依据。

访问地址:http://192.168.41.241:8001/env

返回结果:it's DEV Namespace and Group is DEFAULT_GROUP

5、思考

上面我们分别利用Nacos配置管理功能中的几个不同纬度来实现多环境的配置管理。从结果上而言,不论用哪一种方式,都能够胜任需求,但是哪一种最好呢?

5.1、第一种:通过Data ID与profile实现

优点:这种方式与Spring Cloud Config的实现非常像,用过Spring Cloud Config的用户,可以毫无违和感的过渡过来,由于命名规则类似,所以要从Spring Cloud Config中做迁移也非常简单。

缺点:这种方式在项目与环境多的时候,配置内容就会显得非常混乱。配置列表中会看到各种不同应用,不同环境的配置交织在一起,非常不利于管理。

建议:项目不多时使用,或者可以结合Group对项目根据业务或者组织架构做一些拆分规划。

5.2、第二种:通过Group实现。

优点:通过Group按环境讲各个应用的配置隔离开。可以非常方便的利用Data ID和Group的搜索功能,分别从应用纬度和环境纬度来查看配置。

缺点:由于会占用Group纬度,所以需要对Group的使用做好规划,毕竟与业务上的一些配置分组起冲突等问题。

建议:这种方式虽然结构上比上一种更好一些,但是依然可能会有一些混乱,主要是在Group的管理上要做好规划和控制。

5.3、第三种:通过Namespace实现。

优点:官方建议的方式,通过Namespace来区分不同的环境,释放了Group的自由度,这样可以让Group的使用专注于做业务层面的分组管理。同时,Nacos控制页面上对于Namespace也做了分组展示,不需要搜索,就可以隔离开不同的环境配置,非常易用。

缺点:没有啥缺点,可能就是多引入一个概念,需要用户去理解吧。

建议:直接用这种方式长远上来说会比较省心。虽然可能对小团队而言,项目不多,第一第二方式也够了,但是万一后面做大了呢?

注意:

不论用哪一种方式实现。对于指定环境的配置(spring.profiles.active=DEV、spring.cloud.nacos.config.group=DEV_GROUP、spring.cloud.nacos.config.namespace=xxx),都不要配置在应用的bootstrap.properties中。而是在发布脚本的启动命令中,用-Dspring.profiles.active=DEV的方式来动态指定,会更加灵活!。

6、Nacos配置的多文件加载与共享配置

我们实际应用过程中还会经常碰到这样的问题:有时候我们会对应用的配置根据具体作用做一些拆分,存储在不同的配置文件中,除了归类不同的配置之外,也可以便于共享配置给不同的应用。对于这样的需求,Nacos也可以很好的支持,下面就来具体介绍一下,当使用Nacos时,我们如何加载多个配置,以及如何共享配置。

6.1、加载多个配置

通过之前的学习,我们已经知道Spring应用对Nacos中配置内容的对应关系是通过下面三个参数控制的:

  • spring.cloud.nacos.config.prefix
  • spring.cloud.nacos.config.file-extension
  • spring.cloud.nacos.config.group

默认情况下,会加载Data ID=${spring.application.name}.properties,Group=DEFAULT_GROUP的配置。

假设现在有这样的一个需求:我们想要对所有应用的Actuator模块以及日志输出做统一的配置管理。所以,我们希望可以将Actuator模块的配置放在独立的配置文件actuator.properties文件中,而对于日志输出的配置放在独立的配置文件log.properties文件中。通过拆分这两类配置内容,希望可以做到配置的共享加载与统一管理。

这时候,我们只需要做以下两步,就可以实现这个需求:

第一步:在Nacos中创建Data ID=actuator.properties,Group=DEFAULT_GROUP和Data ID=log.properties,Group=DEFAULT_GROUP的配置内容。

didispace.title=the Namespace DEV and Group is DEFAULT_GROUP

test.env=it's DEV Namespace and Group is DEFAULT_GROUP

编辑bootstrap.properties

# 加载多个配置
spring.cloud.nacos.config.extension-config[0].data-id=actuator.properties
spring.cloud.nacos.config.extension-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-config[0].refresh=true
spring.cloud.nacos.config.extension-config[1].data-id=log.properties
spring.cloud.nacos.config.extension-config[1].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-config[1].refresh=true

启动访问:http://192.168.41.241:8001/env

返回结果:it's public environment for log.properties

访问接口:http://192.168.41.241:8001/test

返回结果:public env test title with DEFAULT_GROUP actuator.properties00

6.2、共享配置

通过上面加载多个配置的实现,实际上我们已经可以实现不同应用共享配置了。但是Nacos中还提供了另外一个便捷的配置方式,比如下面的设置与上面使用的配置内容是等价的:

# 共享配置
spring.cloud.nacos.config.shared-configs=actuator.properties,log.properties
spring.cloud.nacos.config.refresh-enabled=true

或者yaml配置方式

shared-configs: actuator.properties,log.properties
refresh-enabled: true # 目前测试没生效

spring.cloud.nacos.config.shared-configs用来配置多个共享配置的Data Id,多个的时候用用逗号分隔。

spring.cloud.nacos.config.refresh-enabled参数用来定义哪些共享配置的Data Id在配置变化时,应用中可以动态刷新,如果没有明确配置,默认情况下所有共享配置都不支持动态刷新。

方式一:shared-dataids

spring:
application:
name: springcloud-nacos-config
cloud:
nacos:
config:
server-addr: localhost:8848
shared-configs: actuator.properties,log.properties
refresh-enabled: true
file-extension: yaml

方式二:ext-config

spring:
cloud:
nacos:
config:
server-addr: localhost:8848
group: DEFAULT_GROUP
# prefix: springcloud-nacos-config
# namespace: 06678e35-7b4d-4fa7-ac09-2e75487dc57f # 指定namespace=DEV
# 加载多个配置配置方式二:extension-configs
extension-configs[0]:
data-id: actuator.properties
refresh: true
extension-configs[1]:
data-id: log.properties
refresh: true

6.3、配置加载的优先级

当我们加载多个配置的时候,如果存在相同的key时,我们需要深入了解配置加载的优先级关系。

在使用Nacos配置的时候,主要有以下三类配置:

A: 通过spring.cloud.nacos.config.shared-configs定义的共享配置

B: 通过spring.cloud.nacos.config.extension-config[n]定义的加载配置

C: 通过内部规则(spring.cloud.nacos.config.prefix、spring.cloud.nacos.config.file-extension、spring.cloud.nacos.config.group这几个参数)拼接出来的配置。

要弄清楚这几个配置加载的顺序,我们从日志中也可以很清晰的看到,我们可以做一个简单的实验:

根据上面的配置,应用分别会去加载三类不同的配置文件,然后查看控制台输出,发现后面加载的配置会覆盖之前加载的配置,所以优先级关系是:A < B < C

三、Nacos的集群部署

1、windows环境集群搭建

根据官方文档的介绍,Nacos的集群架构大致如下图所示(省略了集中化存储信息的MySQL)

1.1、对MySQL数据源的初始化和配置

在进行集群配置之前,先完成对MySQL数据源的初始化和配置。主要分以下两步:

第一步:初始化MySQL数据库,数据库初始化文件:nacos-mysql.sql,该文件可以在Nacos程序包下的conf目录下获得。

第二步:修改conf/application.properties文件,增加支持MySQL数据源配置,添加(目前只支持mysql)数据源的url、用户名和密码。配置样例如下:

### If user MySQL as datasource:
spring.datasource.platform=mysql
### Connect URL of DB:
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root

1.2、集群配置

在Nacos的conf目录下有一个cluster.conf.example,可以直接把example扩展名去掉来使用,也可以单独创建一个cluster.conf文件,然后打开将后续要部署的Nacos实例地址配置在这里。

本文以在本地不同端点启动3个Nacos服务端为例,可以如下配置:

127.0.0.1:8841、127.0.0.1:8842、127.0.0.1:8843

1.3、启动实例

在完成了上面的配置之后,我们就可以开始在各个节点上启动Nacos实例,以组建Nacos集群来使用了。由于本文中我们测试学习采用了本地启动多实例的情况,与真正生产部署会有一些差异,所以下面分两种情况说一下,如何启动各个Nacos实例。

1.4、本地测试

本文中,在集群配置的时候,我们设定了3个Nacos的实例都在本地,只是以不同的端口区分,所以我们在启动Nacos的时候,需要修改不同的端口号。

下面介绍一种方法来方便地启动Nacos的三个本地实例,我们可以将bin目录下的startup.sh脚本复制三份,分别用来启动三个不同端口的Nacos实例,为了可以方便区分不同实例的启动脚本,我们可以把端口号加入到脚本的命名中,比如:

startup-8841.sh、startup-8842.sh、startup-8843.sh(windows版本修改对应cmd文件)

然后,分别修改这三个脚本中的参数,具体如下图的红色部分(端口号根据上面脚本命名分配):

这里以windows命令方式为例:startup8841.cmd

set "JAVA_OPT=%JAVA_OPT% -Dserver.port=8841"

启动分别访问:

http://192.168.41.241:8841/nacos

http://192.168.41.241:8842/nacos

http://192.168.41.241:8843/nacos

发现里面数据一样

2、linux环境集群搭建

集群模式下运行Nacos

官方文档地址:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

集群模式部署

这个快速开始手册是帮忙您快速在你的电脑上,下载安装并使用Nacos,部署生产使用的集群模式。

集群部署架构图

因此开源的时候推荐用户把所有服务列表放到一个vip下面,然后挂到一个域名下面

http://ip1:port/openAPI 直连ip模式,机器挂则需要修改ip才可以使用。

http://VIP:port/openAPI 挂载VIP模式,直连vip即可,下面挂server真实ip,可读性不好。

http://nacos.com:port/openAPI 域名 + VIP模式,可读性好,而且换ip方便,推荐模式

3、思考

在Nacos官方文档的指引下,Nacos的集群搭建总体上还是非常顺畅的,没有什么太大的难度。但是值得思考的一个问题跟在上一篇中讲数据持久化的思考类似,作为一个注册中心和配置中心,Nacos的架构是否显得太过于臃肿?除了Nacos自身之外,还需要依赖更多的中间件来完成整套生产环境的搭建,相较于其他的可以用于服务发现与配置的中间件来说,就不那么有优势了。尤其对于小团队来说,这样的复杂度与成本投入,也是在选型的时候需要去考虑的。