掘金 后端 ( ) • 2024-05-08 09:01

@[TOC]

一、nacos1.4.1版本:服务注册与发现架构原理

1、基本原理

1、微服务系统在启动时将自己注册到服务注册中心,同时外发布 Http 接口供其它系统调用(一般都是基于SpringMVC) 2、服务消费者基于 Feign 调用服务提供者对外发布的接口,先对调用的本地接口加上注解@FeignClient,Feign会针对加了该注解的接口生成动态代理,服务消费者针对 Feign 生成的动态代理去调用方法时,会在底层生成Http协议格式的请求,类似 /stock/deduct?productId=100 3、Feign 最终会调用Ribbon从本地的Nacos注册表的缓存里根据服务名取出服务提供在机器的列表,然后进行负载均衡并选择一台机器出来,对选出来的机器IP和端口拼接之前生成的url请求,生成调用的Http接口地址http://192.168.0.60:9000/stock/deduct?productId=100,最后基于HTTPClient调用请求

2、Nacos&Ribbon&Feign核心微服务架构图

在这里插入图片描述

3、Nacos架构图

在这里插入图片描述

4、核心功能点

服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。

服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。

服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)

服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。

5、核心功能源码分析

(1)客户端注册逻辑

相当于直接调用http请求,调用了nacos服务端的httpApi。

(2)服务端注册接口

通过http接口,接受注册方信息,存到注册表(多重Map)。 使用阻塞队列,异步注册。 写时复制,使用读写分离的思想。 在这里插入图片描述

在这里插入图片描述

(3)客户端获取服务列表

客户端在本地缓存了一个Map,如果Map中没有,会调用nacosAPI获取服务列表,并存到Map缓存中。 并开启一个定时任务,定时从nacos拉取服务列表,并更新Map。

(4)心跳机制

客户端注册实例之后,如果是临时实例,服务端会添加一个BeatInfo,启动一个定时任务,会定时5S的往nacos服务端发送心跳请求/nacos/v1/ns/instance/beat

服务端收到心跳之后,会更新服务最新的心跳时间。后台有个定时任务,会判断上一次心跳时间,如果超过15秒,就会设置为不健康状态,超过30秒,就会剔除该服务。 在这里插入图片描述 在这里插入图片描述 nacos集群中,只需要有一台nacos服务器做心跳健康检查即可: 也就是说,会根据服务名称,根据hash运算+服务器数量取模,只有符合标准才会判断健康检查。 检查完毕之后,通知给集群中其他nacos。 (nacos集群之间也有心跳) 在这里插入图片描述

在这里插入图片描述

(5)服务端主动推送机制

nacos服务端,服务ip列表有变化时,会发送一个事件: 在这里插入图片描述 这个事件中,会往客户端发送udp请求,把信息发给客户端。 (在服务注册发现时,客户端会发给服务端自己的udp端口)

(6)集群注意事项

注意,集群需要配置mysql。

(7)集群节点状态同步

ServerListManager是一个Component,启动时会加载: 在这里插入图片描述 会定时给其他nacos服务发送心跳。

(8)集群服务状态变动同步

当服务状态有变化时,会通知给集群中其他nacos服务。 ServiceManager中:还是会起一个定时任务进行同步。 在这里插入图片描述

(9)服务新增状态同步

有服务实例注册,并不是通过定时任务同步的,而是新增后,往一个Map里放一个任务,然后还是通过定时任务,进行同步: 拿到集群中,除了自己以外所有的节点,进行同步。

在这里插入图片描述 在这里插入图片描述

(10)nacos集群新节点拉取其他节点数据

在这里插入图片描述

(11)整体架构图

在这里插入图片描述

6、Nacos服务注册表结构

Map<namespace, Map<group::serviceName, Service>> 在这里插入图片描述 举例说明: 在这里插入图片描述

7、源码导入

# 下载nacos源码
git clone https://github.com/alibaba/nacos.git

