微服务·架构组件之服务注册与发现-Nacos

news2024/11/20 12:35:14

微服务·组件架构之服务注册与发现之Nacos

Nacos服务注册与发现流程请添加图片描述

  1. 服务注册:Nacos 客户端会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。 Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
  2. 服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认 5s发送一次心跳。
  3. 服务同步:如果是集群部署,Nacos 服务端集群之间会互相同步服务实例,用来保证服务信息的一致性。
  4. 服务发现:Nacos 客户端在调用服务提供者的服务时,会发送一个REST请求给Nacos 服务端,获取上面注册的服务清单,并且缓存在Nacos 客户端本地,同时会在Nacos客户端本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存。
  5. 服务健康检查:Nacos 服务端会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的 healthy属性置为false,如果某个实例超过30秒没有收到心跳,直接剔除该实例

Nacos服务注册中心数据模型

定义服务

在Nacos中,服务的定义包括以下几个内容:

  • 命名空间(Namespace):Nacos数据模型中最顶层、也是包含范围最广的概念,用于在类似环境或租户等需要强制隔离的场景中定义。
  • 分组(Group):Nacos数据模型中次于命名空间的一种隔离概念,区别于命名空间的强制隔离属性,分组属于一个弱隔离概念,主要用于逻辑区分一些服务使用场景或不同应用的同名服务,最常用的情况主要是同一个服务的测试分组和生产分组、或者将应用名作为分组以防不同应用提供的服务重名。
  • 服务名(name):该服务的实际名称,一般用于描述该服务提供了某种功能或能力。
    通常推荐使用运行环境作命名空间、应用名作为分组和服务功能作为服务名的组合来确保该服务的天然唯一性。

服务元数据

  • 健康保护阈值(ProtectThreshold):未来防止因过多实例故障,导致所有流量流入剩余实例,继而造成流量压力将剩余实例被压垮形成的雪崩效应,应将保护阈值定义为一个0到1之间的浮点数。当域名健康实例数占总服务实例数的比值小于该值时,无论实例是否健康,都会将这个实例返回给客户端。这样做虽然损失了一部分流量,但是保证了集群中剩余健康实例能正常工作。
  • 实例选择器(Selector):用于在获取服务下的实例列表时,过滤和筛选实例。该选择器也被称为理由器,目前Nacos支持通过将实例的部分信息存储在外部元数据管理CMDB中,并在发现服务时使用CMDB中存储的元数据标签进行筛选的能力。
  • 拓展数据(extendData):用于用户在注册实例时自定义扩展的元数据内容,形式为k-v。

服务端数据结构

/**
 * Map(namespace, Map(group::serviceName, Service)).
 */
private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
 
 
/**
 * Service of Nacos server side
 *
 * <p>We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters, which
 * contain
 * a list of instances.
 *
 * <p>his class inherits from Service in API module and stores some fields that do not have to expose to client.
 * 
 * @author nkorange
 */
//重要!!!Service实体类中包含Cluster对象
private Map<String, Cluster> clusterMap = new HashMap<>();
 
 
/**
 * Cluster. 集群类
 *
 */
//持久实例列表
@JsonIgnore
private Set<Instance> persistentInstances = new HashSet<>();
  
//临时实例列表
@JsonIgnore
private Set<Instance> ephemeralInstances = new HashSet<>();
  
//持有service对象
@JsonIgnore
private Service service;

定义实例

由于服务实例是具体提供服务的节点,因此Nacos在设计实例的定义时,主要需要存储实例的一些网络相关的基础信息。

  • 网络IP地址:该实例的IP地址,在Nacos2.0版本后支持设置为域名。
  • 网络端口:该实例的端口信息。
  • 健康状态(Healthy):用于表示该实例是否为健康状态,会在Nacos中通过健康检查手段进行维护。
  • 集群(Cluster):用于标示该实例归属于哪个逻辑集群。
  • 拓展数据(extendData):用与用户自定义扩展的元数据内容,形式为k-v。

