这是小卷对分布式系统架构学习的第8篇文章,在写第2篇文章已经讲过服务发现了,现在就从组件工作原理入手,讲讲注册中心

以下是面试题:

某团面试官:你来说说怎么设计一个注册中心?

我:注册中心嘛,就要有服务发现的功能,服务启动后把自己的信息注册上去,然后消费端可以拉取生产者的信息嘛,然后就能调用了

某团面试官:那你说说分布式系统中注册中心怎么选型呢?Eureka、Zookpeer、Nacos、Etcd这些中间件,你实际用的时候怎么考虑的?

我:就用Nacos啊,公司里大家都用这个

面试官:......

面试官:我知道了,今天的面试就到这吧......

1.注册中心的功能

设计注册中心时,先来思考下面几个问题:

  • 服务如何注册
  • consumer如何知道provider
  • 注册中心怎么做到高可用,服务发现怎么做的

要想实现一个服务注册中心,必须具备以下功能:

  • 服务注册:provider在注册中心完成注册
  • 服务注销:服务提供者需在注册中心完成服务下线
  • 心跳检测:检查服务提供者的健康状态
  • 服务查询:消费者获取服务列表消息
  • 服务变更查询:服务发生变更时,消费者通过查询变更获取最新服务列表
  • 服务高可用

2.Zookeeper工作原理

我们还是选择一个比较活跃的中间件来展开学习注册中心的工作原理。

Zookeeper的文档官网:Apache ZooKeeper

官网解释Zookeeper名字的由来是因为分布式系统就像个动物园(Zoo),目前国内Dubbo场景下大多选用Zookeeper作为注册中心。官方解释它使用一个具有层次结构的命名空间(类似文件系统),用斜杠(“/”)分隔路径元素,根节点是(“/”)表示,无父节点。通过znodes(ZooKeeper节点)存储数据,如果znode有子节点,则无法删除该znode。这些数据可以被多个应用程序共享,并提供高可用性和一致性。

2.1简单API

ZooKeeper的一个设计目标是提供一个非常简单的编程接口,这些接口故意设计得十分简单。然而,借此接口,您可以实现更高阶的操作,如同步原语、组成员管理、所有权等。编程接口支持以下操作:

  • create:在树中的某个位置创建一个节点。
  • delete:删除一个节点。
  • exists:测试某个位置是否存在节点。
  • get data:读取节点中的数据。
  • set data:向节点写入数据。
  • get children:获取节点的子节点列表。
  • sync:等待数据传播。

2.2 服务注册

客户端注册:当一个服务提供者实例启动时,它会向Zookeeper注册到某一路径上。

服务实例通过创建一个znode(通常是临时节点)来注册自己。这个znode包含服务实例的元数据,注册路径为:{service}/{version}/{ip:port}

示例:将我们的HelloService部署启动后,Zookeeper上会创建一个目录:

  • /HelloWorldService/1.0.0/192.168.1.100:8080

下面简述服务注册的过程:

  1. 服务提供者启动时,会将其服务名称,ip地址注册到注册中心;
  2. 服务消费者在第一次调用服务时,会通过注册中心找到相应的服务的IP地址列表,并缓存到本地。当消费者调用服务时,不再请求注册中心,而是直接通过负载均衡算法从IP列表中取一个服务提供者的服务器调用服务;
  3. 当服务提供者的某台服务器宕机或下线时,相应的ip会从服务提供者IP列表中移除。同时,注册中心会将新的服务IP地址列表发送给消费者机器,缓存在消费者本机;
  4. 当某个服务的所有服务器都下线了,那么这个服务也就下线了;
  5. 同样,当服务提供者的某台服务器上线时,注册中心会将新的服务IP地址列表发送给服务消费者机器,缓存在消费者本机;
  6. 服务提供方可以根据服务消费者的数量来作为服务下线的依据

客户端代码示例

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);

2.3 心跳检测机制

服务的某台机器下线时,Zookeeper是如何感知到?

zookeeper提供了“心跳检测”功能,它会定时向各个服务提供者发送一个请求(实际上建立的是一个 socket 长连接),如果长期没有响应,服务中心就认为该服务提供者已经“挂了”,并将其删除。

2.4 服务发现

有关服务发现的概念可以看我之前的文章:分布式系统架构2:服务发现

上面说了有新的服务提供者出现时,注册中心是怎么将这些变化通知给消费者客户端的呢?

有2种方式:

  • 主动Pull方式:消费者定期从注册中心拉取最新的服务提供者列表,并更新本地缓存。如Eureka
  • 发布-订阅模式:消费者实时监听服务更新状态,采用的是监听器+回调机制。Zookeeper用的是发布-订阅模式,客户端在服务节点设置监视器(Watcher)。当节点发生变化(如服务实例上线或下线)时,Zookeeper会通知所有设置了监视器的客户端

2.5 存在问题

Zookeeper作为注册中心不合适,缺少可用性。

zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。

而作为注册中心,可用性的要求高于一致性!

2.6 Zookeeper总结

  • Zookeeper的心跳检测,可以自动探测服务提供者机器的宕机或下线;
  • Zookeeper的Watch机制,可以将变更的注册列表推给服务消费者;
  • Zookeeper是CP模型,不太适合作为注册中心

