一 、什么是 Nacos
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
二、Nacos架构
Provider APP:服务提供者
Consumer APP:服务消费者
Name Server:通过VIP(Virtual IP)或DNS的方式实现Nacos高可用集群的服务路由
Nacos Server:Nacos服务提供者,里面包含的Open API是功能访问入口,Conig Service、Naming Service 是Nacos提供的配置服务、命名服务模块。
Consitency Protocol是一致性协议,用来实现Nacos集群节点的数据同步,这里使用的是Raft算法(Etcd、Redis哨兵选举)
Nacos Console:控制台
三、为什么使用nacos
String url = "http://localhost:8080/Api" restTemplate.getForEntity(url,List.class);
四、注册中心原理
注册流程
服务启动后---->服务注册原理
服务启动时,在spring-cloud-commons包下 spring.factories文件中自动装配,当webServer初始话完成后,会注册监听事件。调用Nacos的register注册服务
springCloudAlibaba实现原理,springCloudAlibaba使用的是Nacos为注册中心,自动装配的配置类是 DubboLoadBalanceRestTemplateAutoConfiguration,原理和上述一致,基于事件监听,不过事件类型不通,spring CloudAlibaba使用了@EvevntListener(ApplicationStartEvent.class) ,该事件是在应用程序初始化上下文后执行,即refresh()方法初始话上下文
服务注册时---->与Nacos建立心跳原理
服务调用registerInstance方法进行服务注册,registerInstance方法中,会调用addBeatInfo方法与Nacos Server服务建立心跳。
服务端是实现”心跳检测“原理:即executorService.schedule(BeatTask beatTask)定时线程定时执行 入参为心跳包数据
服务 启动一个定时线程-----(每隔5s)----->向Nacos服务发送BeatInfo心跳数据包
服务 启动一个监视线程-----()----->用来检测上面的定时线程发送完数据包后,Nacos服务的回应,如果Nacos服务未回应,则认为Nacos服务异常。
Nacos收到服务注册信息---->与服务建立心跳检测原理
Nacos收到服务注册原理:服务调用Nacos的open API进行服务注册,Nacos处理时,实际上时创建了一个concurrentHashMap将服务的信息以Namespace/group/缓存到服务内存中。
Nacos收到心跳数据原理:Nacos服务init完成后,会定时监听上述 第二步 服务发来的心跳包,如果等待超时后,没有收到数据包,则认为服务异常healthy为false,会更新concurrentHashMap缓存的服务地址列表数据。
更新服务的地址列表数据后,会向所有的服务 主动推送Push一个最新的服务地址列表数据
基于数据一致性协议,会将最新的 服务地址列表数据同步到Nacos集群的其他节点上
服务端之间进行远程调用---->调用Nacos获取远程服务地址列表数据原理
服务端获取远程调用服务地址列表数据原理:基于Nacos OpenAPI完成 获取远程服务地址列表数据,进而完成服务之间的远程调用。同时本地会缓存一份地址列表数据(这里说一下,如果使用的是feign那么服务之间的调用协议是Http,如果是Dubbo,那么可以自定义协议,或者Dubbo协议)
服务本地会缓存一份服务提供者地址列表数据---->Nacos实现服务提供者地址列表数据 动态感知
一旦涉及到缓存,就要涉及缓存数据的一致性。在微服务的调用中,服务调用者会缓存一份 服务提供者的地址列表数据,如果这份缓存数据和 Nacos注册中心的 服务提供者地址列表数据不一致。会造成服务消费者进行远程调用时出错。如果客户端的负载均衡没有做好,会造成严重问题。
Nacos解决 服务消费者动态感知 服务提供者地址 列表数据原理:(一般有两种方式Push和Pull,Nacos都提供了)
Pull模式:服务消费者 主动拉取,在调用selectInstance时,可以subscribe为true实现订阅,客户端会有 一个HostReactor update的定时线程-----(每隔10s)---->获取一次服务提供者地址列表数据。这里定时为10s,比上面第二步5s上报心跳大,一定程度上保证了服务消费者获取的地址列表数据的准确性
Push模式:Push模式需要依赖上述的第二步,Nacos会监听服务提供者的心跳数据包,并更新最后一次的心跳时间,如果超时了,那么说明服务提供者异常,会更新地址列表数据。并主动Push给服务消费者。
服务消费者收到Push数据原理:服务消费者收到最新的地址列表数据后,会将数据交给上述 Pull模式的 update定时线程来处理。站在服务消费者的角度,相当于服务消费者主动Pull了一次最新数据。这么做的原因是:保持服务消费者 只有一个线程感知接收服务提供者的地址列表数据。避免了Pull和Push如果多个线程处理,因为时间差造成的地址列表数据不一致的情况。
官方OpenApi服务注册
心跳机制
nacos和client之间采取推拉结合的交互方式,一方面client可以通过定时任务每隔10s向nacos发起查询请求,如果服务列表改变nacos就会返回新列表,另一方面当本地服务实例发生变化时(即server实例注册成功或者心跳停止断开链接),nacos会主动通过UDP协议推送到client,udp协议非常快,不需要保持长连接。在注册中心的场景中client数量往往多于server,如果每一次服务更新,nacos要和成千上万的服务消费者去建立Tcp的话性能肯定是不行的。而如果UDP通知失败,客户端每10秒还会主动去拉一次,客户端拉取和服务器推送是互补的,这样既能保证server实例更新的时效性,又能提高效率。
五、配置中心
1.在nacos上修改配置。
2.nacos客户端中ClientWorker会每隔10ms异步读取一次配置中心文件md5值。
3.和本地md5值比较,有变化的从服务器拉取。
4.将文件保存/缓存到本地。
5.通知NacosContextRefresher配置文件有变化。
6.NacosContextRefresher判断是否需要更新配置。
7.发送事件通知ContextRefresher去更新。
8.这里是更新配置的关键步骤。
9.准备一份before配置,然后通过构建新的Environment的方式拿到新的配置, 接着比较变化,得到有变化的keys。
10.构建Environment时会去读取配置文件,文件优先读本地,如果本地没有通过Http请求服务。
11.构建NacosPropertiesSource,并重新生成ConfigurationProperties对象。
12.通知RefreshScope去更新。
13.销毁scope='refresh'的bean。
14.通知bean容器去构建新的bean(懒加载)。
15.将属性(@Value注解)注入到新的bean。
六、Nacos 与其他注册中心对比
切换使用模式
默认使用AP C一致性 A可用性 P分区容错性
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
七、Nacos的使用
下载源码或安装包
Github 上下载源码方式
git clone https://github.com/alibaba/nacos.git cd nacos/ mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U ls -al distribution/target/ // change the $version to your actual path cd distribution/target/nacos-server-$version/nacos/bin
下载编译后压缩包方式
可以从 Releases · alibaba/nacos · GitHub 下载 nacos-server-$version.zip 包。
①: 把我们的Nacos包解压 tar -zxvf nacos-server-1.1.4.tar.gz
②:cd 到我们的解压目录nacos
③:进入到bin目录下执行命令(启动单机)sh startup.sh -m standalone
④:检查nacos启动的端口lsof -i:8848
⑤:访问nocas的服务端
http://localhost:8848/nacos/index.html
默认的用户名密码是 nocas/nocas
window环境启动nocas server
Nacos client服务端搭建
xml文件加入如下依赖
启动类添加EnableDiscoveryClient注解
@SpringBootApplication @EnableDiscoveryClient public class TestApplication{ public static void main(String[] args){ SpringApplication.run(Tulingvip01MsAlibabaNacosClientOrderApplication.class,args); } }
配置文件配置
spring: cloud: nacos: discovery: server-addr: localhost:8848 namespace: 1111 ephemeral:false #默认true(临时实列) 当服务宕机超过心跳就会将实列剔除 #false永久实列 宕机也不会剔除实列 service:默认取${spring.application.name}也可以通过service配置 group: 分组 默认DEFAULT_GROUP 更细得给相同特征得服务进行归类分组管理 weight:通常结合 安装 权重得负载均衡策略,权重越高分配得流量越大
应用名称
spring.application.name=smartworkflowbusiness
nacos配置中心请求地址
spring.cloud.nacos.config.server-addr=192.168.1.1:9001
nacos 命名空间
spring.cloud.nacos.config.namespace=public
nacos组
spring.cloud.nacos.config.group=DEFAULT_GROUP
nacos配置中心环境
spring.profiles.active=test
nacos注册中心地址
spring.cloud.nacos.discovery.server-addr=192.168.1.1:9001
nacos 注册中心命名空间
spring.cloud.nacos.discovery.namespace=cf94d71d-81c8-4e6f-8c25-8bf14c870701
nacos 运行注册发现
spring.cloud.nacos.discovery.enabled=true
namespace
namespace命名空间是nacos针对于企业级开发设计用来针对于不同环境的区分,比如正在企业开发时有测试环境,生产环境,等其他环境,因此为了保证不同环境配置实现隔离,提出了namespace的概念,默认在nacos中存在一个public命名空间所有配置在没有指定命名空间时都在这个命名空间中获取配置,在实际开发时可以针对于不能环境创建不同的namespace空间。默认空间不能删除!
每个命名空间都有一个唯一id,这个id是读取配置时指定空间的唯一标识
在配置列表查看空间
namespace组
Nacos默认的命名空间是public, Namespace主要用来实现隔离。
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
Group默认是DEFAULT_ GROUP, Group可以把不同的微服务划分到同一个分组里面去。
Service就是微服务; 一个Service可以包含多个Cluster (集群),Nacos默认Cluster是DEFAULT, Cluster是对指定微服务的一个虚拟划分。
比方说为了容灾,将Service微服务分别部署在了A机房和B机房,这时就可以给A机房的Service微服务起一个集群名称(A),给B机房的Service微服务起一个集群名称 (B), 还可以尽量让同一个机房的微服务互相调用,以提升性能。
最后是Instance,就是微服务的实例
在 bootstrap.properties中加入group
spring.cloud.nacos.config.group=dev