赞
踩
在分析eureka、zookeeper、nacos区别前,需要先清楚服务注册、服务发现是什么?
在传统的系统部署中,服务运行在一个固定的已知的 IP 和端口上,如果一个服务需要调用另外一个服务,可以通过地址直接调用。但是,在微服务架构下,服务实例的启动和销毁是很频繁的,服务地址在动态的变化,而且,由于自动扩展,失败和更新,服务实例的配置也经常变化,所以,无法通过硬编码服务地址的方法来访问该服务。
因此,需要设置专门的服务来对实时变化的服务状态进行同步。
目前微服务的服务发现机制主要包含三个角色:服务提供者、服务消费者和服务注册表
服务提供者(Service Provider):服务启动时将服务信息注册到服务注册表,服务退出时将服务注册表的服务信息删除掉。
服务消费者(Service Consumer):从服务注册表获取服务提供者的最新网络位置等服务信息,维护与服务提供者之间的通信。
服务注册表(Service Registry):联系服务提供者和服务消费者的桥梁,维护服务提供者的最新网络位置等服务信息。
服务发现机制的关键部分是服务注册表(Service Registry)。服务注册表提供管理和查询服务注册信息的API。当服务提供者的实例发生变更时(新增/删除服务),服务注册表需要通知服务消费者同步最新的服务实例地址列表。目前大多数的微服务框架使用Netflix Eureka、Etcd、Consul、Apache Zookeeper、nacos等作为服务注册表。
服务注册表是一个可用的服务实例的数据库。服务注册表提供了一个管理API和一个查询API。服务实例的注册和注销通过管理API实现,查询API用来寻找可用的服务实例。
服务注册表是一个分布式的kv数据库,因此,存在CAP问题。根据CAP原则:分布式系统不能同时支持 C(一致性)、A(可用性)、P(分区容错性)需要根据自己的实际业务需求选择CAP的其中两个。
Eureka Server 集群当中的每个节点都是通过 Replicate(即复制)来同步数据,没有主节点和从节点之分,所有节点都是平等而且数据都保持一致。因为结点之间是通过异步方式进行同步数据,不保证强一致性,保证可用性,所以是 AP。
假设 Eureka Server 已经启动,Eureka Client(服务提供者)启动时把服务注册到 Eureka Server;
Eureka Client(服务提供者)每 30 秒(默认可配置)向 Eureka Sever 发 http 请求(即心跳),即服务续约;
Eureka Server 90 秒没有收到向 Eureka Client(服务提供者)的心跳请求,则统计 15 分钟内是否存在 85% 的 Eureka Client(服务提供者)没有发心跳,如果是则进行自我保护状态(比如网络不稳定),如果不是则剔除该 Eureka Client(服务提供者)实例;
Eureka Client(服务消费者)定时调用 Eureka Server 接口获取服务列表更新本地缓存;
Eureka Client(服务消费者)远程调用服务时,先从本地缓存找,如果找到则直接发起服务调用,如果没有则到 Eureka Server 获取服务列表缓存到本地后再发起服务调用;
Eureka Client(服务提供者)应用关闭时会发 HTTP 请求到 Eureka Server,服务端接受请求后把该实例剔除。
在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。
为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制。
-
- eureka.server.enable-self-preservation=true
它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。
PeerEurekaNodes
管理其他服务器节点,并通过 HTTP 进行通信。Zookeeper 支持 CP,当集群中如果有节点宕机则需要选举 leader(FastLeaderElection),选举过程需要 30 至 120 秒,选举过程时zk集群不可用(不能使用服务注册、服务发现),牺牲时间来保证数据一致性。
假设 ZK 已经启动,服务提供者启动时把服务注册到 ZK 注册中心;
ZK 注册中心和服务提供者之间建立一个 Socket 长连接,ZK 注册中心定时向每个服务提供者发数据包,如果服务提供者没响应,则剔除该服务提供者实例,把更新后的服务列表发送给所有服务消费者(即通知);
服务消费者启动时到 ZK 注册中心获取一份服务列表缓存到本地供以后使用;
服务消费者远程调用服务时,先从本地缓存找,如果找到则直接发起服务调用,如果没有则到 ZK 注册中心获取服务列表缓存到本地后再发起服务调用;
当其中一个服务提供者宕机或正常关闭时,ZK 注册中心会把该节点剔除,并通知所有服务消费者更新本地缓存;
当这个服务提供者正常启动后,ZK 注册中心也能感知到,并通知所有服务消费者更新本地缓存。
Nacos从1.0版本选择Ap和CP混合形式实现注册中心,默认情况下采用Ap保证服务可用性,CP形式底层采用Raft协议保证数据的一致性问题。
假设 Nacos Server 已经启动,服务提供者启动时把服务注册到 Nacos 注册中心;
服务提供者注册成功后,定时发 http 请求(即心跳)到注册中心,证明自身服务实例可用;
如果注册中心长时间没有收到服务提供者的心跳请求,则剔除该实例;
服务消费者发现服务支持两种方式,一种是主动请求注册中心获取服务列表(不推荐),一种是订阅注册中心的服务并提交一个 Listener,如果注册中心的服务有变更,由 Listener 来通知服务消费者更新本地服务列表;
服务消费者获取服务相关信息进行远程调用。
经测试,在nacos都停止的情况下,consumer端依然可以通过本地服务列表访问provider。
Distro 协议同步
长轮询或定时拉取:
对比内容 | Nacos | Eureka | ZooKeeper |
一致性协议 | CP+AP | AP | CP |
健康检查 | TCP/HTTP/MYSQL/Client Beat | Client Beat | Keep Alive |
负载均衡策略 | 权重/metadata/Selector | Ribbon | - |
雪崩保护 | 有 | 有 | 无 |
自动注销实例 | 支持 | 支持 | 支持 |
访问协议 | HTTP/DNS | HTTP | TCP |
监听支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 支持 | 不支持 | 不支持 |
Spring Cloud集成 | 支持 | 支持 | 支持 |
Dubbo集成 | 支持 | 不支持 | 支持 |
Kubernetes集成 | 支持 | 不支持 | 不支持 |
AP可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像CP那样使整个注册服务瘫痪。AP方式作为单纯的服务注册中心来说要比CP方式更加“专业”,因为注册服务更重要的是可用性,我们可以接受短期内达不到一致性的状况。
Eureka 不能支撑大量服务实例,因为 Eureka 的每个节点数据都一致,会产生大量的心跳检查等等导致并发性能低下,ZooKeeper 的频繁上下线通知会导致性能下降,而 Nacos 可以支持大量服务实例又不丢性能,据说服务数量能达到 10 万以上。
服务发现后,客户端需要调用服务,这是需要进行负载均衡,具体原理可参考负载均衡使用_主流的负载方案分为以下两种: 集中式负载均衡,在消费者和服务提供方中间使用独立-CSDN博客
参考文章
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。