10. Interview-Dubbo&ZooKeeper

1 zookeeper原理 / zookeepr分布式一致性原理

  • ZooKeeper的核心是原子广播,实现原子广播机制的协议叫ZAB协议
  • 选举阶段、恢复阶段、广播阶段

2 讲一下CAP原理?ZooKeeper是什么?Eureka是什么?

  • C:Consistency,一致性,通常指的是强一致性

  • A:Availability,可用性

  • P:Partition tolerance,分区容错性

  • ZooKeeper是CP,Eureka是AP

  • zookeeper其实提供的也是弱一致性,读的数据可能不是最新的,如果想要读到最新的数据,要手工调用sync方法从leader同步。

3 zookeeper能做什么?zookeeper应用场景?

类似Linux文件系统的树形结构,轻量级的内存文件系统,只适合存储少量信息,不适合存储大量文件或大文件,每个znode默认存储1MB的数据,主要是状态数据。

zookeeper应用场景

  • 注册中心(临时节点、watch)
  • 分布式锁(临时节点、节点唯一性、watch)
  • 分布式ID(顺序节点)
  • 分布式队列(临时有序节点、watch)
  • 配置中心(watch机制发布订阅)
  • leader选举(临时节点、节点唯一性、watch)
  • 统一命名服务:根据指定名字来获取资源或服务的地址,提供者等信息,利用其znode的特点和watcher机制,将其作为动态注册和获取服务信息的配置中心,统一管理服务名称和其对应的服务器列表信息,我们能够近乎实时地感知到后端服务器的状态(上线、下线、宕机)。
  • 集群管理
  • 负载均衡
  • 服务器动态上下线


    监听器原理

利用到zookeeper的中间件

  • dubbo
  • kafka
  • solr
  • HBASE
  • storm

4 zookeeper作为注册中心有什么问题?

  • ZooKeeper是CP,leader选举时间过长(30~120s)会出现服务不可用

5 zookeeper与eureka区别

  • ZooKeeper是CP,Eureka是AP
  • ZooKeeper要n/2+1才能对外服务,Eureka只要一台存活就可以服务,只是信息可能是旧的,还有自我保护机制(15分钟内超过85%的节点没有心跳开启自我保护机制)
  • Eureka在自我保护机制开启后会有以下情况出现:
    • 不再移除本已经过期的服务
    • 还可以接受新服务注册和查询请求,但是不会同步到其它节点
    • 网络稳定恢复正常,新注册信息才会同步到其它节点

6 master选举/leader选举

zoo.cfg中electionAlg属性指定1~3,分别对应3中leader选举算法:

  • 1对应LeaderElection
  • 2对应AuthFastLeaderElection
  • 3对应FastLeaderElection,默认的算法,3.4.0以后只保留这一种。

leader选举过程

  • (myid, zxid)作为quorum的权重
  • 先比较zxid,选zxid大的
  • zxid相同,比较myid,选myid大的
  • 半数机制,超过半数机器存活,则集群可用

7 zookeeper通信模型

ZooKeeper通信模型
  • client ——> follower:java NIO(默认,还有一种基于netty3)
  • follower ——> leader
    • ElectionLeader / AuthFastElectionLeader:UDP
    • FastElectionLeader:TCP/IP

8 zookeeper数据结构(znode默认存储1MB数据)

ZooKeeper跟踪时间的多种方式

  • Zxid:每个ZooKeeper状态变化将会接收到一个zxid(ZooKeeper Transaction Id)的时间戳。ZooKeeper通过该字段了解所有变化的顺序。每次变化都会有一个唯一的zxid,如果zxid1小于zxid2,说明zxid1发生在zxid2之前。

  • Version numbers:每个对节点的变化都会对这个节点的版本号加1.有3个版本号他们分别是version\cversion\aversion

  • Ticks:当在使用多机ZooKeeper服务时,服务器之间会使用ticks票据来定义事件(比如状态上传、会话超时、连接超时等等)的计时。tick时间会通过最小会话超时时间间接显示;如果客户端请求会话超时小于最小的会话时间,服务端会告诉客户端这个会话超时时间实际是最小会话时间;

  • Real time:ZooKeeper没有使用实时时间或者时钟时间,除了把时间戳放进正在创建或者修改的znode节点的数据结构中。

