这是小卷对分布式系统架构学习的第8篇文章,在写第2篇文章已经讲过服务发现了,现在就从组件工作原理入手,讲讲注册中心
以下是面试题:
某团面试官:你来说说怎么设计一个注册中心?
我:注册中心嘛,就要有服务发现的功能,服务启动后把自己的信息注册上去,然后消费端可以拉取生产者的信息嘛,然后就能调用了
某团面试官:那你说说分布式系统中注册中心怎么选型呢?Eureka、Zookpeer、Nacos、Etcd这些中间件,你实际用的时候怎么考虑的?
我:就用Nacos啊,公司里大家都用这个
面试官:......
面试官:我知道了,今天的面试就到这吧......
设计注册中心时,先来思考下面几个问题:
要想实现一个服务注册中心,必须具备以下功能:
我们还是选择一个比较活跃的中间件来展开学习注册中心的工作原理。
Zookeeper的文档官网:Apache ZooKeeper
官网解释Zookeeper名字的由来是因为分布式系统就像个动物园(Zoo),目前国内Dubbo场景下大多选用Zookeeper作为注册中心。官方解释它使用一个具有层次结构的命名空间(类似文件系统),用斜杠(“/”)分隔路径元素,根节点是(“/”)表示,无父节点。通过znodes(ZooKeeper节点)存储数据,如果znode有子节点,则无法删除该znode。这些数据可以被多个应用程序共享,并提供高可用性和一致性。
ZooKeeper的一个设计目标是提供一个非常简单的编程接口,这些接口故意设计得十分简单。然而,借此接口,您可以实现更高阶的操作,如同步原语、组成员管理、所有权等。编程接口支持以下操作:
客户端注册:当一个服务提供者实例启动时,它会向Zookeeper注册到某一路径上。
服务实例通过创建一个znode(通常是临时节点)来注册自己。这个znode包含服务实例的元数据,注册路径为:{service}/{version}/{ip:port}
示例:将我们的HelloService部署启动后,Zookeeper上会创建一个目录:
下面简述服务注册的过程:
客户端代码示例:
ZooKeeper zk = new ZooKeeper("localhost:2181", 3000, null);
String path = "/services/myService";
zk.create(path, "192.168.1.100:8080".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
服务的某台机器下线时,Zookeeper是如何感知到?
zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其删除。
有关服务发现的概念可以看我之前的文章:分布式系统架构2:服务发现
上面说了有新的服务提供者出现时,注册中心是怎么将这些变化通知给消费者客户端的呢?
有2种方式:
Zookeeper作为注册中心不合适,缺少可用性。
zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。
而作为注册中心,可用性的要求高于一致性!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。