美文网首页Java架构师系列
架构设计之微服务注册中心选型

架构设计之微服务注册中心选型

作者: Java架构师CAT | 来源:发表于2019-05-20 10:48 被阅读0次

    ZooKeeper、Consul、Eureka和新生的Nacos 都实现了注册中心的功能。那么从哪些方面进行对比,进而选型呢?

    服务发现

    数据模型

    注册中心的核心数据是服务的名字和它对应的网络地址,当服务注册了多个实例时,我们需要对不健康的实例进行过滤或者针对实例的一些特征进行流量的分配,那么就需要在实例上存储一些例如健康状态、权重等属性。随着服务规模的扩大,渐渐的又需要在整个服务级别设定一些权限规则、以及对所有实例都生效的一些开关,于是在服务级别又会设立一些属性。再往后,我们又发现单个服务的实例又会有划分为多个子集的需求,例如一个服务是多机房部署的,那么可能需要对每个机房的实例做不同的配置,这样又需要在服务和实例之间再设定一个数据级别。

    数据一致性

    数据一致性是分布式系统永恒的话题,Paxos协议的艰深更让数据一致性成为程序员大牛们吹水的常见话题。不过从协议层面上看,一致性的选型已经很长时间没有新的成员加入了。目前来看基本可以归为两家:一种是基于Leader的非对等部署的单点写一致性,一种是对等部署的多写一致性。

    nacos一致性协议

    负载均衡

    负载均衡严格的来说,并不算是传统注册中心的功能。一般来说服务发现的完整流程应该是先从注册中心获取到服务的实例列表,然后再根据自身的需求,来选择其中的部分实例或者按照一定的流量分配机制来访问不同的服务提供者,因此注册中心本身一般不限定服务消费者的访问策略。Eureka、Zookeeper包括Consul,本身都没有去实现可配置及可扩展的负载均衡机制,Eureka的负载均衡是由ribbon来完成的,而Consul则是由Fabio做负载均衡。

    客户端侧负载均衡

    服务端的负载均衡,给服务提供者更强的流量控制权,但是无法满足不同的消费者希望使用不同负载均衡策略的需求。而不同负载均衡策略的场景,确实是存在的。而客户端的负载均衡则提供了这种灵活性,并对用户扩展提供更加友好的支持。但是客户端负载均衡策略如果配置不当,可能会导致服务提供者出现热点,或者压根就拿不到任何服务提供者。

    服务端侧负载均衡

    健康检查

    Zookeeper和Eureka都实现了一种TTL的机制,就是如果客户端在一定时间内没有向注册中心发送心跳,则会将这个客户端摘除。Eureka做的更好的一点在于它允许在注册服务的时候,自定义检查自身状态的健康检查方法。这在服务实例能够保持心跳上报的场景下,是一种比较好的体验,在Dubbo和SpringCloud这两大体系内,也被培养成用户心智上的默认行为。Nacos也支持这种TTL机制,不过这与ConfigServer在阿里巴巴内部的机制又有一些区别。Nacos目前支持临时实例使用心跳上报方式维持活性,发送心跳的周期默认是5秒,Nacos服务端会在15秒没收到心跳后将实例设置为不健康,在30秒没收到心跳时将这个临时实例摘除。

    客户端健康检查和服务端健康检查有一些不同的关注点。客户端健康检查主要关注客户端上报心跳的方式、服务端摘除不健康客户端的机制。而服务端健康检查,则关注探测客户端的方式、灵敏度及设置客户端健康状态的机制。从实现复杂性来说,服务端探测肯定是要更加复杂的,因为需要服务端根据注册服务配置的健康检查方式,去执行相应的接口,判断相应的返回结果,并做好重试机制和线程池的管理。这与客户端探测,只需要等待心跳,然后刷新TTL是不一样的。同时服务端健康检查无法摘除不健康实例,这意味着只要注册过的服务实例,如果不调用接口主动注销,这些服务实例都需要去维持健康检查的探测任务,而客户端则可以随时摘除不健康实例,减轻服务端的压力。

    Nacos的健康检查

    虽然大部分用户用到的性能不高,但是他们仍然希望选用的产品的性能越高越好。影响读写性能的因素很多:一致性协议、机器的配置、集群的规模、存量数据的规模、数据结构及读写逻辑的设计等等。在服务发现的场景中,我们认为读写性能都是非常关键的,但是并非性能越高就越好,因为追求性能往往需要其他方面做出牺牲。Zookeeper在写性能上似乎能达到上万的TPS,这得益于Zookeeper精巧的设计,不过这显然是因为有一系列的前提存在。首先Zookeeper的写逻辑就是进行K-V的写入,内部没有聚合;其次Zookeeper舍弃了服务发现的基本功能如健康检查、友好的查询接口,它在支持这些功能的时候,显然需要增加一些逻辑,甚至弃用现有的数据结构;最后,Paxos协议本身就限制了Zookeeper集群的规模,3、5个节点是不能应对大规模的服务订阅和查询的。

     Nacos性能与容量报告

    易用性

    易用性也是用户比较关注的一块内容。产品虽然可以在功能特性或者性能上做到非常先进,但是如果用户的使用成本极高,也会让用户望而却步。易用性包括多方面的工作,例如API和客户端的接入是否简单,文档是否齐全易懂,控制台界面是否完善等。对于开源产品来说,还有一块是社区是否活跃。在比较Nacos、Eureka和Zookeeper在易用性上的表现时,我们诚邀社区的用户进行全方位的反馈,因为毕竟在阿里巴巴集团内部,我们对Eureka、Zookeeper的使用场景是有限的。从我们使用的经验和调研来看,Zookeeper的易用性是比较差的,Zookeeper的客户端使用比较复杂,没有针对服务发现的模型设计以及相应的API封装,需要依赖方自己处理。对多语言的支持也不太好,同时没有比较好用的控制台进行运维管理。

    集群扩展性

    集群扩展性的另一个方面是多地域部署和容灾的支持。当讲究集群的高可用和稳定性以及网络上的跨地域延迟要求能够在每个地域都部署集群的时候,我们现有的方案有多机房容灾、异地多活、多数据中心等。

    Nacos的多机房部署和容灾

    首先是双机房容灾,基于Leader写的协议不做改造是无法支持的,这意味着Zookeeper不能在没有人工干预的情况下做到双机房容灾。在单机房断网情况下,使机房内服务可用并不难,难的是如何在断网恢复后做数据聚合,Zookeeper的单点写模式就会有断网恢复后的数据对账问题。Eureka的部署模式天然支持多机房容灾,因为Eureka采用的是纯临时实例的注册模式:不持久化、所有数据都可以通过客户端心跳上报进行补偿。上面说到,临时实例和持久化实例都有它的应用场景,为了能够兼容这两种场景,Nacos支持两种模式的部署,一种是和Eureka一样的AP协议的部署,这种模式只支持临时实例,可以完美替代当前的Zookeeper、Eureka,并支持机房容灾。另一种是支持持久化实例的CP模式,这种情况下不支持双机房容灾。

    Nacos的多数据中心方案

    用户扩展性

    在框架的设计中,扩展性是一个重要的设计原则。Spring、Dubbo、Ribbon等框架都在用户扩展性上做了比较好的设计。这些框架的扩展性往往由面向接口及动态类加载等技术,来运行用户扩展约定的接口,实现用户自定义的逻辑。在Server的设计中,用户扩展是比较审慎的。因为用户扩展代码的引入,可能会影响原有Server服务的可用性,同时如果出问题,排查的难度也是比较大的。设计良好的SPI是可能的,但是由此带来的稳定性和运维的风险是需要仔细考虑的。在开源软件中,往往通过直接贡献代码的方式来实现用户扩展,好的扩展会被很多人不停的更新和维护,这也是一种比较好的开发模式。Zookeeper和Eureka目前Server端都不支持用户扩展,一个支持用户扩展的服务发现产品是CoreDNS。CoreDNS整体架构就是通过插件来串联起来的,通过将插件代码以约定的方式放到CoreDNS工程下,重新构建就可以将插件添加到CoreDNS整体功能链路的一环中。

    所有产品都应该尽量支持用户运行时扩展,这需要Server端SPI机制设计的足够健壮和容错。Nacos在这方面已经开放了对第三方CMDB的扩展支持,后续很快会开放健康检查及负载均衡等核心功能的用户扩展。目的就是为了能够以一种解耦的方式支持用户各种各样的需求。

    尾声

    为了能让大家对注册中心产品整体的差异有一个快速的总览,我们制作了下面这个表格:


    为了广大程序员们能够成功进阶架构师,我特地精心准备了Java架构师的学习视频,现免费分享,进企鹅裙693845731与大佬交流,资料免费领

    需要其他资源的也可以关注公众号【动力节点Java资源库】,回复 jgs 即可

    相关文章

      网友评论

        本文标题:架构设计之微服务注册中心选型

        本文链接:https://www.haomeiwen.com/subject/sushzqtx.html