在ZooKeeper的每个znode节点的数据结构由以下几个字段组成:

  • czxid:znode节点创建时间所对应的zxid
  • mzxid:znode节点修改时间所对应的zxid
  • ctime:以距离时间原点(epoch)的毫秒数表示的znode创建时间
  • mtime:以距离时间原点(epoch)的毫秒数表示的znode最近修改时间
  • version:znode节点的版本号,记录修改次数
  • cversion:znode子节点的版本号,记录子节点修改次数
  • aversion:znode节点的权限(ACL)版本号,记录ACL修改次数
  • ephemeralOwner:如果znode节点是临时节点,表示所属会话的id,如果不是临时节点则为0
  • dataLength:znode节点数据字段的长度
  • numChildren:znode节点的子节点数量

9 服务注册到zookeeper,这些数据保存在哪里?

zoo.cfg中dataDir=/tmp/zookeeper

10 zookeeper怎么实现分布式锁

分布式锁的3种实现方案

  • 数据库锁
    • 乐观锁,version
    • 悲观锁,for update
  • redis实现分布式锁
    • setnx()
    • Redission
    • Redlock
  • ZooKeeper实现分布式锁
    • 有序临时节点,最小的有序节点获得锁,使用完就消失,通过watch监控节点变化,继续找出最小的有序节点获得锁,依次继续。

zookeeper分布式锁实现方式

  • 排它锁/写锁/独占锁/阻塞锁
    • 加锁:创建临时节点
      • 基础版本:/exclusive节点下创建临时有序节点,/exclusive/lock,创建成功即加锁成功;其它未获得锁的客户端注册watch监听
      • 改进版本:临时节点序号最小的获得锁,其它的客户端注册watch监听
    • 释放锁:删除加锁时候创建成功的临时节点
      • 正常释放:正常执行完业务逻辑,客户端主动删除临时节点;
      • 异常释放:当前获取锁的客户端机器发生宕机,zookeeper上的临时节点会被移除。
  • 共享锁/读锁/非阻塞锁
    • 在获取共享锁时,所有客户端都会到/shared_lock节点下创建一个临时顺序节点(shared_lock/[Hostname]-请求类型-序号),若是读请求,则创建/shared_lock/192.168.0.1-R-0000000001;
    • 若是写请求,则创建/shared_lock/192.168.0.1-W-0000000001
zookeeper实现分布式锁原理

zookeeper分布式锁开源实现

  • Apache curator

zookeeper实现分布式锁用临时节点有什么问题?

  • 使用EPHEMERAL会引出一个风险:在非正常情况下,网络延迟比较大出现session timeout,ZooKeeper就会认为该client已关闭,从而销毁其id标识,竞争资源的下一个id就可以获取锁。这时可能两个process同时拿到锁在跑任务,设置好sessionTimeout很重要,不要跨机房访问。

  • 同样使用PERSISTENT同样会存在一个死锁的风险,进程异常退出后,对应的竞争资源id一直没有删除,下一个id一直无法获取锁对象。

  • 至于是否使用优化后的分布式锁,开发人员可以灵活掌握。在集群规模不大、网络资源丰富的情况下,之前的实现方案比较简单实用;若集群规模达到一定程度,希望可以精细化地控制分布式锁机制,可以尝试改进后的分布式锁实现。

11 ZooKeeper三种角色

  • Leader
    • 一个ZooKeeper集群同一时间只会有一个leader,它发起和维护与Follower和Observer间的心跳。
    • 所有写操作都是Leader完成的,同时会将写操作通过原子广播给其他服务器,只有超过半数的节点(不包括Observer节点)写入成功,该写请求就会被提交。
  • Follower
    • Follower可以直接处理并响应客户端的读请求,将写请求转发给Leader
    • Follower有投票权
  • Observer
    • Observer无投票权
    • Observer接受客户端请求,并将写请求转发给Leader
    • 加入Observer提高伸缩性,不影响吞吐率

12 ZooKeeper四种节点

  • 持久节点
  • 临时节点
  • 持久顺序节点
  • 临时顺序节点

13 ZAB协议

13.1 事务编号Zxid

  • 低32位:单调递增的计数器,每次事务加1
  • 高32位:epoch,每选举一个leader,都会有一个新的epoch,在之前基础上加1

13.2 ZAB协议的两种模式

  • 恢复模式
    leader选举的过程
  • 广播模式
    Leader和各节点同步的过程

13.3 ZAB协议的4个阶段

  • 选举阶段
    • 一个节点得票数超过半数就可以成为准leader,此时的leader只有进入到广播阶段才算是真正的leader
  • 发现阶段
    • 准leader生成epoch,follower接受epoch
  • 同步阶段
    • leader获得最新的信息同步集群所有副本
  • 广播阶段
    • 此时的leader才是真正的leader,leader进行消息广播,正式对外提供服务。

