53-Nacos
1. 基础说明
Nacos(Dynamic Naming and Configuration Service)
1.1 概要
(1)服务发现和服务健康监测
Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用原生SDK、OpenAPI、或一个独立的 Agent。注册 Service 后,服务消费者可以使用 DNS 或 HTTP&API 查找和发现服务。
(2)动态配置服务
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。
动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos 提供了一个简洁易用的 UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
(3)动态 DNS 服务
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单 DNS 解析服务。动态 DNS 服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。
Nacos 提供了一些简单的 DNS APIs 帮助您管理服务的关联域名和可用的 IP:PORT 列表。
(4)服务及其元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
1.2 架构
基础架构:
逻辑架构:
1.3 安装
(1)官网下载压缩包
(2)执行 sql 脚本(Nacos 默认使用的是自带的嵌入式数据库 derby)
-
新建数据库 nacos_config,数据库初始化脚本文件
${NACOS_HOME}/conf/nacos-mysql.sql
; -
修改
${NACOS_HOME}/conf/application.properties
,增加 MySQL 数据源配置;spring.datasource.platform=mysql ### Count of DB: db.num=1 ### Connect URL of DB: db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=123456
(3)单节点模式启动:sh startup.sh -m standalone
(4)集群方式启动
- 复制解压后的 nacos 文件夹,分别命名为 nacos-01、nacos-02、nacos-03;
- 使用同一台机器模拟,故将上述 3 个文件夹中 application.properties 中的 server.port 分别改为 8848、8849、8850。同时给当前实例节点绑定ip,因为服务器可能绑定多个 IP:
nacos.inetutils.ip-address=127.0.0.1
; - 复制一份 conf/cluster.conf.example 文件,命名为 cluster.conf,在该配置文件中设置集群中每一个节点的信息:
# 集群节点配置 127.0.0.1:8848 127.0.0.1:8849 127.0.0.1:8850
- 分别启动每一个实例(后续可以自制批处理脚本)
sh startup.sh -m cluster
【补充】Nacos 支持 AP 模式和 CP 模式的切换
1.4 模型
数据模型
Namespace 命名空间、Group 分组、集群这些都是为了进行归类管理,把服务和配置文件进行归类,归类之后就可以实现⼀定的效果。比如,对于服务来说,不同命名空间中的服务不能够互相访问调用。
- Namespace:命名空间,对不同的环境进行隔离,比如隔离开发环境、测试环境和生产环境;
- Group:分组,将若干个服务或者若干个配置集归为一组,通常习惯一个系统归为一个组;
- Service:某一个服务,比如网关微服务;
- DataId:配置集或者可以认为是一个配置文件;
Namespace + Group + {Service/DataId} 如同 Maven 中的 GAV 坐标,GAV 坐标是为了锁定 Jar,而这里是为了锁定 {服务 / 配置文件}。
服务领域模型
配置领域模型
1.5 对比
服务注册中心对比:
- Nacos 与 Eureka 的共同点(注册中心)
- 都支持服务注册和服务拉取
- 都支持服务提供者心跳方式做健康检测
- Nacos 与 Eureka 的区别(注册中心)
- Nacos 支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式;临时实例心跳不正常会被剔除,非临时实例则不会被剔除;
- Nacos 支持服务列表变更的消息推送模式,服务列表更新更及时;
- Nacos 集群默认采用 AP 方式,当集群中存在非临时实例时,采用 CP 模式;Eureka 采用 AP 方式;
- Nacos 还支持了配置中心,Eureka 则只有注册中心,这也是选择使用 Nacos 的一个重要原因。
2. 服务注册发现
2.1 基本使用
(1)在父 pom.xml 中引入 SCA 依赖;
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
(2)微服务引入依赖;
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(3)修改 application.yml
spring:
cloud:
nacos:
# 集群中各节点信息都配置在这里(域名-VIP-绑定映射到各个实例的地址信息)
discovery:
server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
(4)在项目启动类上添加开启服务发现的注解 @EnableDiscoveryClient
(5)启动微服务,观察 Nacos 控制台
保护阈值:可以设置为 0~1 之间的浮点数,它其实是一个比例值(当前服务健康实例数/当前服务总实例数)。
【场景】一般流程下,Nacos 是服务注册中心,服务消费者要从 Nacos 获取某一个服务的可用实例信息,对于服务实例有健康/不健康状态之分,Nacos 在返回给消费者实例信息的时候,会返回健康实例。这个时候在一些高并发、大流量场景下会存在一定的问题。如果服务 A 有 100 个实例,98 个实例都不健康了,只有 2 个实例是健康的,如果 Nacos 只返回这两个健康实例的信息的话,那么后续消费者的请求将全部被分配到这两个实例,流量洪峰到来,2个健康的实例也扛不住了,整个服务 A 就扛不住,上游的微服务也会导致崩溃,产生雪崩效应。
保护阈值的意义在于:当服务 A 健康实例数/总实例数 < 保护阈值
的时候,说明健康实例真的不多了,这个时候保护阈值会被触发(状态 true)Nacos 将会把该服务所有的实例信息(健康的+不健康的)全部提供给消费者,消费者可能访问到不健康的实例,请求失败,但这样也比造成雪崩要好,牺牲了一些请求,保证了整个系统的一个可用。
注意:阿里内部在使用 Nacos 的时候,也经常调整这个保护阈值参数。
2.2 负载均衡
我们可以发现服务注册到 Nacos 中,有一个权重属性,这个权重属性就是 Nacos 的负载均衡机制,此时需要用到 Nacos 的负载均衡策略 NacosRule,我们可以在程序中先初始化负载均衡算法,再到 bootstrap.yml 中配置权重。
(1)初始化负载均衡算法(必须是 prototype)
@Bean
@Scope(value="prototype")
public IRule loadBalanceRule(){
return new NacosRule();
}
(2)在微服务的 bootstrap.yml 中配置权重
spring:
application:
name: hailtaxi-driver
cloud:
nacos:
discovery:
server-addr: 192.168.200.200:8848
weight: 1
config:
server-addr: 192.168.200.200:8848
3. 服务配置中心
3.1 基本使用
依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
通过 Namespace + Group + DataId 来锁定配置文件,Namespace 不指定就默认 public,Group 不指定就默认 DEFAULT_GROUP。
一个 dataId 对应一个配置文件,dataId 的完整格式:${prefix}-${spring.profile.active}.${file-extension}
。
- prefix 默认为
spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置; - spring.profile.active 即为当前环境对应的
profile
。 注意:当spring.profile.active
为空时,对应的连接符-
也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
; - file-exetension 为配置内容的数据格式,可以通过配置项
spring.cloud.nacos.config.file-extension
来配置。目前只支持 properties 和 yaml 类型。
【示例】bootstrap.yml 中编写 Nacos 配置
spring.cloud.nacos.config.enabled=true
spring.cloud.nacos.config.server-addr=localhost:8848
# 1. 命名空间,用来做环境隔离
# 默认 public
# spring.cloud.nacos.config.namespace=<命名空间ID>
# 2. Nacos 中的配置集所在分组,默认 DEFAULT_GROUP
spring.cloud.nacos.config.group=DEFAULT_GROUP
spring.cloud.nacos.config.prefix=common
spring.profile.active=dev
spring.cloud.nacos.config.file-extension=properties
3.2 共享/扩展配置
【共享配置】在实际的业务场景中应用和共享配置间的关系可能,Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义 DataId 的配置,通过它可以解决配置共享问题。
创建一个Data ID 为 datasource.yaml 的配置,用于配置数据库连接:
在业务微服务模块的 bootstrap.yml 中引入共享配置需要使用 shared-configs
属性,配置如下:
spring:
application:
name: hailtaxi-driver
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 192.168.200.200:8848
weight: 1
namespace: 1ebba5f6-49da-40cc-950b-f75c8f7d07b3
config:
server-addr: 192.168.200.200:8848
namespace: 1ebba5f6-49da-40cc-950b-f75c8f7d07b3
file-extension: yaml
# 加载共享配置信息
shared-configs[0]:
dataId: datasource.yaml
refresh: true
【扩展配置】Nacos 除了支持读取以上所支持的的配置信息外,用户还可以自定义扩展配置。
在 Nacos 中创建一个 Data ID 为 custom.yaml 的配置,配置信息如下图:
在业务微服务模块的 bootstrap.yml 中加载该配置,使用 extension-configs
属性:
spring:
application:
name: hailtaxi-driver
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 192.168.200.200:8848
weight: 1
namespace: 1ebba5f6-49da-40cc-950b-f75c8f7d07b3
config:
server-addr: 192.168.200.200:8848
namespace: 1ebba5f6-49da-40cc-950b-f75c8f7d07b3
file-extension: yaml
# 加载共享配置信息
shared-configs[0]:
dataId: datasource.yaml
refresh: true
# 加载扩展配置
extension-configs:
- dataId: custom.yaml
3.3 配置刷新
配置自动刷新对程序来说非常重要,Nacos 支持配置自动刷新,并且提供了多种刷新机制。
a. Environment
Nacos 支持配置的动态更新,Environment 能实时更新到最新的配置信息。
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.itheima.driver.mapper")
public class DriverApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(DriverApplication.class,args);
while(true) {
// 当动态配置刷新时,会更新到 Enviroment中
String name = applicationContext.getEnvironment().getProperty("app.name");
String version = applicationContext.getEnvironment().getProperty("app.version");
System.out.println("app.name="+name+";app.version=" + version);
try {
TimeUnit.SECONDS.sleep(5); // 每隔5s中从Enviroment中获取一下
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
b. @Value 自动刷新
程序中如果写了 @Value
注解,可以采用 @RefreshScope
实现刷新,只需要在指定类上添加该注解即可。
@RestController
@RequestMapping(value = "/driver")
@RefreshScope
public class DriverController {
@Value("${app.version}")
private String version;
@Value("${app.name}")
private String appname;
@GetMapping("/appinfo")
public String getAppInfo() {
return appname + ";"+version;
}
}
注意,刷新的只是保存了 Nacos 配置的这些字符串变量(像修改数据库连接地址的配置,并不会导致数据库连接被修改,改的只是微服务本地保存这个连接地址的字符串变量)。
c. 注册配置变更监听
// TODO
3.4 灰度发布
灰度配置指的是指定部分客户端 IP 进行新配置的下发,其余客户端配置保持不变,用以验证新配置对客户端的影响,保证配置的平稳发布。灰度配置是生产环境中一个比较重要的功能,对于保证生产环境的稳定性非常重要。在 1.1.0 中,Nacos 支持了以 IP 为粒度的灰度配置,具体使用步骤如下:
(1)管理端选择指定的配置,编辑配置,勾选“Beta发布”,在文本框里填入要下发配置配置的 IP,多个 IP 用逗号分隔。
(2)修改配置内容,点击“发布Beta”按钮,即可完成灰度配置的发布,点击“发布Beta”后,“发布Beta”按钮变灰,此时可以选择“停止Beta”或“发布”。
- “停止Beta”表示取消停止灰度发布,当前灰度发布配置的 IP 列表和配置内容都会删除,页面回到正常发布的样式。
- “发布”表示将灰度配置在所有客户端生效,之前的配置也会被覆盖,同时页面回到正常发布的样式。
4. 集群和持久化配置
Nacos 集群模式有多种,但其实无论哪种都是将 3 个 Nacos 服务进行集群发布。集群需要采用数据共享模式进行配置信息共享,也就是要将数据存入到同一个数据库中,我们对每种集群模式进行说明:
(1)直连模式
http://ip1:port/openAPI
直连 IP 模式,机器挂则需要修改 IP 才可以使用。
比如我现在有 3 个 Nacos,每次操作数据的时候,都需要使用 IP:PORT 的模式,这种模式效率极低,并且一旦节点故障无法识别,因此官方不推荐这种模式。
(2)VIP 模式
http://VIP:port/openAPI
挂载 VIP 模式,直连 VIP 即可,下面挂 server 真实 IP,可读性不好。
(3)域名模式
http://nacos.com:port/openAPI
域名 + VIP模式,可读性好,而且换 IP 方便,因此官方推荐该模式,该模式的结构图如下:
集群搭建:
(1)在 Linux 上的 mysql 中运行 nacos-mysql.sql;
(2)修改 application.properties 中数据库的配置;
(3)Linux 服务器上 nacos 的集群配置 cluster.conf(IP 不能写 127.0.0.1,必须是 hostname -i
能够识别的 IP)
IP1:Port1
IP2:Port2
IP3:Port3
...
(4)编辑 Nacos 的启动脚本 startup.sh,使它能够接受不同的端口号进而启动不同的 nacos 实例:
(5)启动 Nacos:./startup.sh -p <Port1>
、./startup.sh -p <Port2>
、...
(6)修改 nginx.conf,然后启动 Nginx
(7)微服务注册进 Nacos 集群
spring:
application:
cloud:
nacos:
discovery:
server-addr: <NGINX-IP>:<NGINX-PORT>
(8)小结