实例元数据

  • 权重(Weight):实例级别的配置。权重越大,分配给该实例的流量越大。
  • 上线状态(Enable):标记该实例是否接受流量,优先级大于权重和健康状态。
  • 拓展数据(extendData):用与用户自定义扩展的元数据内容,形式为k-v。
    在Nacos2.0版中,实例数据被拆分为实例定义和实例元数据,只要对应着两种不同场景:开发运行场景以及运维场景。

客户端数据结构

    
    
    /**
     * unique id of this instance.
     */
    private String instanceId;
 
    /**
     * instance ip
     */
    private String ip;
 
    /**
     * instance port
     */
    private int port;
 
    /**
     * instance weight
     */
    private double weight = 1.0D;
 
    /**
     * instance health status
     */
    private boolean healthy = true;
 
    /**
     * If instance is enabled to accept request
     */
    private boolean enabled = true;
 
    /**
     * If instance is ephemeral
     *
     * @since 1.0.0
     */
    private boolean ephemeral = true;
 
    /**
     * cluster information of instance
     */
    private String clusterName;
 
    /**
     * Service information of instance
     * 拼接:分组名@@服务名
     */
    private String serviceName;
 
    /**
     * user extended attributes
     */
    private Map<String, String> metadata = new HashMap<String, String>();

集群

定义集群

  • 健康检查类型(HealthCheckTye):使用哪种类型的健康检查方式,目前支持的TCP,HTTP,MySQL;设置为NONE可以关闭健康检查。
  • 健康检查端口(HealthCheckPort):设置用于健康检查的端口。
  • 是否使用实例端口进行健康检查(UseInstancePort):如果使用实例端口进行健康检查,将会使用实例定义中的网络端口进行健康检查,而不再使用上述设置的健康检查端口进行。
  • 拓展数据(extendData):用与用户自定义扩展的元数据内容,形式为k-v。

请添加图片描述

生命周期

在注册中心中,实例数据都和服务实例的状态绑定,因此服务实例的状态直接决定了注册中心中实例数据的生命周期。

服务的生命周期

  • 开始:用户向注册中心发起服务注册请求
  • 结束:用户主动发起删除服务的请求或一定时间内服务没有实例。

实例的生命周期

持久化实例

持久化的实例会通过健康检查的状态维护健康状态,但是不会自动终止该实例的生命周期。唯一终止持久化实例生命周期的方法就是注销实例的请求。

非持久化实例

Nacos1.0版本通过心跳请求进行续约,当超过一定时间内没有心跳进行续约时,该非持久化实例则终止生命周期。
Nacos2.0版本通过gRPC的长连接来维持状态,当连接发生中断时,该非久化实例则终止生命周期。

集群的生命周期

  • 开始:与集群中第一个实例的生命周期同时开始。
  • 结束:与集群中最后一个服务的生命周期同时结束。

元数据的生命周期

元数据通常为运维人员的主从操作的数据,会被Nacos进行一段时间的记忆。因此元数据的生命周期的终止相比对应的数据要滞后,如果在滞后期间,对应的数据又重新开始生命周期,则元数据的生命周期将被立即重制。

Nacos注册中心健康检查机制

临时实例健康检查机制

Nacos提供给了两种方式进行临时实例的注册,即通过Nacos的OpenAPI进行服务注册或通过Nacos提供的SDK进行服务注册。
OpenAPI的注册方式是用户根据自身需求调用Http接口对服务进行注册,然后通过Http接口发送心跳到注册中心。在注册服务的同时会注册一个全局的客户端心跳检测任务。在服务端一段时间没有收到来自客户端的心跳后,该任务会将其标记为不健康,如果在间隔的时间内还未收到心跳,那么该任务会将其剔除。
SDK的注册方式实际是通过RPC与注册中心保持连接,客户端会定时的通过RPC连接向Nacos注册中心发送心跳,保持连接的存活。如果连接中断,注册中心会剔除该client所注册的服务来达到下线的效果。