13.4 ZAB协议的java实现

将原生的ZAB协议的发现阶段和同步阶段合并为恢复阶段。

  • 选举阶段
  • 恢复阶段
  • 广播阶段

13.5 投票机制

  • 每个节点首先给自己投票
  • zxid最大的节点
  • 节点获得超半数得票

14 判断长连接是否存活?怎么实现心跳检测机制?

当长连接没有流量时,无法判断是通信异常还是通信正常但无业务流量引起的,需要心跳包来实现。

  • 方式一:应用层实现心跳机制(推荐)
    • 优点:实现策略灵活,能及时检测到连接状态;
    • 缺点:每个应用都需要有一套,无法底层共用;
  • 方式二:利用TCP的KeepAlive机制
    • TCP协议本身提供了心跳机制,需要通过SO_KEEPALIVE开启。默认情况下,当连接空闲2小时后,每隔75s发送一次心跳包,如果连续9次没有收到响应则关闭连接。
    • 优点:不需要二次开发,简单配置参数即可;
    • 缺点:网络环境的复杂性使得KeepAlive机制容易失效;

15 zookeeper写数据流程

zookeeper写数据流程

16 paxos & Raft & ZAB

相同点

  • 都是分布式一致性协议,都是采用quorum确定少数服从多数的一致性
  • ZooKeeper还实现了带权重的quorum(myid越大权重越大)
  • 核心都是leader选举,都是先到先得的投票方式
  • 写操作都是leader发起
  • 都采用心跳检测探活

异同点

  • Raft和ZAB是paxos基础上改性的,Raft目标是简单易懂
  • Raft的心跳是leader到follower,ZAB是follower到leader
  • ZAB的follower在投票给leader前必须跟leader日志达成一致,Raft的follower简单的谁的term高投给谁
  • paxos中角色是proposor、acceptor、learner,ZAB是leader、follower、observer
  • ZAB中用epoch,Raft用term

使用场景

  • paxos
    • Google chubby
  • Raft
    • Redis Cluster
    • etcd
  • ZAB
    • ZooKeeper

17 什么是quorum?什么是NWR?

  • quorum又叫做NWR协议,分布式存储中控制一致性的策略。
    • N,分布式存储系统中,有多少份备份数据
    • W,至少有W份写入才代表写成功
    • R,至少有R份读取才代表读成功
  • W+R>N,强一致性
  • W+R<=N,最终一致性

18 Dubbo原理

Dubbo架构图

Dubbo架构主要分为五个模块:容器、服务提供者、服务消费者、注册中心、监控中心。

  1. 容器启动,运行服务提供者,其实就是一个main程序
  2. 服务提供者启动后,发布服务到注册中心
  3. 消费者启动后,向注册中心订阅服务列表;当服务列表有变化时,注册中心基于长连接推送变更给消费者
  4. 消费者调用服务,服务端根据软负载均衡算法选择一台提供者给消费者调用,如果调用失败,再选择另一台提供调用服务
  5. 服务提供者和消费者在内存中累积调用次数和时间,每隔一分钟发送统计数据给监控中心
  6. 注册中心和监控中心是可选的,即使两个都宕机,也不影响服务提供者和消费者,因为消费者本地缓存了服务列表,可以直连服务提供者
  7. Registry、Provider、Consumer三者之间都是基于长连接的,Monitor不是
  8. Provider全部宕机,服务不可使用,Consumer会无限次重连等待Provider恢复

19 Dubbo服务发现与注册流程

Invoker
Exporter

1、调用JavassistProxyFactory 生成一个Invoker。 对应Invoker invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));这一段

2、用com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol#export方法 进行一个服务的暴露

3、DubboProtocol#export 方法最终会调用com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory#createRegistry

进行一个服务注册 这时zookeepr相应的目录下面就会有对应的内容.这时服务注册就算完成了。

20 Dubbo序列化方式?效率上各有什么区别?

  • hessian2(duubo默认)
    Hessian是一种跨语言的高效的二进制序列化方式,hessian2是阿里基于hessian修改的,是dubbo默认的序列化方式。

  • Kryo+FST(dubbox默认)
    基于Java语言的高效的二进制序列化方式,dubbox中默认使用的序列化方式。

  • thrift/protobuf
    跨语言高效序列化方式

  • dubbo
    阿里开发尚未成熟的序列化方式,不建议在生产环境使用。

  • json/fastjson
    json是常用的文本序列化方式,性能低于二进制序列化方式。

  • Java序列化
    Java自带的序列化方式,性能不理想。

