java八股文面试[SpringCloud]——如何设计一个注册中心

框架:

需要考虑的点:

服务注册
注册表结构设计
服务发现
服务订阅
服务推送
健康检查
集群同步:设计到数据同步,数据同步我们有哪些协议 raft 、distro、ZAB

一、选型:

注册中心作为一个服务注册和发现的服务,必须是高可用的,所以应该是AP模型

作为CP模型的zk和etcd,在小规模应用情况下低于千级服务,可以使用,不过跨机房时容易因为网络问题导致注册服务不可用,另外CP模型都是一主多从(选主)情况,写入操作只能通过主节点,所以如果服务过多,服务的心跳检查机制是一个比较频繁的动作,会导致主写入瓶颈;由于zk采用zab协议、etcd采用raft协议进行数据同步,都是从主同步到多个节点,高并发写入时,容易出现瓶颈;

作为AP模型的eureka,1.0开源,2.0不再开源,后续无法升级。阿里开源的nacos也是AP模型,可以作为一个方案,蚂蚁金服的sofa也可以考虑。

二、自研考虑事项

1、注册中心提供节点信息的存储与扩展,使用mysql持久化,redis做缓存

2、提供权重设置,分组设置,可区分核心应用和非核心应用调用不同的分组,互不干扰

3、基于netty通过tcp协议,提供者和消费者与注册中心保持长连接

4、注册中心集群节点间可采用gossip协议维护集群节点的自动发现、转移和心跳

三 如何设计一个注册中心

我们需要解决如下几个问题:

  • 服务如何注册
  • consumer如何知道provider
  • 服务注册中心如何高可用
  • 服务上下线,消费端如何动态感知

3.1 服务注册

服务列表保存通常有三种方式:本地内存、数据库、第三方缓存系统

注册上去后,consumer需要服务地址的时候,就可以用相应key去注册中心获取对应的服务列表。

同一个服务注册中心,我们可以注册多个服务,比如用户服务、商品服务、订单服务...

3.2 服务消费

onsumer端通过key获取指定的服务地址列表。

以上的还是蛮简单的吧,简单来说,我们就是引用了一个第三方的服务来存放我们的服务提供者列表。并且以key-value的形式存储,key我们可以理解为服务名称,value就是服务实例列表。

注册中心高可用

高可用无非就是做集群,我们可以对注册中心部署多个节点。在消费端consumer只需要知道一个服务注册中心集群地址cluster-url即可。

动态感知服务上下线

consumer拿到服务列表后,会把服务列表保存起来,保存到本地缓存里

consumer通过一定的负载均衡算法,选择出一个地址,最后发起远程的调用。

如果我们的服务节点挂掉一个了,怎么办?

此时,服务注册中心的服务列表还是之前的列表,如果consumer调用到过掉的节点上,那岂不是会出问题呀。

所以,我们的服务注册中心需要知道哪个服务节点挂了,然后从对应服务列表里删除

有种办法叫做心跳检测heartBeat,即就是服务注册中心,每隔一定时间去监测一下provider,如果监测到某个服务挂了,那就把对应服务地址从服务列表中删除。

可是不对呀,此时consumer端本地列表里还有过掉的服务地址,怎么办呢?

或者是,在增加一个新的服务节点

对于服务注册中心来说,就是服务列表里增加一个服务地址。

但是在消费端存在同样的问题,就是服务注册中心的服务列表和consumer端的服务列表不一样了。

如何让consumer端也动态感知呢?

其实很简单,此时,我们得思维换一下,因为consumer的服务列表是来自于服务注册中心,我们就可以把consumer理解为消费端,服务注册中心理解为服务端。此时,consumer端就可以去服务端(服务注册中心)拉取provider服务列表。

通常有两种方案:push和pull

  • push:服务注册中心主动推送服务列表给consumer。
  • pull:consumer主动从注册中心拉取服务列表。

不管是push还是pull,都会存在consumer和服务注册中心的通信管道。如果他们之间断开了,那就无法获取服务列表了。

还有就是服务注册中心知道consumer的地址,比如

我得知道你的微信好友,不然我怎么把我手里的资源发给你

我们的网络通信,必然会存在监听的动作。

如果服务注册中心要push到consumer,此时他们之间需要建立一个会话,所以,在服务注册中心会维护一个会话管理的模块。还有一种方式就是consumer提供一个API,这个API给服务注册中心进行回调。

本质是我们是使用HTTP协议还是使用Socket监听

push有个不好点,那就是服务注册中心需要维护大量的会话,而且还需要对每个会话维持一个心跳,以便知晓这些会话状态,得确保这些consumer能收到数据,

另外就是pull,pull其实就相对push就简单多了。pull和我们前面说的心跳机制是类似的,consumer端启动定时任务,每个多久拉取服务注册中心的服务列表。pull也不需要去维护大量的会话,我只需要每隔多久调用接口拉取服务列表即可。但是这里还是会存在一个问题,因为是定时去拉取,所以会存在一定的数据延迟,比如consumer刚刚拉取服务列表,但就在拉取结束的后,某个服务provider挂了,consumer就要等下次拉取才知道对应服务provider挂了。

如果定时任务是每隔30秒拉去一次,那就是说,延迟最长时间是30秒。

还有一种方式long-pull,也叫长轮询,是上面两种方案的优化方案,consumer发起拉取请求时,先把这个请求hold住,当服务注册中心有发生变化后,consumer端能立马感知。

关于长轮询:

与简单轮询相似,只是在服务端在没有新的返回数据情况下不会立即响应,而会 挂起,直到有数据或即将超时
优点:实现也不复杂,同时相对轮询,节约带宽
缺点:还是存在占用服务端资源的问题,虽然及时性比轮询要高,但是会在没有数据的时候在服务端挂起,所以会一直占用服务端资源,处理能力变少
应用:一些早期的对及时性有一些要求的应用:web IM 聊天

这样,我们就搞定了所谓的服务上下线动态感知。

通过上面的服务注册、服务消费、注册中心高可用以及动态感知服务的上下线,这就是我们去实现一个服务注册中心的通用模型。

小总结

关于如何设计一个注册中心,无非重点关以下几点:

  • 服务是如何注册
  • 消费端如何获取服务
  • 如何保证注册中心的高可用
  • 动态感知服务的上下线

知识来源:马士兵教育
注册中心设计 - 知乎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小田田_XOW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值