nacos整理
Nacos定位
一个更易于构建云原生应用的服务发现与管理、动态配置服务和动态DNS服务平台。
动态配置服务:动态配置服务让您能够以中心化、外部化和动态化的方式管理所有环境的配置。动态配置消除了配置变更时重新部署应用和服务的需要。配置中心化管理让实现无状态服务更简单,也让按需弹性扩展服务更容易。
服务发现与管理:动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos 支持 DNS-Based 和 RPC-Based(Dubbo、gRPC)模式的服务发现。Nacos 也提供实时健康检查,以防止将请求发往不健康的主机或服务实例。借助 Nacos,您可以更容易地为您的服务实现断路器。
动态DNS服务:通过支持权重路由,动态 DNS 服务能让您轻松实现中间层负载均衡、更灵活的路由策略、流量控制以及简单数据中心内网的简单 DNS 解析服务。动态 DNS 服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以消除耦合到厂商私有服务发现 API 上的风险。
Nacos优势
易用:简单的数据模型,标准的 restfulAPI,易用的控制台,丰富的使用文档。
稳定:99.9% 高可用,支持具有数百万服务的大规模场景,具备企业级 SLA 的开源产品。
实时:数据变更毫秒级推送生效。
规模:十万级服务/配置,百万级连接,具备强大扩展性。
Nacos 生态
Nacos 几乎支持所有主流语言,其中 Java/Golang/Python 已经支持 Nacos 2.0 长链接协议。
基础模型y
- Nacos 提供可视化的控制台,可以对配置进行发布、更新、删除、灰度、版本管理等功能。
- SDK 可以提供发布配置、更新配置、监听配置等功能。
- SDK 通过 GRPC 长连接监听配置变更,Server 端对比 Client 端配置的 MD5 和本地 MD5 是否相等,不相等推送配置变更。
- SDK会保存配置的快照,当服务端出现问题的时候从本地获取。
关键概念
Namespace:用来进行资源隔离,支持多套环境配置,可以根据不同的环境来创建 Namespace 。比如开发环境、测试环境、线上环境,我们就创建对应的 Namespace(dev、test、prod)。
Data ID:Nacos 中的某个配置集的 ID。
Group:Nacos 中的一组配置集。
例如:
三套环境下多个A、B、C三个租户配置,如下:
Namespace为dev、test、prod。
Group为Group_A、Group_B、Group_C三组group。
Data ID为application.properties。
Namespace | Group | Data ID |
dev | Group_A | application.properties |
Group_B | application.properties | |
Group_C | application.properties | |
test | Group_A | application.properties |
Group_B | application.properties | |
Group_C | application.properties | |
prod | Group_A | application.properties |
Group_B | application.properties | |
Group_C | application.properties |
配置存储模型
1、config_info:存储配置信息的主表,里面包含 dataId、groupId、content、tenantId、encryptedDataKey 等数据。
2、config_info_beta:灰度测试的配置信息表,存储的内容和 config_info 基本相似。有一个 beta_ips 字段用于客户端请求配置时判断是否是灰度的ip。
3、config_tags_relation:配置的标签表,在发布配置的时候如果指定了标签,那么会把标签和配置的关联信息存储在该表中。
4、his_config_info:配置的历史信息表,在配置的发布、更新、删除等操作都会记录一条数据,可以做多版本管理和快速回滚。、
Nacos 一致性协议
集群模式下,需要考虑如何保障各个节点之间的数据一致性以及数据同步。
算法:Raft 以及 Distro。
强一致性共识算法,当前工业生产中,最多使用的就是 Raft 协议,Raft 协议更容易让人理解,并且有很多成熟的工业算法实现,比如蚂蚁金服的 JRaft、Zookeeper 的 ZAB、Consul 的 Raft、百度的 braft、Apache Ratis;
Distro 算法是集 Gossip 以及 Eureka 协议的优点并加以优化而出来的。对于原生的Gossip,由于随机选取发送消息的节点,也就不可避免的存在消息重复发送给同一节点的情况,增加了网络的传输的压力,也给消息节点带来额外的处理负载,而 Distro 算法引入了权威 Server 的概念,每个节点负责一部分数据以及将自己的数据同步给其他节点,有效的降低了消息冗余的问题。
Nacos中任何使用一致性协议的,都只需要使用 getData 以及 write 方法即可。
写操作
对于一个已经启动完成的 Distro 集群,在一次客户端发起写操作的流程中,当注册非持久化的实例的写请求打到某台 Nacos 服务器时,整个步骤包括几个部分(图中从上到下顺序):
- 前置的 Filter 拦截请求,并根据请求中包含的 IP 和 port 信息计算其所属的 Distro 责任节点,并将该请求转发到所属的 Distro 责任节点上。
- 责任节点上的 Controller 将写请求进行解析。
- Distro 协议定期执行 Sync 任务,将本机所负责的所有的实例信息同步到其他节点上。
读操作
由于每台机器上都存放了全量数据,因此在每一次读操作中,Distro 机器会直接从本地拉取数据。快速响应。
这种机制保证了 Distro 协议可以作为一种 AP 协议,对于读操作都进行及时的响应。在网络分区的情况下,对于所有的读操作也能够正常返回;当网络恢复时,各个 Distro 节点会把各数据分片的数据进行合并恢复。
一致性总结
Distro 协议是 Nacos 对于临时实例数据开发的一致性协议。其数据存储在缓存中,并且会在启动时进行全量数据同步,并定期进行数据校验。
在 Distro 协议的设计思想下,每个 Distro 节点都可以接收到读写请求。所有的 Distro 协议的请求场景主要分为三种情况:
1、当该节点接收到属于该节点负责的实例的写请求时,直接写入。
2、当该节点接收到不属于该节点负责的实例的写请求时,将在集群内部路由,转发给对应的节点,从而完成读写。
3、当该节点接收到任何读请求时,都直接在本机查询并返回(因为所有实例都被同步到了每台机器上)。
Distro 协议作为 Nacos 的内嵌临时实例一致性协议,保证了在分布式环境下每个节点上面的服务信息的状态都能够及时地通知其他节点,可以维持数十万量级服务实例的存储和一致性。
Nacos长链接
为什么使用长链接?
异步 Servlet缺点:(数据一致性:基于MD5比对一致性)http短连接,30秒定期创建销毁连接,GC压力大。
HTTP/UDP缺点:(数据一致性:UDP 推送 + 补偿查询)丢包,云架构下无法反向推送。
长链接核心诉求
客户端
1、实时感知连接建立,连接断开事件
2、客户端调用服务端支持同步阻塞,异步future,异步 callback 三种模式
3、选址/服务发现
4、响应服务端连接重置消息进行连接切换
服务端
1、实时感知连接建立,连接断开事件
2、服务端往客户端主动进行数据推送,需要客户端进行 Ack 返回以支持可靠推送,并且需要进行失败重试
3、服务端主动推送负载调节能力
负载均衡
-
常见的负载均衡策略:随机,hash,轮询,权重,最小连接数,最快响应速度等
- 在短连接中,因为连接快速建立销毁,“随机,hash,轮询,权重”四种方式大致能够保持整体是均衡的,服务端重启也不会影响整体均衡,其中“最小连接数,最快响应速度”是有状态的算法,因为数据延时容易造成堆积效应;
- 长连接因为建立连接后,如果没有异常情况出现,连接会一直保持,断连后需要重新选择一个新的服务节点,当出现服务节点发布重启后,最终连接会出现不均衡的情况出现,“随机,轮询,权重”的策略在客户端重连切换时可以使用,“最小连接数,最快响应速度”和短连接一样也会出现数据延时造成堆积效应。
- 长连接和短连接的一个主要差别在于在整体连接稳定时,服务端需要一个rebalance的机制,将集群视角的连接数重新洗牌分配,趋向另外一种稳态。
- 客户端随机+服务端柔性调整
核心的策略是客户端+服务端双向调节策略,客户端随机选择+服务端运行时柔性调整。
- 客户端随机:客户端在启动时获取服务列表,按照随机规则进行节点选择,逻辑比较简单,整体能够保持随机。
- 服务端柔性-人工管控方案:实现人工调节每个 Server 节点的连接数,工触发reblance,人工削峰填谷。
- 服务端柔性-自动化管控方案:基于每个 server 间连接数及负载自动计算节点合理连接数,自动触发reblance,自动削峰填谷。实现周期较长,比较依赖算法准确性。
连接生命周期
心跳保活机制
理解 TCP Keepalive: https://blog.csdn.net/chrisnotfound/article/details/80111559
grpc keepalive :https://blog.csdn.net/zhaominpro/article/details/103127023
netty 的心跳检测:https://www.cnblogs.com/rickiyang/p/12792120.html
- 低成本快速感知:客户端需要在服务端不可用时尽快地切换到新的服务节点,降低不可用时间,并且能够感知底层连接切换事件,重置上下文;服务端需要在客户端断开连接时剔除客户端连接对应的上下文,包括配置监听,服务订阅上下文,并且处理客户端连接对应的实例上下线。
- 客户端正常重启:客户端主动关闭连接,服务端实时感知
- 服务端正常重启 : 服务端主动关闭连接,客户端实时感知
- 防抖:
- 网络短暂不可用: 客户端需要能接受短暂网络抖动,需要一定重试机制,防止集群抖动,超过阈值后需要自动切换server,但要防止请求风暴。
- 断网演练:断网场景下,以合理的频率进行重试,断网结束时可以快速重连恢复。
长链接选型对比
grpc | WebSocket | tbremote | Rsocket | netty | mina | ||
---|---|---|---|---|---|---|---|
客户端通信 | sync | 支持 | 支持 | 支持 | 支持 | 无rpc语意 | 无rpc语意 |
future | 支持 | 不支持 | 支持 | 支持 | 无rpc语意 | 无rpc语意 | |
callback | 结合 guava实现 | 不支持 | 支持 | 支持 (依赖jdk 1.8+ completableFuture) |
无rpc语意 | 无rpc语意 | |
服务端推送 | sync | 无ack | 支持 | 支持 | 支持 | 无rpc语意 | 无rpc语意 |
future | 不支持 | 支持 | 支持 | 支持 | 无rpc语意 | 无rpc语意 | |
callback | 不支持 | 支持 | 支持 | 支持 | 无rpc语意 | 无rpc语意 | |
连接生命周期 | 客户端感知断连 | 无 (基于stream流 error complete事件可实现) |
支持 | 支持 | 支持 | 支持 | 支持 |
服务端感知断连 | 支持 (官方不建议使用) |
支持 | 支持 | 支持 | 支持 | 支持 | |
心跳保活 | 应用层自定义,ping-pong消息 | 应用层自定义,单byte ack | 自定义keepalive frame | TCP+ 自定义 | 自定义 keepalive filter | ||
性能 | tps | ||||||
安全性 | TLS | TLS | TLS | TLS | TLS | TLS | |
其他 | Github Star/Issue | 最高go版本:11.9K/124 issue | 最高java版本:1.8/47 issue | ||||
备注 | 服务端推送Ack自建 | 阿里内部基于mina实现的私有协议 | rsocket私有协议,社区活跃度,用户数一般 | 需要自定义rpc协议 | 需要自定义rpc协议 |