一、前言

  在前面学习了Zookeeper中服务器的三种角色及其之间的通信,接着学习对于客户端的一次请求,Zookeeper是如何进行处理的。

二、请求处理

  2.1 会话创建请求

  Zookeeper服务端对于会话创建的处理,大体可以分为请求接收、会话创建、预处理、事务处理、事务应用和会话响应六大环节,其大体流程如


  1. 请求接收

  (1) I/O层接收来自客户端的请求。NIOServerCnxn维护每一个客户端连接,客户端与服务器端的所有通信都是由NIOServerCnxn负责,其负责统一接收来自客户端的所有请求,并将请求内容从底层网络I/O中完整地读取出来。

  (2) 判断是否是客户端会话创建请求。每个会话对应一个NIOServerCnxn实体,对于每个请求,Zookeeper都会检查当前NIOServerCnxn实体是否已经被初始化,如果尚未被初始化,那么就可以确定该客户端一定是会话创建请求。

  (3) 反序列化ConnectRequest请求。一旦确定客户端请求是否是会话创建请求,那么服务端就可以对其进行反序列化,并生成一个ConnectRequest载体。

  (4) 判断是否是ReadOnly客户端。如果当前Zookeeper服务器是以ReadOnly模式启动,那么所有来自非ReadOnly型客户端的请求将无法被处理。因此,服务端需要先检查是否是ReadOnly客户端,并以此来决定是否接受该会话创建请求。

  (5) 检查客户端ZXID。正常情况下,在一个Zookeeper集群中,服务端的ZXID必定大于客户端的ZXID,因此若发现客户端的ZXID大于服务端ZXID,那么服务端不接受该客户端的会话创建请求。

  (6) 协商sessionTimeout。在客户端向服务器发送超时时间后,服务器会根据自己的超时时间限制最终确定该会话超时时间,这个过程就是sessionTimeout协商过程。

  (7) 判断是否需要重新激活创建会话。服务端根据客户端请求中是否包含sessionID来判断该客户端是否需要重新创建会话,若客户单请求中包含sessionID,那么就认为该客户端正在进行会话重连,这种情况下,服务端只需要重新打开这个会话,否则需要重新创建。

  2. 会话创建

  (1) 为客户端生成sessionID。在为客户端创建会话之前,服务端首先会为每个客户端分配一个sessionID,服务端为客户端分配的sessionID是全局唯一的。

  (2) 注册会话。向SessionTracker中注册会话,SessionTracker中维护了sessionsWithTimeout和sessionsById,在会话创建初期,会将客户端会话的相关信息保存到这两个数据结构中。

  (3) 激活会话。激活会话涉及Zookeeper会话管理的分桶策略,其核心是为会话安排一个区块,以便会话清理程序能够快速高效地进行会话清理。

  (4) 生成会话密码。服务端在创建一个客户端会话时,会同时为客户端生成一个会话密码,连同sessionID一同发给客户端,作为会话在集群中不同机器间转移的凭证。

  3. 预处理

  (1) 将请求交给PrepRequestProcessor处理器处理。在提交给第一个请求处理器之前,Zookeeper会根据该请求所属的会话,进行一次激活会话操作,以确保当前会话处于激活状态,完成会话激活后,则提交请求至处理器。

  (2) 创建请求事务头。对于事务请求,Zookeeper会为其创建请求事务头,服务端后续的请求处理器都是基于该请求头来识别当前请求是否是事务请求,请求事务头包含了一个事务请求最基本的一些信息,包括sessionID、ZXID(事务请求对应的事务ZXID)、CXID(客户端的操作序列)和请求类型(如create、delete、setData、createSession等)等。

  (3) 创建请求事务体。由于此时是会话创建请求,其事务体是CreateSessionTxn。

  (4) 注册于激活会话。处理由非Leader服务器转发过来的会话创建请求。

  4. 事务处理

  (1) 将请求交给ProposalRequestProcessor处理器。与提议相关的处理器,从ProposalRequestProcessor开始,请求的处理将会进入三个子处理流程,分别是Sync流程、Proposal流程、Commit流程。

  Sync流程

  使用SyncRequestProcessor处理器记录事务日志,针对每个事务请求,都会通过事务日志的形式将其记录,完成日志记录后,每个Follower都会向Leader发送ACK消息,表明自身完成了事务日志的记录,以便Leader统计每个事务请求的投票情况。

  Proposal流程

  每个事务请求都需要集群中过半机器投票认可才能被真正应用到内存数据库中,这个投票与统计过程就是Proposal流程。

    · 发起投票。若当前请求是事务请求,Leader会发起一轮事务投票,在发起事务投票之前,会检查当前服务端的ZXID是否可用。

    · 生成提议Proposal。若ZXID可用,Zookeeper会将已创建的请求头和事务体以及ZXID和请求本身序列化到Proposal对象中,此Proposal对象就是一个提议。

    · 广播提议。Leader以ZXID作为标识,将该提议放入投票箱outstandingProposals中,同时将该提议广播给所有Follower。

    · 收集投票。Follower接收到Leader提议后,进入Sync流程进行日志记录,记录完成后,发送ACK消息至Leader服务器,Leader根据这些ACK消息来统计每个提议的投票情况,当一个提议获得半数以上投票时,就认为该提议通过,进入Commit阶段。

    · 将请求放入toBeApplied队列中。

    · 广播Commit消息。Leader向Follower和Observer发送COMMIT消息。向Observer发送INFORM消息,向Leader发送ZXID。

  Commit流程

    · 将请求交付CommitProcessor。CommitProcessor收到请求后,将其放入queuedRequests队列中。

    · 处理queuedRequest队列请求。CommitProcessor中单独的线程处理queuedRequests队列中的请求。

    · 标记nextPending。若从queuedRequests中取出的是事务请求,则需要在集群中进行投票处理,同时将nextPending标记位当前请求。

    · 等待Proposal投票。在进行Commit流程的同时,Leader会生成Proposal并广播给所有Follower服务器,此时,Commit流程等待,直到投票结束。

    · 投票通过。若提议获得过半机器认可,则进入请求提交阶段,该请求会被放入commitedRequests队列中,同时唤醒Commit流程。

    · 提交请求。若commitedRequests队列中存在可以提交的请求,那么Commit流程则开始提交请求,将请求放入toProcess队列中,然后交付下一个请求处理器:FinalRequestProcessor。

  5. 事务应用

  (1) 交付给FinalRequestProcessor处理器。FinalRequestProcessor处理器检查outstandingChanges队列中请求的有效性,若发现这些请求已经落后于当前正在处理的请求,那么直接从outstandingChanges队列中移除。

  (2) 事务应用。之前的请求处理仅仅将事务请求记录到了事务日志中,而内存数据库中的状态尚未改变,因此,需要将事务变更应用到内存数据库。

  (3) 将事务请求放入队列commitProposal。完成事务应用后,则将该请求放入commitProposal队列中,commitProposal用来保存最近被提交的事务请求,以便集群间机器进行数据的快速同步。

  6. 会话响应

  (1) 统计处理。Zookeeper计算请求在服务端处理所花费的时间,统计客户端连接的基本信息,如lastZxid(最新的ZXID)、lastOp(最后一次和服务端的操作)、lastLatency(最后一次请求处理所花费的时间)等。

  (2) 创建响应ConnectResponse。会话创建成功后的响应,包含了当前客户端和服务端之间的通信协议版本号、会话超时时间、sessionID和会话密码。

  (3) 序列化ConnectResponse。

  (4) I/O层发送响应给客户端。

  2.2 SetData请求

  服务端对于SetData请求大致可以分为四步,预处理、事务处理、事务应用、请求响应。

  1. 预处理

  (1) I/O层接收来自客户端的请求。

  (2) 判断是否是客户端"会话创建"请求。对于SetData请求,按照正常事务请求进行处理。

  (3) 将请求交给PrepRequestProcessor处理器进行处理。

  (4) 创建请求事务头。

  (5) 会话检查。检查该会话是否有效。

  (6) 反序列化请求,并创建ChangeRecord记录。反序列化并生成特定的SetDataRequest请求,请求中包含了数据节点路径path、更新的内容data和期望的数据节点版本version。同时根据请求对应的path,Zookeeper生成一个ChangeRecord记录,并放入outstandingChanges队列中。

  (7) ACL检查。检查客户端是否具有数据更新的权限。

  (8) 数据版本检查。通过version属性来实现乐观锁机制的写入校验。

  (9) 创建请求事务体SetDataTxn。

  (10) 保存事务操作到outstandingChanges队列中。

  2. 事务处理

  对于事务请求,服务端都会发起事务处理流程。所有事务请求都是由ProposalRequestProcessor处理器处理,通过Sync、Proposal、Commit三个子流程相互协作完成。

  3. 事务应用

  (1) 交付给FinalRequestProcessor处理器。

  (2) 事务应用。将请求事务头和事务体直接交给内存数据库ZKDatabase进行事务应用,同时返回ProcessTxnResult对象,包含了数据节点内容更新后的stat。

  (3) 将事务请求放入commitProposal队列。

  4. 请求响应

  (1) 创建响应体SetDataResponse。其包含了当前数据节点的最新状态stat。

  (2) 创建响应头。包含当前响应对应的事务ZXID和请求处理是否成功的标识。

  (3) 序列化响应。

  (4) I/O层发送响应给客户端。

  2.3 GetData请求

  服务端对于GetData请求的处理,大致分为三步,预处理、非事务处理、请求响应。

  1. 预处理

  (1) I/O层接收来自客户端的请求。

  (2) 判断是否是客户端"会话创建"请求。

  (3) 将请求交给PrepRequestProcessor处理器进行处理。

  (4) 会话检查。

  2. 非事务处理

  (1) 反序列化GetDataRequest请求。

  (2) 获取数据节点。

  (3) ACL检查。

  (4) 获取数据内容和stat,注册Watcher。

  3. 请求响应

  (1) 创建响应体GetDataResponse。响应体包含当前数据节点的内容和状态stat。

  (2) 创建响应头。

  (3) 统计处理。

  (4) 序列化响应。

  (5) I/O层发送响应给客户端。

