Zookeeper与Dubbo


@toc

常见关系对比:

Dubbo是个微服务整体架构的框架,提供的功能包括服务注册发现,远程调用,监控等等。对标的项目大概是spring cloud。Dubbo的服务发现模块基于zookeeper实现。

Zookeeper。是用来保证分布式一致性的一个软件。不是为了服务发现注册而设计的,只不过它的特性也可以被二次开发成服务发现注册中心罢了。


CAP 理论

  • C : Consistency 一致性,数据在多个副本之间似否能够保持一致的特性。
  • A: Availability 可用性,系统服务必须一直处于可用状态,对每个请求总是在指定的时间返回结果。
  • P:Partition tolerance 分区容错性,遇到分区网络故障时,仍能对外提供一致性和可用性的服务。

Dubbo👇👇👇

1 、Dubbo 的注册中心集群挂掉,发布者和订阅者之间还能通信么?

可以通讯。启动 Dubbo 时,消费者会从 Zookeeper 拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。

2、Dubbo 和 Spring Cloud 有什么哪些区别?

Dubbo 底层是使用 Netty 这样的 NIO 框架,是基于 TCP 协议传输的。

-Spring Cloud 是基于 Http 协议 Rest 接口调用远程过程的通信,相对来说 Http 请求会有更大的报文,占的带宽也会更多。但是 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。

3、Dubbo集群提供了哪些负载均衡策略?

  • Random LoadBalance: 随机选取提供者策略,有利于动态调整提供者权重。截面碰撞率高,调用次数越多,分布越均匀。
  • RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题。
  • LeastActive LoadBalance: 少活跃调用策略,解决慢提供者接收更少的请求。
  • ConstantHash LoadBalance: 一致性 Hash 策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动。

默认为 Random 随机调用。

4、服务调用超时会怎么样?

dubbo 在调用服务不成功时,默认是会重试两次

5、为什么要有 RPC,HTTP 不好么?

这两个不是一个层级的东西,没有可比性。HTTP 只是传输协议,协议只是规范了一定的交流格式,RPC 对比的是本地过程调用,是用来作为分布式系统之间的通信,它可以用 HTTP 来传输,也可以基于 TCP 自定义协议传输。

HTTP 协议比较冗余,所以 RPC 大多都是基于 TCP 自定义协议,定制化的才是最适合自己的。

6、说说你对 Dubbo 的了解?

在这里插入图片描述
在这里插入图片描述
Dubbo 总体分了以上这么几个角色,分别的作用是xxxx。

首先服务提供者 Provider 启动然后向注册中心注册自己所能提供的服务。

服务消费者 Consumer 启动向注册中心订阅自己所需的服务。然后注册中心将提供者元信息通知给 Consumer, 之后 Consumer 因为已经从注册中心获取提供者的地址,因此可以通过负载均衡选择一个 Provider 直接调用 。

之后服务提供方元数据变更的话注册中心会把变更推送给服务消费者。

服务提供者和消费者都会在内存中记录着调用的次数和时间,然后定时的发送统计数据到监控中心。

7、看过源码,那说下服务暴露的流程?

服务的暴露起始于 Spring IOC 容器刷新完毕之后,会根据配置参数组装成 URL, 然后根据 URL 的参数来进行本地或者远程调用。

会通过 proxyFactory.getInvoker,利用 javassist 来进行动态代理,封装真的实现类,然后再通过 URL 参数选择对应的协议来进行 协议暴露,默认是 Dubbo 协议。

在第一次暴露的时候会调用 createServer 来创建 Server,默认是 NettyServer。

然后将 暴露 得到的 exporter 存入一个 Map 中,供之后的远程调用查找,然后会向注册中心注册提供者的信息。
在这里插入图片描述

8、看过源码,那说下服务引入的流程?

服务的引入时机有两种,第一种是饿汉式,第二种是懒汉式。

饿汉式就是加载完毕就会引入,懒汉式是只有当这个服务被注入到其他类中时启动引入流程,默认是懒汉式。

会先根据配置参数组装成 URL ,一般而言我们都会配置注册中心,所以向注册中心注册消费者的信息,并且订阅提供者、配置、路由等节点。

得知提供者的信息之后会进入 Dubbo 协议的引入,会创建 Invoker 然后通过 Cluster 来包装 Invoker最终返回代理类。

