服务注册发现与注册中心对比-Eureka,Consul,Zookeeper,Nacos对比
注册中心简介
微服务架构中,注册中心是最核心的基础服务之一,注册中心可以看做是微服务架构中的通信中心,当一个服务去请求另一个服务时,通过注册中心可以获取该服务的状态,地址等核心信息。
服务注册主要关系到三大角色:服务提供者、服务消费者、注册中心。
流程和原理
基础流程
服务启动时,将自身的网络地址等信息注册到注册中心,注册中心记录服务注册数据。
服务消费者从注册中心获取服务提供者的地址,并通过地址和基于特定的方式调用服务提供者的接口。
各个服务与注册中心使用一定机制通信。如果注册中心与服务长时间无法通信,就会注销该实例,这也称为服务下线,当服务重新连接之后,会基于一定的策略在线上线。
服务地址相关信息发生变化时,会重新注册到注册中心。这样,服务消费者就无需手工维护提供者的相关配置。
核心功能
通过上面的基本流程,不难发现一个注册中心需要具备哪些核心功能:
-
服务发现
服务发现是指服务在启动后,注册到注册中心,服务方提供自身的元数据,比如IP地址、端口、运行状况指标的Uri 、主页地址等信息。 -
服务记录
记录注册中心的服务的信息,例如服务名称、IP地址、端口等。服务消费方基于查询获取可用的服务实例列表。 -
动态管理服务
注册中心基于特定的机制定时测试已注册的服务,例如:默认的情况下会每隔30秒发送一次心跳来进行服务续约。通过服务续约来告知Server该Client仍然可用。正常情况下,如果Server在90 秒内没有收到Client 的心跳,Server会将Client 实例从注册列表中删除。
1、Eureka、Consul、Zookeeper三者异同点
它们的使用方式基本一致,只是导入依赖不同。
1.1 Nacos 与其它注册中心特性对比
Nacos 支持 AP(高可用) 和 CP(强一致性) 模式的切换
使用命令 curl -X PUT ‘$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP’ 进行切换
2、CAP理论
-
C:Consistency(强一致性)
一致性就是说,我们读写数据必须是一摸一样的。
比如一条数据,分别存在两个服务器中,server1和server2。
我们此时将数据a通过server1修改为数据b。此时如果我们访问server1访问的应该是b。
当我们访问server2的时候,如果返回的还是未修改的a,那么则不符合一致性,如果返回的是b,则符合数据的一致性。 -
A:Availability(可用性)
只要我对服务器,发送请求,服务器必须对我进行相应,保证服务器一直是可用的。 -
P:Partition tolerance(分区容错性)
一般来说,分布式系统是分布在多个位置的。比如我们的一台服务器在北京,一台在上海。可能由于天气等原因的影响。造成了两条服务器直接不能互相通信,数据不能进行同步。这就是分区容错。我们认为,分区容错是不可避免的。也就是说 P 是必然存在的。
CAP 理论关注粒度是数据,而不是整体系统设计的策略
CAP 理论的核心是:一个分布式系统不可能同时很好的满足一致性, 可用性和分区容错性这三个需求。
因此,根据CAP原理将NoSQL数据库分成了满足CA原则、满足CP原则和满足AP原则三大类:
- CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
- CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
- AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
3、eureka和zookeeper的cap理论
eureka是基于ap的。zookeeper是基于cp的。
3.1 Eureka
eureka的架构实现图如下:
3.1.1 eureka的基本原理
上图是来自eureka的官方架构图,这是基于集群配置的eureka;
- 处于不同节点的eureka通过Replicate进行数据同步
- Application Service为服务提供者
- Application Client为服务消费者
- Make Remote Call完成一次服务调用
服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
3.1.2 eureka的自我保护机制
在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。
为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制。
eureka.server.enable-self-preservation=true
它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。
3.1.3 eureka保证ap
eureka优先保证可用性。在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务 注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广 的网络分割故障,并实现“0”宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新 的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过 Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息。
4、zookeeper
zookeeper保证cp。
作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能 因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的。
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
4.1 基础描述
ZooKeeper是非常经典的服务注册中心中间件,在国内环境下,由于受到Dubbo框架的影响,大部分情况下认为Zookeeper是RPC服务框架下注册中心最好选择,随着Dubbo框架的不断开发优化,和各种注册中心组件的诞生,即使是RPC框架,现在的注册中心也逐步放弃了ZooKeeper。在常用的开发集群环境中,ZooKeeper依然起到十分重要的作用,Java体系中,大部分的集群环境都是依赖ZooKeeper管理服务的各个节点。
4.2 组件特点
从Zookeeper的数据结构特点看,并不是基于服务注册而设计的,ZooKeeper提供的命名空间与文件系统的名称空间非常相似,在数据结构上高度抽象为K-V格式,十分通用,说到这里不得不提一下Redis,也可以作为注册中心使用,只是用的不多。
ZooKeeper组件支持节点短暂存在,只要创建znode的会话处于活动状态,这些znode就会存在,会话结束时,将删除znode。Dubbo框架正是基于这个特点,服务启动往Zookeeper注册的就是临时节点,需要定时发心跳到Zookeeper来续约节点,并允许服务下线时,将Zookeeper上相应的节点删除,同时Zookeeper使用ZAB协议虽然保证了数据的强一致性。
5、eureka和zookeeper的区别总结
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。Eureka作为单纯的服务注册中心来说要比zookeeper更加“专业”,因为注册服务更重要的是可用性,我们可以接受短期内达不到一致性的状况。
6、Consul组件
6.1 基础描述
Consul是用于服务发现和配置的工具。Consul是分布式的,高度可用的,并且具有极高的可伸缩性,而且开发使用都很简便。它提供了一个功能齐全的控制面板,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心、ServiceMesh。Consul在设计上把很多分布式服务治理上要用到的功能都包含在内了。
6.2 组件特点
Consul提供多个数据中心的支持,基于Fabio做负载均衡,每个数据中心内,都有客户端和服务端的混合构成。预计有三到五台服务端。可以在失败和性能的可用性之间取得良好的平衡。数据中心中的所有节点都参与八卦协议。这意味着有一个八卦池,其中包含给定数据中心的所有节点。这有几个目的:首先,不需要为客户端配置服务器的地址;发现是自动完成的。其次,检测节点故障的工作不是放在服务器上,而是分布式的。这使得故障检测比天真的心跳方案更具可扩展性。第三,它被用作消息传递层,用于在诸如领导者选举等重要事件发生时进行通知。
7、Nacos组件
7.1 基础描述
Nacos致力于发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。Nacos更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构(例如微服务范式、云原生范式)的服务基础设施。Nacos支持作为RPC注册中心,例如:支持Dubbo框架;也具备微服务注册中心的能力,例如:SpringCloud框架。
7.2 组件特点
Nacos在经过多年生产经验后提炼出的数据模型,则是一种服务-集群-实例的三层模型。如上文所说,这样基本可以满足服务在所有场景下的数据存储和管理,数据模型虽然相对复杂,但是并不强制使用数据结构的风格,大多数应用场景下,和Eureka数据模型是类似的。
Nacos提供数据逻辑隔离模型,用户账号可以新建多个命名空间,每个命名空间对应一个客户端实例,这个命名空间对应的注册中心物理集群是可以根据规则进行路由的,这样可以让注册中心内部的升级和迁移对用户是无感知的。