三、总结

  本篇博文讲解了Zookeeper服务端对于客户端不同请求的处理的具体流程,可能从文字上看步骤会显得相对枯燥,但是会为之后的源码分析打下很好的基础,谢谢各位园友的观看~

【分布式】Zookeeper请求处理相关推荐

  1. 学习Docker容器网络模型 - 搭建分布式Zookeeper集群

    ZooKeeper是一个流行的分布式协调服务.它提供了两种不同的部署方式:单机模式和分布式模式.其中单机模式的部署非常简单,网上也有很多资料,我们今天会利用Docker搭建分布式Zookeeper集群 ...

  2. springboot分布式(zookeeper+Dubbo)

    文章目录 springBoot 分布式zookeeper+Dubbo 一.基础知识 单一应用架构 垂直应用架构 分布式架构 流动计算架构 什么是RPC? 二.Dubbo 什么是Dubbo 为什么使用D ...

  3. java zookeeper 使用场景_java架构之路-(分布式zookeeper)zookeeper真实使用场景

    上几次博客,我说了一下Zookeeper的简单使用和API的使用,我们接下来看一下他的真实场景. 一.分布式集群管理✨✨✨ 我们现在有这样一个需求,请先抛开Zookeeper是集群还是单机的概念,下面 ...

  4. 【扫盲系列】分布式+Zookeeper+Docker+K8S

    文章目录 一.分布式 概念 分布式锁 二.Zookeeper 概念 数据模型 基本操作和事件通知 Zookeeper的一致性 三.Docker 概念 四.K8S 概念 架构 一.分布式 概念 单机结构 ...

  5. 分布式Zookeeper安装搭建详解

    一.下载zookeeper安装包 在官网中下载,对于在墙内的用户,并不推荐该方式下载速度可能比较慢 推荐方式:在cloudera仓库进行下载,相较于官网下载更加稳定快速,地址http://archiv ...

  6. 《从Paxos到zookeeper分布式一致性原理与实践》笔记

    <从Paxos到zookeeper分布式一致性原理与实践>笔记 文章目录 <从Paxos到zookeeper分布式一致性原理与实践>笔记 一.概念 二.一致性协调 2.1 2P ...

  7. 《从Paxos到zookeeper分布式一致性原理与实践》

    <从Paxos到zookeeper分布式一致性原理与实践> 一.概念 ACID: Automaticy.consistency.isolation. Durability CAP: con ...

  8. ZooKeeper伪分布式集群安装及使用

    为什么80%的码农都做不了架构师?>>>    ZooKeeper伪分布式集群安装及使用 让Hadoop跑在云端系列文章,介绍了如何整合虚拟化和Hadoop,让Hadoop集群跑在V ...

  9. ZooKeeper:win7上安装单机及伪分布式安装

    zookeeper是一个为分布式应用所设计的分布式的.开源的调度服务,它主要用来解决分布式应用中经常遇到的一些数据管理问题,简化分布式应用,协调及其管理的难度,提高性能的分布式服务. 本章的目的:如何 ...