9、看过源码,那说下服务调用的流程?

调用某个接口的方法会调用之前生成的代理类,然后会从 cluster 中经过路由的过滤、负载均衡机制选择一个 invoker 发起远程调用,此时会记录此请求和请求的 ID 等待服务端的响应。

服务端接受请求之后会通过参数找到之前暴露存储的 map,得到相应的 exporter ,然后最终调用真正的实现类,再组装好结果返回,这个响应会带上之前请求的 ID。

消费者收到这个响应之后会通过 ID 去找之前记录的请求,然后找到请求之后将响应塞到对应的 Future 中,唤醒等待的线程,最后消费者得到响应,一个流程完毕。

10、知道什么是 SPI 嘛?

SPI 是 Service Provider Interface,主要用于框架中,框架定义好接口,不同的使用者有不同的需求,因此需要有不同的实现,而 SPI 就通过定义一个特定的位置,Java SPI 约定在 Classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,然后文件里面记录的是此 jar 包提供的具体实现类的全类名。

所以就可以通过接口找到对应的文件,获取具体的实现类然后加载即可,做到了灵活的替换具体的实现类。

11、为什么 Dubbo 不用 JDK 的 SPI,而是要自己实现?

因为 Java SPI 在查找扩展实现类的时候遍历 SPI 的配置文件并且将实现类全部实例化,假设一个实现类初始化过程比较消耗资源且耗时,但是你的代码里面又用不上它,这就产生了资源的浪费。

因此 Dubbo 就自己实现了一个 SPI,给每个实现类配了个名字,通过名字去文件里面找到对应的实现类全限定名然后加载实例化,按需加载。

zookeeper👇👇👇

1、ZooKeeper 是什么?

ZooKeeper 是一个开源的分布式协调服务,用于在自身之间协调,并通过稳健的同步技术维护共享数据。ZooKeeper本身是一个分布式应用程序,为写入分布式应用程序提供服务。

ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性 能高效、功能稳定的系统提供给用户。

Zookeeper 保证了如下分布式一致性特性:

(1)顺序一致性

(2)原子性

(3)单一视图

(4)可靠性

(5)实时性(最终一致性)

客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了 监听器,这个监听器也是由所连接的 zookeeper 机器来处理。对于写请求,这 些请求会同时发给其他 zookeeper 机器并且达成一致后,请求才会返回成功。

因此,随着 zookeeper 的集群机器增多,读请求的吞吐会提高但是写请求的吞 吐会下降

2、ZooKeeper 提供了什么?

  • 文件系统

    Zookeeper 提供一个多层级的节点命名空间(节点称为 znode)。与文件系统 不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。

    Zookeeper 为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构, 这种特性使得 Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限 为1M。

  • 通知机制

    通知机制还是通过Watches来做的
    监视是一种简单的机制,使客户端收到关于ZooKeeper集合中的更改的通知。客户端可以在读取特定znode时设置Watches。Watches会向注册的客户端发送任何znode(客户端注册表)更改的通知。


    Znode更改是与znode相关的数据的修改或znode的子项中的更改。只触发一次watches。如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。

3、 Zookeeper 怎么保证主从节点的状态同步?

Zookeeper 的核心是原子广播机制,这个机制保证了各个 server 之间的同步。 实现这个机制的协议叫做 Zab 协议。Zab 协议有两种模式,它们分别是恢复模式和广播模式。

  • 恢复模式

当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出 来,且大多数 机器完成了和 leader 的状态同步以后,恢复模式就结束了,然后进入消息广播模式。

  • 广播模式

一旦 leader 已经和多数的 follower 进行了状态同步后,它就可以开始广播消息 了,即进入广播状态。这时候当一个 机器加入 ZooKeeper 服务中,它会在 恢复模式下启动,发现 leader,并和 leader 进行状态同步。待到同步结束,它也参与消息广播。ZooKeeper 服务一直维持在 广播状态,直到 leader 崩溃了或者 leader 失去了大部分的 followers 支持。

4、四种类型的数据节点 Znode

(1)持久节点

除非手动删除,否则节点一直存在于 Zookeeper 上

(2)临时节点

临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与 zookeeper 连接断开不一定会话失效),那么这个客户端创建的所有临时节点 都会被移除。