21 Dubbo的consumer怎么调provider?Dubbo负载均衡策略?

  • Random(缺省默认)
    随机。缺省默认,按照权重设置随机概率。

  • RoundRobin
    轮询。按照公约后的权重设置轮询比率。

  • LeastActive
    最少活跃调用数。使慢的机器接手到更少的请求。

  • ConsistentHash
    一致hash。相同参数的请求总是发送到同一台机器。

22 Dubbo的容错机制

  • failover(缺省默认)
    Dubbo缺省默认值,失败自动重试,通常用于读操作,但重试会带来更长延迟,可通过retries="2"来设置重试次数(不含第一次)
  • failfast
    快速失败,通常用于非幂等性的写操作,如新增记录
  • failsafe
    失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作
  • failback
    失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知等操作
  • forking
    并行调用多个服务器,只有一个成功即返回,通常用于实时性较高的读操作,但需要浪费更多的服务资源,可通过forks="2"来设置最大并行数
  • broadcast
    从2.1.0版本开支支持,广播告诉所有提供者,逐个调用,任意一台报错则报错,通常用于通知所有提供者更新缓存或日志等本地资源信息。
Dubbo集群容错模式

23 Dubbo的SPI机制跟Java的SPI有什么区别?

  1. SPI定义
    SPI的全名为Service Provider Interface。JDK的SPI实现了为接口自动寻找实现类的功能。

  2. SPI的使用方式
    当服务提供者提供一个接口的多个实现的时候,一般会在META-INF/services/ 下面建立一个与接口全路径同名的文件,在文件里配置接口具体的实现类。当外部调用模块的时候的时候就能实例化对应的实现类。

  3. JDK和Dubbo实现SPI的异同

    • JDK的SPI用ServiceLoader实现,Dubbo的SPI用ExtensionLoader实现
    • JDK的SPI会在一次实例化所有实现,可能会比较耗时,而且有些可能用不到的实现类也会实例化,浪费资源而且没有选择;Dubbo的SPI是延迟加载的。
    • dubbo的spi文件定义在META-INF/dubbo/internal/路径下面和jdk的spi类似。但是dubbo的spi文件里面格式和jdkSPI有点不一样,是key-value形式,格式是扩展名=全路径的类名。
    • dubbo的spi增加了对扩展点IOC和AOP的支持,一个扩展点可以直接setter注入其他扩展点。这是jdk spi不支持的。

24 Dubbo的group和version

24.1 Dubbo的group属性

  • 当一个接口有多种实现时,可以用group区分。






  • Dubbo消费者也可以设置为:消费任意一个group的服务。

24.2 Dubbo的version属性

  • 当一个接口的实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。








  • 消费者消费服任意版本的服务时:

  • 接口升级时,要注意方法:
    • 在低压力时间段,先升级一半的提供者为新版本;
    • 再将所有的消费者升级为新版本;
    • 然后将剩下的一半提供者升级为新版本。

25 Dubbo怎么实现灰度发布?

Dubbo服务调用原理

客户端在发起RPC服务调用之前,在客户端首先从服务器列表中选择一个服务调用者,包含如下关键角色:
   1、Directory
   服务的动态发现,通常基于注册中心进行服务的动态注册与发现,其具体实现类为RegistryDirectory。
   2、Router
   路由实现,其含义是根据Directory发现的所有服务提供者列表中,进行路由选择,也就是根据一定的路由规则选择合适的服务提供者,为Directory发现的服务提供者列表子集,可以基于Condition或脚本(默认为JS脚本,其实现类为ScriptRouter)。
   3、LoadBalance
   负载均衡机制,其作用主要是根据负载均衡算法(随机、轮询)
等算法,从(Directory–>Router)中返回的服务提供者列表中选择一个服务提供者,进行本次的RPC服务调用。
4、Cluster
   集群(容错机制),就是当从服务提供者列表中按照负载均衡算法选择一个服务提供者,进行RPC服务调用后,发送了异常后的策略,例如failover(重试)、failfast(快速失败)等。
   服务的灰度发布,其目标是希望根据请求,某些请求走新版本服务器,某些请求走旧版本服务器,其本质就是路由机制,即通过一定的条件来缩小服务的服务提供者列表,正好与Dubbo的Router相吻合。

30 Dubbo源码

你可能感兴趣的:(10. Interview-Dubbo&ZooKeeper)