永久实例健康检查机制

Nacos采用的是注册中心探测机制,注册中心会在永久服务初始化时根据客户端选择的协议类型注册探活的定时任务。Nacos内置提供了三种探测的协议:Http、TCP、MySQL。

集群模式下的健康检查机制

对于集群下的服务,Nacos一个服务只会被Nacos集群中的一个注册中心所负责,其余节点的服务信息只是集群副本,用于订阅者在查询服务列表时,始终可以获得全部的服务列表。临时节点只会对其被负责的注册中心节点发送心跳信息,注册中心服务节点会对其负责的永久实例进行健康探测,在获取到健康状态后由当前节点将健康信息同步到集群中的其他注册中心。

Nacos为什么需要一致性协议

Nacos是一个简单存储数据的组件,因此为了实现这个目标,就需要在Nacos内部实现数据存储。单机下问题不大,简单的内嵌关系型数据库即可;但是在集群模式下,就要考虑如何保障各个节点之间的数据一致性以及数据同步,而要解决这个问题,就不得不引入共识算法来保障各个节点之间的数据一致性。

Nacos为什么选择Raft以及Distro

Nacos在单个集群中同时运行了CP协议和AP协议,这个要从Nacos的应用场景出发:Nacos是一个集服务注册发现以及配置管理于一体的组件,因此对于集群中各个节点之间的数据一致性保障问题要从两方面考虑。

从服务注册发现来看

服务注册发现中心在当前微服务体系下,是十分重要的组件,服务之间感知对方服务当前可正常提供服务的实例信息,必须从服务注册中心中获取,因此对于服务注册中心组件的可用性,提出了很高的要求。需要在任何场景下尽最大可能保证服务注册发现能力可以对外提供服务。同时Nacos的服务注册发现设计,采用了心跳可自动完成服务数据的补偿机制。如果数据丢失的话,可以通过该机制快速弥补数据丢失。

针对非持久化服务(即需要客户端上报心跳机制进行服务实例续约)强一致性的共识算法不太合适,因为强一致共识算法必须保证集群中可用节点超过半数。而最终一致算法更多的是保证可用性,并且能够在一定时间内各个节点之间的数据达成一致。

针对持久化服务,数据是直接使用Nacos服务端的,因此需要由Nacos保障数据节点之间的强一致性。

从配置管理来看

配置数据,是直接在Nacos服务端进行创建并管理的,必须保证大部分节点都保存了此配置数据才能任务配置被成功保存了。因此需要使用强一致性共识算法。

为什么是Raft和Distro

对于强一致性算法,当前工业生产中,使用最多的就是Raft协议,Raft协议更容易让人理解,并且有很多成熟的工业算法实现,比如蚂蚁金服的JRaft、Zookeeper的ZAB、Consul的Raft、百度的braft以及Apache的Ratis;JRaft支持多RaftGroup,为Nacos的多数据分片带来了可能。

Distro是阿里自研的一个最终一致性协议。最终一致性协议有很多,例如Gossip、Eureka内的数据同步算法。而Distro是集合以上两种算法的优点并加以优化而来的。对于原生Gossip,由于随机选取发送消息的节点,也就不可弥漫的存在消息重复发送给同一节点的清空,增加了网路的传输压力,也给消息节点带来了额外的处理负担,而Distro引入权威Server的概念,每个节点负责一部分数据以及自己的数据同步给其他节点,有效的降低消息冗余问题。

Distro协议

Distro协议是Nacos社区自研的一种AP分布式协议,是面向临时实例设计的一种分步式协议,其保证了某些Nacos节点宕机后,整个临时实例处理系统依旧可以正常工作。作为一种有状态的中间件应用的内嵌协议,Distro保证了各个Nacos节点对于海量注册请求统一协调和存储。