(3)持久顺序节点

基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维 护的自增整型数字。

(4)临时顺序节点

基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的 自增整型数字。

5、Zookeeper Watcher 机制 – 数据变更通知

Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服 务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。

工作机制:

(1)客户端注册 watcher

(2)服务端处理 watcher

(3)客户端回调 watcher

Watcher 特性总结:

  1. 一次性

    无论是服务端还是客户端,一旦一个 Watcher 被 触 发 ,Zookeeper 都会将其 从相应的存储中移除。这样的设计有效的减轻了服务端的压力,不然对于更新非常频繁的节点,服务端会不断的向客户端发送事件通知,无论对于网络还是服务 端的压力都非常大。

    1. 客户端串行执行 客户端 Watcher 回调的过程是一个串行同步的过程。

    2. 轻量

3.1、Watcher 通知非常简单,只会告诉客户端发生了事件,而不会说明事件的 具体内容。
3.2、客户端向服务端注册 Watcher 的时候,并不会把客户端真实的 Watcher 对象实体传递到服务端,仅仅是在客户端请求中使用 boolean 类型属性进行了 标记。

  1. watcher event 异步发送 watcher 的通知事件从 server 发送到 client 是 异步的,这就存在一个问题,不同的客户端和服务器之间是通过 socket 进行通 信,由于网络延迟或其他因素导致客户端在不通畅的时刻监听到事件,由于 Zookeeper 本身提供了 ordering guarantee,即客户端监听事件后,才会感知它所监视 znode发生了变化。所以我们使用 Zookeeper 不能期望能够监控到节点每次的变化。Zookeeper 只能保证最终的一致性,而无法保证强一致性。

6、讲讲客户端注册 Watcher 实现、服务端处理 Watcher 实现、客户端回调 Watcher?

客户端注册 Watcher 实现:
(1)调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象

(2)标记请求 request,封装 Watcher 到 WatchRegistration

(3)封装成 Packet 对象,发送 request到 服务端

(4)收到服务端响应后,将 Watcher 注册到 ZKWatcherManager 中进行管理

(5)请求返回,完成注册。

服务端处理 Watcher 实现:
(1)服务端接收 Watcher 并存储

接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节 点的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端的连接, 实现了 Watcher 的 process 接口,此时可以看成一个 Watcher 对象)存储在 WatcherManager 的 WatchTable 和 watch2Paths 中去。

(2)Watcher 触发

以服务端接收到 setData() 事务请求触发 NodeDataChanged 事件为例:

2.1 封装 WatchedEvent 将通知状态(SyncConnected)、事件类型(NodeDataChanged)以及节点 路径封装成一个 WatchedEvent 对象

2.2 查询 Watcher 从 WatchTable 中根据节点路径查找 Watcher

2.3 没找到;说明没有客户端在该数据节点上注册过 Watcher

2.4 找到;提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher(从 这里可以看出 Watcher 在服务端是一次性的,触发一次就失效了)

(3)调用 process 方法来触发 Watcher ,这里 process 主要就是通过 ServerCnxn 对应的 TCP 连接发送 Watcher 事件 通知。

客户端回调 Watcher:
客户端 SendThread 线程接收事件通知,交由 EventThread 线程回调 Watcher。

客户端的 Watcher 机制同样是一次性的,一旦被触发后,该 Watcher 就失效 了。

7、服务器角色有哪些?

Leader

(1) 事务请求的唯一调度和处理者,保证集群事务处理的顺序性

(2) 集群内部各服务的调度者

Follower

(1) 处理客户端的非事务请求,转发事务请求给 Leader 服务器

(2) 参与事务请求 Proposal 的投票

(3) 参与 Leader 选举投票

Observer

(1)3.0 版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础

上提升集群的非事务处理能力

(2) 处理客户端的非事务请求,转发事务请求给 Leader 服务器

(3) 不参与任何形式的投票

8、如何识别请求的先后顺序?

ZooKeeper 会给每个更新请求,分配一个全局唯一的递增编号(zxid),编号的大小体现事务操作的先后顺序。

9、Zookeeper 下 Server 工作状态有哪些?

服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、 OBSERVING。

(1) LOOKING:寻 找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。

(2) FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。

(3)LEADING:领导者状态。表明当前服务器角色是 Leader。