最新文章

  1. 布线干货 | 线缆截面积的测量标准
  2. 某设备产品漏洞挖掘-从JS文件挖掘RCE
  3. Redis性能问题排查解决手册(值得收藏)
  4. mysql cluster cge (commercial)_Mysql 产品分类和版本说明
  5. dataTables去掉搜索框,每页多少条框体,解决Cannot reinitialise DataTable问题,以及数据格式ajax等问题...
  6. 浅谈常见的NoSQL技术方案和选型
  7. GitHub 疑遭中间人攻击,最大暗网托管商再被黑!
  8. 三步走!从头开始设计一款游戏
  9. RQNOJ 169 最小乘车费用
  10. 土方回填施工方案范本_土方回填施工方案.doc.docx
  11. git push you are not allowed to upload merges
  12. java实现微软文本转语音(TTS)经验总结
  13. time_wait,不要乱用tcp_tw_recycle和net.ipv4.tcp_tw_reuse
  14. CameraX Java 1.0.0-alpha10 安卓开发
  15. 材料化学博士后-谷歌offer的转行总结 -- 转自一亩三分地
  16. 用JavaScript在网页右下角弹出窗口
  17. 深度学习之细粒度分类
  18. Python复习系列:Python基础知识(三)
  19. promise的优点promise.all(),promise.race(),promise.allSettled()的原理
  20. js 正则匹配邮箱_JS正则表达式验证手机号和邮箱

热门文章

  1. 显示驱动包含在Linux内核层,驱动程序层(上) - Linux内核--网络栈实现分析_Linux编程_Linux公社-Linux系统门户网站...
  2. matlab 地埋管温度场,地埋管换热器周围土壤冻结温度场的模拟研究
  3. matlab腔内光子寿命,mcFORnp matlab环境下,利用蒙特卡洛模拟光子包在生物组织内的光路传输 271万源代码下载- www.pudn.com...
  4. 函数 php_PHP回调函数及匿名函数概念与用法详解
  5. 自动生成文章的html,文章自动更新工具|自动生成文件|自动伪原创|文章自动插入关键词工具...
  6. ajax得到session,Ajax如何使用Session
  7. 谭浩强课后题之----输出10个数中最大的
  8. 很多人都不知道的小秘密,c++中拷贝分为两种
  9. hibench 压测flink_【原创】大数据基础之Benchmark(1)HiBench
  10. LeetCode:198:打家劫舍