设计思想

  • Nacos每个节点是平等的都可以处理写请求,同时把新数据同步到其他节点。
  • 每个节点只负责部分数据,定时发送自己负责数据的校验值到其他节点来保持数据一致性。
  • 每个节点独立处理读请求,及时从本机发出的响应。

工作原理

数据初始化

新加入的Distro节点会进行全量数据拉取,具体操作是轮询所有的Distro节点,通过向其他的机器发送请求拉取全量数据。

在全量拉取操作完成后,Nacos的每台机器上都维护了当前的所有注册上来的非持久化实例数据。

数据校验

在Distro集群启动之后,各台机器之间会定期的发送心跳。心跳信息主要为各个机器上的所有数据的元信息(之所以是元信息,是因为需要保证网络中数据传输的量级维持在一个较低的水平)。这种数据校验会以心跳的形式进行,即每台机器在固定的时间间隔向其他机器发起一次数据校验的请求。

一旦在数据校验过程中,某台机器发现其他机器上的数据与本地数据不一致,则会发起一次全量拉取请求,将数据补齐。

写操作

对于一个已经启动完成的Distro集群,在一次客户端发起写操作的流程中,当注册非持久化的实例的写请求打到某台Nacos服务器时,Distro集群的处流程:

  • 前置的Filter拦截请求,并根据请求中包含的IP和Port信息计算其所属的Distro负责节点,并将该请求转发到所属的Distro节点上。
  • Distro节点上的controller将写请求进行解析。
  • Distro协议定期执行sync任务,将本机所负责的所有实例信息同步到其他节点上。
读请求

由于每台机器上都存放了全量数据,因此在每次读操作中,Distro机器会直接从本地拉取数据,快速响应。

这种协议保证了Distro协议可以作为一种AP协议,对于读操作都进行了及时的响应。在网络分区的情况下,对于所有的读操作也能够正常返回;当网络恢复时,各个Distro节点会把各个数据分片的数据进行合并恢复。

小结

Distro协议是Nacos对于临时实例数开发的一致性协议,其数据存储在缓存中,并且会在启动是进行全量数据同步,并定期进行数据校验。

Nacos寻址机制

Nacos支持单机部署和集群部署,针对单机部署,Nacos只是自己和自己进行通信;对于集群模式,则集群中的每个Nacos成员都需要相互通信,那么应该怎么管理集群内的Nacos成员节点信息,这就是Nacos内部寻址机制。

设计

无论是单机模式还是集群模式,其根本区别只是Nacos成员节点的个数是单个还是多个,并且能够感知到这些节点的变更情况:节点是增加了还是减少了;当前罪行的成员列表信息是什么;怎么管理成员列表信息;如何快速的支持新的、更优秀的成员列表管理模式等.

内部实现
单机寻址

单机寻址,就是找到自己的IP:Post组合信息,然后格式化一个节点信息,调用afterLookup将信息存储到ServierMemberManager中。

文件寻址

文件寻址是Nacos集群模式下默认的寻址实现。文件寻址就是每个Nacos节点需要维护一个cluster.conf的文件,文件中默认填写每个成员的IP信息即可。

当Nacos节点启动时,会读取该文件的内容,然后将文件内的IP解析为节点列表,调用afterLookup将信息存储到ServierMemberManager中。如果发现集群扩缩容,那么需要修改每个Nacos节点下的cluster.conf文件,然后Nacos内部的文件变动监听中心会自动发现文件修改,重新读取文件内容、加载IP列表信息,更新新增节点。缺点是运维成本太大。

地址服务器寻址

地址服务器寻址模式是Nacos推荐的一种集群成员节点信息管理,该模式利用了简易的web服务器,用于管理cluster.conf文件的内容信息,这样运维只需要管理一份集群节点内容即可。而每个Nacos成员节点只需要向这个web节点定时请求当前最新的集群成员节点列表信息即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/971383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT 案例实战趋势分析面积图制作