如何设计一个注册中心?以Zookeeper为例的更多相关文章

  1. Dubbo原理解析-注册中心之Zookeeper协议注册中心

    下面我们来看下开源dubbo推荐的业界成熟的zookeeper做为注册中心, zookeeper是hadoop的一个子项目是分布式系统的可靠协调者,他提供了配置维护,名字服务,分布式同步等服务.对于z ...

  2. 服务注册中心之ZooKeeper系列(二) 实现一个简单微服务之间调用的例子

    上一篇文章简单介绍了ZooKeeper,讲了分布式中,每个微服务都会部署到多台服务器上,那服务之间的调用是怎么样的呢?如图: 1.集群A中的服务调用者如何发现集群B中的服务提供者呢? 2.集群A中的服 ...

  3. 服务注册中心之ZooKeeper系列(一)

    一.服务注册中心介绍 分布式服务框架部署在多台不同的机器上.例如服务A是订单相关的处理服务,服务B是订单的客户的相关信息服务.此时有个需求需要在服务A中获取订单客户的信息.如下图: 此时就面临以下几个 ...

  4. Dubbo多注册中心和Zookeeper服务的迁移

    一.Dubbo多注册中心 1. 应用场景 例如阿里有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心. consumer.xml <?xm ...

  5. Spring Cloud注册中心之Zookeeper

    zookeeper可以作为分布式服务的注册中心 在服务端安装zookeeper 参考:https://www.cnblogs.com/conly/p/12267506.html 创建spring bo ...

  6. 服务注册中心之ZooKeeper系列(三) 实现分布式锁

    通过ZooKeeper的有序节点.节点路径不回重复.还有节点删除会触发Wathcer事件的这些特性,我们可以实现分布式锁. 一.思路 zookeeper中创建一个根节点Locks,用于后续各个客户端的 ...

  7. 基于spring-cloud的微服务(1) 服务注册中心eureka

    eureka是Netflix提供的服务注册中心组建,springcloud将其做了封装,作为自己的微服务架构中的一个注册中心组建 下面的例子在IDEA中启动一个eureka的实例,然后提供一个prov ...

  8. 为什么推荐Zookeeper作注册中心

    Zookeeper的数据模型很简单,有一系列被称为ZNode的数据节点组成,与传统的磁盘文件系统不同的是,zk将全量数据存储在内存中,可谓是高性能,而且支持集群,可谓高可用,另外支持事件监听.这些特点 ...

  9. Spring Cloud 系列之 ZooKeeper 注册中心

    什么是注册中心 服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用,主要用来存储服务信息,譬如提供者 url 串.路由信息等.服务注册中心是微服务架构中最基础的设施之一. 注册中心可以说 ...

  10. 学习一下 SpringCloud (二)-- 服务注册中心 Eureka、Zookeeper、Consul、Nacos

    (1) 相关博文地址: 学习一下 SpringCloud (一)-- 从单体架构到微服务架构.代码拆分(maven 聚合): https://www.cnblogs.com/l-y-h/p/14105 ...

随机推荐

  1. Web渗透07_脚本代码注入和OS命令注入( 恐怖级别 )

    1 PHP代码注入 1.1 原理成因 网站对用户的输入过滤出现问题,同时网站的脚本编写用到一些危险函数 eval(),assert().如果被攻击者发现漏洞,直接可能造成攻击者完全控制整个web甚至是 ...

  2. 顺序结构程序设计(python)

    文章目录 1.python运算符 1.1 python算数运算 1.2python比较运算符 1.3 Python赋值运算符 1.4 python逻辑运算符 1.5 python成员运算符 1.6py ...

  3. JAVA 传输post传输长字符、数据编码解码 反序列化字符串

    JAVA 传输post传输长字符.数据编码解码 1.前段传输 这是传输的数组对象 2.后端接收格式已解码 JS代码: $.ajax({ url:prefix+"/importModelTre ...

  4. 如果一个接口不使用token鉴权,应该怎么保持在登录状态下进行测试?

    1.token是接口中用于身份验证和授权的令牌,用户通过登录操作,服务器会返回一个token,这个token会在后续的请求中发送到服务器,用来证明用户的身份和权限. 2.如果接口没有token,可以使 ...

  5. 盘点Vue3 watch的一些关键时刻能够大显身手的功能

    前言 watch这个API大家应该都不陌生,在Vue3版本中给watch增加不少有用的功能,比如deep选项支持传入数字.pause.resume.stop方法.once选项.onCleanup函数. ...

  6. Solr学习总结-Facet

    返回查询集合中指定field的统计情况,例如找到city一样的文档数目: 加入文档 <add> <doc> <field name="id">1 ...

  7. How to display XML in a JTree using JDOM

    How to display XML in a JTree using JDOM This brief tutorial will explain how to use Java to make an ...

  8. golang之命令行参数

    当我们希望通过命令行启动Golang程序,获取输入的各种形式参数时,该如何处理呢? [os.Args] os.Args是一个string的切片,用来存储所有的命令行参数,包括go run main.g ...

  9. C++中的多线程及其之后的周边

    多线程 参考:https://zhuanlan.zhihu.com/p/613630658 平台差异:Linux 与 Windows,跨平台方案 在Linux上,有pthread的使用,而C++ 11 ...

  10. 【论文系列】PPO知识点梳理 (尽我可能细致通俗理解!)

    零.题记 这篇博客一方面为了记录当前的知识点,另一方面PPO算法实在是太重要了,不但要从理论上理解它到底是怎样实现的,还需要从代码方面进行学习和记录,这里我就通俗的将这个知识点进行简单的记录,用来日后 ...