为了账号安全,请及时绑定邮箱和手机立即绑定

面试官:如果公司要自研一套分布式注册中心,说说你的设计思路?

标签:
微服务

1. 注册中心是个啥?

服务注册中心,它是微服务实例及该服务元数据的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。

服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求。

2. 何为CAP设计原则,及BASE理论?

一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)

分区容忍性(P):就是当由于网络故障之时,导致集群里的机器不能保证其互相保持正常通信之时,每台机器所具备各自为战能力,保证服务能否正常使用

CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。

如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备

但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问

此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足。必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足。

BASE 说的俗一点CA都退而求其次,这就是所谓的最终一致性。

3. 面对品种繁多的注册中心组件,又该如何进行技术选型呢?

基于上面的理论铺垫,我就拿目前工作中最常用的Eureka和ZooKeeper进行对比。

我直接放上两幅图:

https://img1.sycdn.imooc.com//5d5fd45c0001b21c06730282.jpg

上图是Eureka集群原理图,采用peer-to-peer的架构集群模式,部署一个集群,但是集群里每个机器的地位是对等的

各个服务可以向任何一个Eureka实例服务注册和服务发现,集群里任何一个Euerka实例接收到写请求之后,会自动同步给其他所有的Eureka实例 

但是他就会有一个问题,可能还没同步数据过去,结果自己就死了

此时还是可以继续从别的机器上拉取注册表,但是看到的就不是最新的数据了,但是保证了可用性 ,此种状态就遵循了BASE理论,即最终一致性。

架构图如下所示:

https://img1.sycdn.imooc.com//5d5fd45f000111a506910303.jpg

ZooKeeper是有一个leader节点会接收数据, 然后同步写其他节点,一旦leader挂了,要重新选举leader

这个过程里为了保证C,就牺牲了A,不可用一段时间,但是一个leader选举好了,那么就可以继续写数据了,保证一致性

说到这里,笔者觉得现实场景适用真正意义上的AP几乎不存在,一个完全不要求数据统一的场景笔者确实没经历过,再说直白一点这不就是脑裂了吗。。。

接下来我继续从两个方面说说他俩的区别:

(1)服务注册发现的时效性

zk,时效性更好,注册或者是挂了,一般秒级就能感知到

eureka,默认配置非常糟糕,服务发现感知要到几十秒,甚至分钟级别

上线一个新的服务实例,到其他人可以发现他,极端情况下,可能要1分钟的时间,ribbon去获取每个服务上缓存的eureka的注册表进行负载均衡

服务故障,隔60秒才去检查心跳,发现这个服务上一次心跳是在60秒之前,隔60秒去检查心跳,超过90秒没有心跳,才会认为他死了,2分钟都过去

30秒,才会更新缓存,30秒,其他服务才会来拉取最新的注册表

三分钟都过去了,如果你的服务实例挂掉了,此时别人感知到,可能要两三分钟的时间,一两分钟的时间,很漫长

(2)容量

zk,不适合大规模的服务实例,因为服务上下线的时候,需要瞬间推送数据通知到所有的其他服务实例

所以一旦服务规模太大,到了几千个服务实例的时候,会导致网络带宽被大量占用

eureka,也很难支撑大规模的服务实例,因为每个eureka实例都要接受所有的请求,实例多了压力太大,扛不住,也很难到几千服务实例

之前dubbo技术体系都是用zk当注册中心,spring cloud技术体系都是用eureka当注册中心这两种是运用最广泛的

但是现在很多中小型公司以spring cloud居多,所以后面基于eureka说一下服务注册中心的生产优化

4. 如果要对注册中心进行自研又该注意哪些呢?

既然要自研注册中心了 那么肯定要开发其对应的客户端以及服务端 , 两端都要考虑各自的东西

客户端:

服务拉取:每次肯定不是全量拉取,这个时候你就要思考服务端有可能提供一个最近的变更队列,供客户端拉取

并且一定要有一个用于校验拉取增量数据之后数据是否完整的指标数据,用于校验数据是否有异常,异常则做一次全量拉取。

心跳发送:告诉服务端自己是否存活进行服务的一个续约。

服务下线:进行服务下线,修改运行状态的标记位,当然这个标记位要保证其可见性。

服务端:

服务注册:要对java并发包的拥有着深刻的理解,在服务注册表一定一定要注意读写并发控制,既要保证线程安全,同时也要降低锁的争用,最大限度保证其性能。

对所注册服务的健康检查:在单位时间内,如果所注册服务没进行服务的续约,则要将该服务下线。

集群同步:要根据自己实际的业务需求,制定合适的集群架构方案,在这个前提下,在制定合适的数据传输方案,保证吞吐量。

还有就是要考虑,注册中心与主流技术框架兼容性。

END

石杉的架构笔记(id:shishan100)                       
作者:中华石杉,多年BAT架构经验倾囊相授 

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
7626
获赞与收藏
1.1万

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消