面积图使用HTML,JS,Echarts 来完成代码可以使用ChatGPT AIGC 来实现代码编写。 完整的代码复制如下: <!DOCTYPE html> <html> <head><meta charset="utf-8"><script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.2.2/echa…

EasyPOI处理excel、CSV导入导出

1 简介 使用POI在导出导出excel、导出csv、word时代码有点过于繁琐&#xff0c;好消息是近两年在开发市场上流行一种简化POI开发的类库&#xff1a;easyPOI。从名称上就能发现就是为了简化开发。 能干什么&#xff1f; Excel的快速导入导出,Excel模板导出,Word模板导出,可以…

【kubernetes】Harbor部署及KubeSphere使用私有仓库Harbor

私有仓库Harbor https://goharbor.io/ 内容学习于马士兵云原生课程 Harbor部署 部署docker及docker-compose 略 获取Harbor安装文件 https://github.com/goharbor/harbor/releases/download/v2.4.1/harbor-offline-installer-v2.4.1.tgz tar -zxvf harbor-offline-installe…

线程安全缓存ConcurrentLinkedHashMap,Kotlin

线程安全缓存ConcurrentLinkedHashMap&#xff0c;Kotlin LinkedHashMap实现LRU缓存cache机制&#xff0c;Kotlin_zhangphil的博客-CSDN博客* * 基于Java LinkedList,实现Android大数据缓存策略 * 作者&#xff1a;Zhang Phil * 原文出处&#xff1a;http://blog.csdn.net/zha…

无法将类型为“Newtonsoft.Json.Linq.JObject”的对象转换为类型“Newtonsoft.Json.Linq.JArray”解决方法

对于“Newtonsoft.Json.Linq.JObject”的对象强制类型转换为类型“Newtonsoft.Json.Linq.JArray”报错 第一的图为对象{“*************”:“********”} 第二个图片为数组[{“…”:“…”}] 在我这里进行强制转换对象转换为类型“Newtonsoft.Json.Linq.JArray”报错. 那我们…

【java】【项目实战】[外卖十一]项目优化(Ngnix)

目录 一、Nginx概述 1、Nginx介绍 2、Nginx下载和安装 3、Nginx目录结构 二、Nginx命令 1、查看版本 2、检查配置文件正确性 3、启动和停止 4、重新加载配置文件 三、Nginx配置文件结构 1、全局块 2、events块 3、http块 四、Nginx具体应用 1、部署静态资源 2、…

mysql基于AES_ENCRYPTAES_DECRYPT实现密码的加密与解密