(4)OBSERVING:观察者状态。表明当前服务器角色是 Observer。

10、 分布式集群中为什么会有 leader 节点?

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要进行 leader 选举。

11、zk 节点宕机如何处理?

Zookeeper 本身也是集群,推荐配置不少于 3 个服务器。Zookeeper 自身也要保证当一个节点宕机时,其他节点会继续提供服务。

如果是一个 Follower 宕机,还有 2 台服务器提供访问,因为 Zookeeper 上的数据是有多个副本的,数据并不会丢失;

如果是一个 Leader 宕机,Zookeeper 会选举出新的 Leader。
ZK 集群的机制是只要超过半数的节点正常,集群就能正常提供服务。

ZK节点挂得太多,只剩一半或不到一半节点能工作,集群才失效。

12、zookeeper 负载均衡和 nginx 负载均衡区别?

zk 的负载均衡是可以调控,nginx 只是能调权重,其他需要可控的都需要自己写插件;但是 nginx 的吞吐量比 zk 大很多,应该说按业务选择用哪种方式。

13、Zookeeper 有哪几种几种部署模式?

Zookeeper 有三种部署模式:

  1. 单机部署::ZooKeeper以单实例的形式运 行在一台服务器上,适合测试环境。
  2. 集群部署:ZooKeeper运行在多台服务器上,适合生产环境。
  3. 伪集群部署:在一台服务器上跑多个ZooKeeper实例。

14、集群最少要几台机器,集群规则是怎样的?集群中有 3 台服务器,其中一个节点宕机,这个时候 Zookeeper 还可以使用吗?

集群规则为 2N+1 台,N>0,即 3 台。可以继续使用,单数服务器只要没超过一半的服务器宕机就可以继续使用。

15、集群支持动态添加机器吗?

其实就是水平扩容,Zookeeper 在这方面不太好。两种方式:

全部重启:关闭所有 Zookeeper 服务,修改配置之后启动。不影响之前客户端的会话。

逐个重启:在过半存活即可用的原则下,一台机器重启不影响整个集群对外提供服务。这是比较常用的方式。

16、Zookeeper 对节点的 watch 监听通知是永久的吗?为什么不是永久的?

不是。官方声明:一个 Watch 事件是一个一次性的触发器,当被设置了 Watch 的数据发生了改变的时候,则服务器将这个改变发送给设置了 Watch 的客户端,以便通知它们。

为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次变动都要通知到所有的客户端,给网络和服务器造成很大压力。

一般是客户端执行 getData(“/节点 A”,true),如果节点 A 发生了变更或删除,客户端会得到它的 watch 事件,但是在之后节点 A 又发生了变更,而客户端又没有设置 watch 事件,就不再给客户端发送。在实际应用中,很多情况下,我们的客户端不需要知道服务端的每一次变动,我只要最新的数据即可。

17、说几个 zookeeper 常用的命令?

常用命令:ls get set create delete 等

18、说一下 Zookeeper 的通知机制?

client 端会对某个 znode 建立一个 watcher 事件,当该 znode 发生变化时,这些 client 会收到 zk 的通知,然后 client 可以根据 znode 变化来做出业务上的改变等

19、说说zookeeper实现分布式锁?

zk就是基于节点去实现各种分布式锁的。zk节点有个唯一的特性,就是我们创建过这个节点了,你再创建zk是会报错的,那我们就利用一下他的唯一性去实现分布式锁。解锁的话就在finally中删除节点就行了。

加锁我们知道创建节点就够了,但是你得实现一个阻塞的效果呀,那咋搞?

死循环,递归不断去尝试,直到成功,一个伪装的阻塞效果。

怎么知道前面的老哥删除节点了嗯?

监听节点的删除事件

注意,我们要使用顺序临时节点

临时节点可以保证当前“拿到锁“的服务器宕机了,那么这个临时节点就会自动删除掉,其他客户端自动获取锁。
至于顺序:就是为了解决【监听,是所有服务都去监听一个节点的,节点的释放也会通知所有的服务器】这个情况的。
用了顺序临时节点这里每个节点只监听了自己的前一个节点,释放当然也是一个个释放下去,就不会出现羊群效应了。

20、能说说ZK在分布式锁中实践的一些缺点么?

1、Zk性能上可能并没有缓存服务那么高。

因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。


文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录