选择Tag 1.4.1版本 源码整体结构(注意,nacos源码导入要求maven 3.2.5以上版本): 在这里插入图片描述

8、CP架构以及Raft协议

nacos主要是AP架构。(配置的ephemeral默认是true,就是AP架构,设置为false就是CP架构,即注册的节点是否是临时节点) 也就是说,既可以注册临时节点也可以注册持久化节点。最好是选择AP架构,使用临时节点。

查看Raft协议的动图网站:http://thesecretlivesofdata.com/raft/

注意!nacos集群架构,注册信息持久化是写在文件中的。配置信息持久化是写在mysql中的。

在这里插入图片描述 在这里插入图片描述 半数以上节点同步: 在这里插入图片描述

二、Nacos2.x版本:服务注册与发现源码解析

1、Nacos 2.X 核心架构源码剖析

在这里插入图片描述

2、Nacos 2.X grpcClient初始化源码剖析

在这里插入图片描述

3、Nacos 2.X grpcServer启动源码剖析

在这里插入图片描述

4、总结

2.x版本:同一个服务下,节点必须是相同的(临时/非临时)。

nacos2.0使用大量的事件驱动方式 在这里插入图片描述

临时实例,使用了GRPC,持久化实例几乎没人用: 在这里插入图片描述

三、Nacos2.1.0版本:配置中心源码

1、Nacos2.1.0配置中心源码分析

在这里插入图片描述 配置中心核心接口ConfigService 在这里插入图片描述

2、获取配置

获取配置的主要方法是 NacosConfigService 类的 getConfig 方法,通常情况下该方法直接从本地文件中取得配置的值,如果本地文件不存在或者内容为空,则再通过grpc从远端拉取配置,并保存到本地快照中。 在这里插入图片描述

3、注册监听器

配置中心客户端会通过对配置项注册监听器达到在配置项变更的时候执行回调的功能。 ConfigService#getConfigAndSignListener ConfigService#addListener

Nacos 可以通过以上方式注册监听器,它们内部的实现均是调用 ClientWorker 类的 addCacheDataIfAbsent。其中 CacheData 是一个维护配置项和其下注册的所有监听器的实例,所有的 CacheData 都保存在 ClientWorker 类中的原子 cacheMap 中,其内部的核心成员有: 在这里插入图片描述

4、 nacos config server源码分析

配置dump 在这里插入图片描述 服务端启动时就会依赖 DumpService 的 init 方法,从数据库中 load 配置存储在本地磁盘上,并将一些重要的元信息例如 MD5 值缓存在内存中。服务端会根据心跳文件中保存的最后一次心跳时间,来判断到底是从数据库 dump 全量配置数据还是部分增量配置数据(如果机器上次心跳间隔是 6h 以内的话)。

全量 dump 当然先清空磁盘缓存,然后根据主键 ID 每次捞取一千条配置刷进磁盘和内存。增量 dump 就是捞取最近六小时的新增配置(包括更新的和删除的),先按照这批数据刷新一遍内存和文件,再根据内存里所有的数据全量去比对一遍数据库,如果有改变的再同步一次,相比于全量 dump 的话会减少一定的数据库 IO 和磁盘 IO 次数。

5、配置发布

发布配置的代码位于 ConfigController#publishConfig中。集群部署,请求一开始也只会打到一台机器,这台机器将配置插入Mysql中进行持久化。服务端并不是针对每次配置查询都去访问 MySQL ,而是会依赖 dump 功能在本地文件中将配置缓存起来。因此当单台机器保存完毕配置之后,需要通知其他机器刷新内存和本地磁盘中的文件内容,因此它会发布一个名为 ConfigDataChangeEvent 的事件,这个事件会通过grpc调用通知所有集群节点(包括自身),触发本地文件和内存的刷新。 在这里插入图片描述

6、客户端监听器

客户端将所有的dataId各自绑定一个监听器,当nacos上有配置变更,会刷新Environment、RefreshScope中的数据。 在这里插入图片描述