1.直接使用AES_ENCRYPT&&AES_DECRYPT函数导致的问题。 执行语句 select AES_ENCRYPT(cd123,key) 结果 加密过后的字符串是一串很奇怪的字符。 尝试使用上面加密过后的字符解密。 select AES_DECRYPT(u5£d|#,key) 结果 并未成功的解密 2.解决办法 使用 hex(…

kubernetes——RBAC鉴权

简介 基于角色的访问控制(RBAC)是一种基于组织中各个用户的角色来调节对计算机或网络资源的访问的方法。 目的&#xff1a;防止k8s里的pod&#xff08;会运行程序&#xff09;能随意获取整个集群里的信息和访问集群里的资源 概念 Rule&#xff1a;规则&#xff0c;一组属于…

图解SQL查询之模糊查询技巧:如何使用LIKE对数据进行筛选

模糊查询是一种特殊的条件查询方式&#xff0c;它允许根据模式匹配来查找符合特定条件的数据。在 SQL 中&#xff0c;我们使用 LIKE 关键字来进行模糊查询。在 LIKE 模糊查询中&#xff0c;有两种常用的通配符&#xff1a; 百分号&#xff08;%&#xff09;&#xff1a;表示任…

合宙Air724UG LuatOS-Air LVGL API控件-图片 (Image)

图片 (Image) 图片IMG是用于显示图像的基本对象类型&#xff0c;图像来源可以是文件&#xff0c;或者定义的符号。 示例代码 -- 创建图片控件 img lvgl.img_create(lvgl.scr_act(), nil) -- 设置图片显示的图像 lvgl.img_set_src(img, "/lua/luatos.png") -- 图片…

SpringMVC:从入门到精通

一、SpringMVC是什么 SpringMVC是Spring提供的一个强大而灵活的web框架&#xff0c;借助于注解&#xff0c;Spring MVC提供了几乎是POJO的开发模式【POJO是指简单Java对象&#xff08;Plain Old Java Objects、pure old java object 或者 plain ordinary java object&#xff0…

社区团购新玩法,生鲜蔬菜配货发货小程序商城

在当前的电商市场中&#xff0c;生鲜市场具有巨大的潜力和发展空间。为了满足消费者的需求&#xff0c;许多生鲜店正在寻找创新的方法来提高销售和客户满意度。其中&#xff0c;制作一个个性且功能强大的生鲜小程序商城是一个非常有效的策略。以下是在乔拓云平台上制作生鲜小程…

#systemverilog# 之 event region 和 timeslot 仿真调度(九)assign 赋值 和 always 组合赋值的调度区别

有时候,我们会发现一个问题,举个最简单的例子:比如将两个信号进行简单的异或运算。该逻辑运算,我们可以使用 assign 数据流建模完成,也可以使用always 组合逻辑过程赋值语句实现。那仿真工具在对它进行调度的时候,有什么区别吗? 不慌,今天,我们举个例子,来验证这一点…

2023 最新前端面试题 (HTML 篇)

1. src 和 href 的区别 src 用于替换当前元素&#xff08;引入&#xff09;&#xff0c;href 用于在当前文档和引用资源之间确立联系&#xff08;引用&#xff09; &#xff08;1&#xff09;src&#xff08;source&#xff09; 指向外部资源的位置&#xff0c;指向的内容将会嵌…

Python爬虫——新手使用代理ip详细教程

Python代理IP爬虫是一种可以让爬虫拥有更多网络访问权限的技术。代理IP的作用是可以为爬虫提供多个IP地址&#xff0c;从而加快其爬取数据的速度&#xff0c;同时也可以避免因为访问频率过高而被网站封禁的问题。本文将介绍如何使用Python实现代理IP的爬取和使用。 一、代理IP的…

ArrayList底层实现原理

ArrayList ArrayList最早出现在 JDK 1.2中&#xff0c;底层基于数组实现&#xff0c;它是一个动态数组列表结构的容器。 元素有序&#xff0c;可重复增删元素的速度慢。每次增加删除元素&#xff0c;都需要更改数组长度、拷贝元素及移动元素位置。查询元素的速度快。底层数据…

qt简易网络聊天室 数据库的练习

qt网络聊天室 服务器&#xff1a; 配置文件.pro QT core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exac…

酷派30/锋尚40/大观40S首发解锁BL+完美root权限+去除密码黑砖线刷修复

早前的中华酷联&#xff0c;随着时代的发展&#xff0c;酷派手机虽热发展的并没有其他手机那么快&#xff0c;但也 是坚强的活了下来。目前主打机型为Cool系列&#xff0c;最高为Cool30机型&#xff0c;并且发布酷派锋尚 40酷派大观40S&#xff0c;起头并进。该系列机型&#x…

动手学深度学习(五)Kaggle房价预测

Kaggle房价数据集&#xff0c;前四个为房价特征&#xff0c;最后一个为标签&#xff08;房价&#xff09;。 一、下载数据集 import numpy as np import pandas as pd import torch from torch import nn from d2l import torch as d2l import hashlib import os import tarfi…

XSS简单介绍

目录 一、认识XSS 1.XSS原理 2.XSS分类 二、XSS漏洞复现 1.搭建靶机进行复现 2.案例解析 2.1第一关 2.2第二关 2.3第三关 2.4第四关 一、认识XSS 1.XSS原理 XSS跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;…