副本介绍
官方:一个更易于构建云原生应用的动态服务发现(Nacos Discovery)、服务配置(Nacos Config)和服务管理平台
集 注册中心+配置中心+服务管理 于一身
Nacos 的关键特性包括:
- 服务发现和服务健康监测
- 动态配置服务
- 动态 DNS 服务
- 服务及其元数据管理
第一关:初识Nacos注册中心
注册中心演变及其设计思想
- 服务启动的时候,调用注册接口,将服务注册到注册表里
- 服务停止的时候,调用注销接口,将服务从注册表里剔除
- 服务运行的时候,会定时发送心跳,根据结果对注册表里的数据进行操作
心跳机制的作用有什么呢?
可能服务每隔一段时间,向注册中心发送一次心跳。一定时间内(15s)注册中心没有收到心跳,就把status状态改为down,再过一段时间(30s)还是没有收到该服务的心跳,就需要把该服务从注册表里剔除出去。
第二关:Nacos Server 部署
安装nacos的时候,需要考虑到整体的版本选择问题,包括:SpringBoot 的版本,SpringCloud 的版本,SpringCloud Alibaba 的版本,SpringCloud Alibaba 中各项技术的版本
版本之间的依赖可参考SpringCloud Alibaba 官方文档提供的关系
本机安装 Nacos。
- 直接进入bin目录。
sh startup.sh -m standalone (standalone 是启动单机模式,nacos默认的是集群模式)
- 修改/nacos/conf/application.propertile文件,从里面配置我们自己的数据库(集群必须配置,单机模式如果不配置的话,nacos会默认使用内存)
- 也可以直接修改 startup.sh 文件,把里面的mode 从 cluster 直接改成 standalone (这样第一步就不需要跟后面的命令了)
Docker 安装 Nacos
-
查找docker镜像,拉取镜像
-
启动容器
docker run -d --name nacos -p 8848:8848 -e MODE=standalone -v /nacos/logs:/home/nacos/logs --restart=always nacos/nacos-server
介绍一下各个参数
-d 后台运行
-p 端口映射。外部访问端口:内部映射端口
-e 环境变量设置 (多个环境变量的使用 -e xxx=xxx -e xxx=xxx -e xxx=xxx)
-v 某个容器的目录:映射到服务器上的目录
上述启动nacos 是单机模式,没有指定数据库,会默认使用内存。当我们需要指定数据库的时候,可以通过 -e 配置环境变量,也可以学习使用docker-compose进行简化处理(需要注意的是当使用集群模式,必须使用外部数据库)
查看容器的输出日志
docker logs --since 容器id
进入容器
第三关:Nacos核心功能之服务发现
Nacos Discovery
服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。 leader raft
服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册
Nacos 的经典模型
一共由三层构成:
- Namespace 命名空间
- Group 组
- Service/DataId 服务/配置
Nacos 的分层是用来做什么的呢?
核心作用就两个字 - 【隔离】
最经典的使用场景就是 我们通过Namespace去划分开发环境,然后通过Group在细分每个环境里需要隔离的服务/子系统。
Nacos Discovery实践 - 创建服务 provider
Provider 的实现目标:
- 整合 Nacos
- 提供一个简单的接口
如何整合Nacos
- 添加Nacos Discovery 的依赖
- 在配置文件中指定 Nacos Server 的地址
- 添加 @EnableDiscoveryClient 注解,开启服务发现
修改 pom.xml 文件
...
org.springframework.boot
spring-boot-starter-parent
2.2.5.RELEASE
com.example
provider
...
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR3
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.2.1.RELEASE
pom
import
org.springframework.boot
spring-boot-maven-plugin
创建配置文件bootstrap.yml ,添加Nacos配置
( Nacos-docker 是docker容器的名称,会有对应的ip地址)
spring:
application:
name: provider
cloud:
nacos:
discovery:
server-addr: ${NACOS-HOST:nacos-docker}:${NACOS-PORT:8848}
namespace: ${REGISTER_NAMESPACE}
给启动类添加注解,开启nacos服务发现
...
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
之后我们启动Provider 服务,启动完成后,打开Nacos 控制台中的服务列表页面就可以看到我们启动的服务了
Nacos Discovery实践 - 创建服务 consumer
Consumer 的实现目标:
- 整合 Nacos (同上)
- 提供一个简单的接口,在接口中调用 Provider 的接口
使用restTemplate 进行调用
@Configuration
public class ConsumerConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
public class TestController {
// 引入 LoadBalancerClient,负责负载均衡
@Autowired
private LoadBalancerClient loadBalancerClient;
// 引入 RestTemplate
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(@RequestParam String name) {
// 通过 loadBalancerClient 获取名为 "provider" 服务的一个实例
ServiceInstance serviceInstance =
loadBalancerClient.choose("provider");
// 取得实例的 URI
URI instanceUri = serviceInstance.getUri();
// 使用 RestTemplate 发起请求调用
String result = restTemplate.getForObject(
instanceUri + "/hello?name=" + name,
String.class);
return "[consumer] " + result + "!";
}
}
在平时开发中,我们这边的调用会使用 openFeign 或者 Dubbo 底层也都是通过服务名,从而负载均衡到对应的服务上
第四关:Nacos 核心功能之分布式配置
Nacos Config
传统配置文件的弊端
- 维护性 多个服务的公共配置发生变化的时候,需要把所有微服务的配置文件更改
- 时效性 当更改了配置文件,需要重启服务
- 安全性 所有敏感配置都在代码里,容易出问题(不发工资就清库 - -)。 同时Nacos 有权限控制,可以通过不同的环境给员工配置不同的账号
分布式配置到底有什么用处呢?
我们平时都是把配置写在应用的配置文件里的是吧,这样做肯定是没毛病的,但就是管理起来比较麻烦。
比如一个服务部署了10个实例,他们的配置都是一样的是吧,如果想改动其中的一个配置的值,该怎么做?
答案是:修改服务中配置文件,然后重新部署10个实例是吧。
但这样做是不是很麻烦啊?如果修改配置这个动作比较频繁,可就相当悲催了。而且还需要重新部署服务。
要是能够动态修改配置就好了,不用重新部署就方便多了。这就需要能够实现配置的【动态刷新】。假设动态配置可以实现,但是每个实例中修改同一个配置还是挺麻烦的。如果能够在一个地方改动配置之后,所有相关实例能够自动获取都最新的值,然后自动生效,那就完美啦,这就需要实现配置的【共享配置】。
所以我们期待两个功能:
- 配置动态刷新
- 统一修改配置,所有实例自动获取最新值
而Nacos Config 分布式配置功能就可以帮我们实现这2个愿望,完美。
Nacos Config实践
实践目标
- 创建一个服务,使用本地配置,然后整合Nacos Config,改用 Nacos 中的配置
- 实现配置动态刷新
实践步骤
- 在 Nacos 中新建配置
- 给服务中添加 Nacos Config 依赖
- 给服务中创建配置文件 bootstrap.yaml
在 Nacos 中新建配置
新建配置 Data ID 填写 demo-config.yml
Group不用动,默认是DEFAULT_GROUP
配置格式. YAML
改造服务,给服务添加依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
补充 bootstrap.yaml 配置文件
为什么要用bootstrap.yaml ?
是因为bootstrap.yaml 的优先级高于 application.yaml, 在应用启动的时候就可以读取到了,所以需要在其中配置服务最基础的信息,例如服务名、Nacos Config 的地址,这样就可以获取Nacos 中的配置了。
server:
port: 8080
spring:
application:
name: demo-config
cloud:
nacos:
config:
server-addr: 192.168.0.5:8848
file-extension: yml
其中定义了服务端口、服务名、Nacos Config 的连接地址,这都是很好理解的,但最后一行的 "file-extension: yml" 是干什么的呢?
这就涉及到 Nacos Config 的配置命名规则。
回想一下,之前我们在 Nacos 中新建了一个配置,"Data ID" 命名为了 "demo-config.yml" 是吧。
那么为什么这么命名?我们的服务又如何关联到这个配置呢?
我们把 "demo-config.yml" 这个名字对照 bootstrap.yaml 的内容看一下:
同时Nacos Config 也是支持 profiles.active 的,
由此可看出,Nacos 中配置 DataID 的命名规则是:
[application.name]-[profiles.active] . [file-extension]
配置动态刷新
经过上面的改造,已经可以读取 Nacos 配置中心里面的配置了,同时是可以自动刷新的。
「特殊的情况1」但是如果通过@Value注解获取配置文件里数据,在 Nacos 中修改配置的值之后,服务是不能获知的。所以还需要加一点东西来实现配置的动态刷新。方法极其简单,添加 @RefreshScope
注解即可,如下:
@RefreshScope
@RestController
public class TestController {
...
}
「特殊的情况2」公共的配置文件(共享配置文件)。shared-configs 不会自动刷新,需要用户自己配置刷新 ( yml数组的两种形式分别在下面展示 )
「以下配置网上抄录,注释齐全,可根据自己实际情况修改,非常nice」
spring:
application:
# 服务名
name: pearl-test
cloud:
nacos:
config:
# 是否开启配置中心 默认true
enabled: true
# 配置中心地址
server-addr: localhost:8848
# 配置文件后缀
file-extension: yml
# 配置对应的分组
group: PEARL_GROUP
# 命名空间 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等
namespace: ba42e722-81aa-48f1-9944-9dca57d5f396
# Nacos 认证用户
username: nacos
# Nacos 认证密码
password: 123456
# 支持多个共享 Data Id 的配置,优先级小于extension-configs,自定义 Data Id 配置 属性是个集合,内部由 Config POJO 组成。Config 有 3 个属性,分别是 dataId, group 以及 refresh
shared-configs[0]:
data-id: pearl-common.yml # 配置文件名-Data Id
group: PEARL_GROUP # 默认为DEFAULT_GROUP
refresh: false # 是否动态刷新,默认为false
shared-configs[1]:
data-id: pearl-custom.yml
group: PEARL_GROUP
refresh: true
Nacos Config 权限控制
要想实现权限控制,除了对应角色的权限处理之外。还需要修改nacos的配置文件。
编辑文件: vim nacos/conf/application.properties
修改 nacos.core.auth.enabled = true (默认是false)