1)处理器链

这部分内容我们主要讲解zookeeper请求在zookeeper server端的处理流程,对于不同角色的zookeeper具有不同的处理流程, ZookeepeerServer的start方法中会调用setupRequestProcessors()来初始化处理器链,它被子类覆写实现。

1.      LeaderZooKeeperServer

看如上代码主要建立了如下的两个处理器流链

(1)    PrepRequestProcessor(线程) => ProposalRequestProcessor(调initialize) =>CommitProcessor(线程) => Leader.ToBeAppliedRequestProcessor=>FinalRequestProcessor

(2)  ProposalRequestProcessor构造器设置另一处理器链, initialize方法启动SyncRequestProcessor线程 SyncRequestProcessor(线程)=> AckRequestProcessor

2.      FollowerZooKeeperServer

看如上代码主要建立了如下的两个处理器流链

(1)  FollowerRequestProcessor  => CommitProcessor(线程)  =>FinalRequestProcessor(线程)

(2)  SyncRequestProcessor(线程)=> SendAckRequestProcessor

3.      ObserverZooKeeperServer

(1)    ObserverRequestProcessor => CommitProcessor(线程)  =>FinalRequestProcessor(线程)

(2)    SyncRequestProcessor(线程)=>  SendAckRequestProcessor

(3)    看如上代码主要建立了如下的两个处理器流链

2)处理器详解

各个processor的主要功能

1) PrepRequestProcessor

如名字这个处理器主要功能是对请求进行预处理, 将client向server请求二进制数据反序列化成sever中请求操作。

PrepRequestProcessor做为leader的第一个处理器,它的请求数据来源主要来自:

(1)    Leader做一个zk服务接收客户端请求提交到PrepRequestProcessor的队列中

(2)    作为集群的leader,在LearnerHanler.run方法中接收learner向leader发送的投票请求,消息类型为Leader.REQUEST

PrepRequestProcessor的处理流程:

(1)    对于非事物性请求:sync,exists, getData, getChildRen,ping, setWatches 这里只做session的检查看看是否超时

(2)    对于事务请求:create, delete,setData,setAcl,check,multi,根据请求的类型创建不同的操作如:type=create è CreateRequest, type=delete èDeleteRequest  等等

(3)    Zookeeper创建新的事务号zxid

(4)    创建并设置事务请求的消息头

(5)    反序列化网络client请求对象提取数据到事务对象的消息体中

PrepRequestProcessor线程 {

run {

1. submittedRequests.take()取出nio读取的请求

2. 根据请求type构建对应的record对象,并将request中的ByteBuffer数据,反序列化到record中

3. zks.getNextZxid() 生成一个新的事务号递增,作为zxid

4. 根据cxid,zxid, sessionId等构建事务头TxnHeader

5.1 对create/delete/setData/setACL/createSession/closeSession/check

1)checkSession,检测是否过期

2)创建对应的事务体CreateTxn/DeleteTxn等等

3)构建ChangeRecord加入到zks.outstandingChanges队列中去(FinalRequestProcessor会去处理,最终去改变数据)

5.2 exists/getData 只是 checkSession

6. 调下一个Processor

}

processRequest() {

//单机版被zookeeper调,将nio读取的请求加入到submittedRequests中

}

}

2)ProposalRequestProcessor

ProposalRequestProcessor的处理逻辑相对比较简单

(1)    转发到后面的处理器

(2)    如果是事务性请求(请求头存在的话),leader向follower发起操作请求,超过一半才算成功响应客户端

(3)    如果是事务性请求,调用leader的同步处理器流程

3)CommitProcessor

这个处理器逻辑还是有点小复杂的, leader和learner都需要用到这个处理器

3.1) 对于非事务性的操作(查询,exist等)直接回把请求转到下一个处理器处理

3.2) leader 对于事务性操作(create, setData等)请求,CommitProcessor线程任务会hold在这里,leader中ProposalRequestProcessor处理器会将请求提案发送给所有的followers, followers响应leader,然后leader中LearnerHandler会调processAck处理响应,当超过半数的时候将调CommitProcessor.commit()方法提交请求, 紧接着CommitProcessor将请求传递到下一个处理器处理

3.2) learner对于事务性操作(create, setData等)请求CommitProcessor线程任务会hold在这里, FollowerRequestProcessor或者ObserverRequestProcessor调CommitProcessor将请求提交队列之后会立刻向leader发送事务操作提案,Follower接收到leader的commit消息或者Observer接收到leader的inform消息它们会向CommitProcessor提交请求,紧接着CommitProcessor将请求传递到下一个处理器处理

伪代码:

CommitProcessor{

run() {

1. toProcess需要交予下一个Processor的,先都交给下一个

2. nextPending请求时对于事务操作的,有一个不为空一直循环直到有commit过来

3. queuedRequests.size() == 0&& committedRequests.size() > 0 follower observer接收commit ,加入到toProcess集合中去

4. nextPending != null&&  committedRequests.size() > 0  leader发起投票请求,并接收follower反馈的, 加入到toProcess集合中去

5. nextPending == null 前面循环

6.如果是请求reqeust是事务操作赋给nextPending对象

7.如果不是加入到toProcess集合中去

//这里主要通过nextPending对象控制请求响应的顺序

}

commit(Request){

将request添加到committedRequests队列中去

}

processRequest(Request) {

由上游处理器调用,将request对象添加到queuedRequests请求队列中

}

}

4)ToBeAppliedRequestProcessor

这个处理器的逻辑比较简单

1)   将请求转发给一下个处理器,必须是FinalRequestProcessor

2)   其实leader在走到这个处理器之前会在CommitProcessor中hod一会等到follower反馈在到这,follower反馈后leader的LearnerHandler的processAck会将请求加入toBeApplied集合,所以在这里对于事务请求一定会在toBeApplied中有对应的移除调,如果没有ConcurrentLinkedQueue直接会抛NoSuchElementException异常

5)FinalRequestProcessor

这个处理器是最后一个处理器,真正去执行事务操作更改dataree的数据。

1)   调底层修改数据zks.processTxn(hdr, txn)

2)   将请求加入到committedLog集合中

3)   构建请求的响应,响应客户端

伪代码:

FinalRequestProcessor{

processRequest(Request request) {

//zks.outstandingChanges这个玩意起什么作用,一直没弄清楚

1.事务头不为空,是事务类操作 {

zks.processTxn(hdr,txn) //zkServer处理事务操作

}

如果是closeSesion,无需生成响应

根据请求类型(request.type)生成响应,并调NioServerCnxn.sendResponse写入chanel通道

}

}

6) SyncRequestProcessor

这个处理器用来将请求记录到txLog文件中,通过批量刷盘的方式来提升io的性能,这里请求只有被写入到本地磁盘后,才会被传递到下一个处理器

下面看一下伪代码:

SyncRequestProcessor线程 {

run() {

//flush的时间点:1. queuedRequests为空 2.toFlush.size() > 1000

//生成新的snapshot

调zks.getZKDatabase().append(si)添加一条事务日志

1)成功:是事务类操作有事务头, 根据规则判断是否需要生一个新的snapshot,加入到toFlush的集合中

2)失败:没有事务头TxnHeader, 优化直接调下一个Processor

}

flush() {

zks.getZKDatabase().commit();同步到本snapshot

然后循环调下一个Processor

}

processRequest() {

加入到阻塞队列queuedRequests中, 让同步线程自己处理

}

}

7) AckRequestProcessor

被ProposalRequestProcessor调用, leader自己做一次投票的成功响应

8) SendAckRequestProcessor

对于leader投票请求的发送响应

3)交互图

1. 下面就用一张图来说明Leader端的处理器链的交互过程

2. 下面就用一张图来说明Follower(Observer类似)端的处理器链的交互过程

zookeeper原理解析-服务器端处理流程的更多相关文章

  1. zookeeper原理解析-客户端与服务器端交互

    Zookeeper集群中server数量总是确定的,所以集群中的server交互采用比较可靠的bio长连接模型:不同于集群中sever间交互zookeeper客户端其实数量是未知的,为了提高zooke ...

  2. zookeeper原理解析-数据存储

    Zookeeper内存结构 Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeepe ...

  3. zookeeper原理解析-选举

    1)QuorumPeerMain加载 Zookeeper集群启动的入口类是QuorumPeerMain来加载配置启动QuorumPeer线程.首先我们来看下QuorumPeer, 谷歌翻译quorum ...

  4. ZooKeeper学习之路 (八)ZooKeeper原理解析

    ZooKeeper中的各种角色 ZooKeeper与客户端 每个Server在工作过程中有三种状态: LOOKING:当前Server不知道leader是谁,正在搜寻 LEADING:当前Server ...

  5. ZooKeeper原理解析

    目录 ZooKeeper中的各种角色 ZooKeeper与客户端 Zookeeper节点数据操作流程 Paxos 算法概述(ZAB 协议) ZooKeeper 的选主机制 选择机制中的概念 选举消息内 ...

  6. zookeeper原理解析-序列化

    1)底层通信数据封装与操作           BinaryInputArchive& BinaryOutputArchive底层通信数据封装与操作     BinaryInputArchiv ...

  7. 1.zookeeper原理解析-数据存储之Zookeeper内存结构

    Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeeper也实现了类似数据库的功能. ...

  8. Zookeeper(三) Zookeeper原理与应用

    一.zookeeper原理解析 1.进群角色描述 2.Paxos 算法概述( ZAB 协议)    分布式一致性算法 3.Zookeeper 的选主(恢复模式) 以一个简单的例子来说明整个选举的过程. ...

  9. MS14-068(CVE-2014-6324)域控提权利用及原理解析

    漏洞利用 0x01 漏洞利用前提 1.域控没有打MS14-068的补丁(KB3011780) 2.拿下一台加入域的计算机 3.有这台域内计算机的域用户密码和Sid 0x02 工具下载 Ms14-068 ...

随机推荐

  1. nodejs微信公众号快速开发|自定义关键字回复

    一点说明: nodejs 微信api 扩展,集成大部分功能. 案例 https://github.com/leiroc/node-wxeasy-example 上传example中文件到服务器 ,然后 ...

  2. iOS-集成支付宝支付、微信支付简单总结

    支付宝快捷支付: 官方文档中,支付宝说建议我们使用支付时要讲签名过程放在服务器端,这样安全.同时给的demo中签名是在本地移动端做的...不过支付宝的集成还是较简单的. 为了安全签名当然放后台做了.我 ...

  3. SQL Server 2012 新特性:新增和修改函数

    转换函数      1.PARSE      Parse是把字符串类型转化为想要的类型,看看和convert和cast的区别         SELECT PARSE ('2.111111' AS f ...

  4. sqlserver中根据表中的配置概率取到数据

      create proc pr_zhanglei_test1 /*功能描述: 根据t_zhanglei_test1中perc设置的概率,取到相应数据old_id */ as declare @per ...

  5. [Android] 怎么在应用中实现密码隐藏?

    [Android] 怎么在应用中实现密码隐藏? 在安卓应用中,用户注册或者登录时,需要把密码隐藏,实现一定的保密效果.在安卓中,可以通过设置EditText组件的TransformationMetho ...

  6. 6-1 bash脚本编程之四 整数测试及特殊变量

    1. exit:退出脚本.可以定义,如 #exit 数字(0-255) 2. 文件测试 -e FILE:测试文件是否存在 -f FILE:测试文件是否为普通 -d FILE:测试指定路径是否为目录 - ...

  7. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  8. js判断用户是否正在滚动滚动条,滚动条滚动是否停止

    js智能判断是否可以自动滚动 比如,做一个音乐播放器,边播放,边定位歌词,播放的时候,需要自动定位到播放语句,但是用户去拖动或者滚动div(歌词面板)时,这时就必须停止自动滚动,或者说是不能自动滚动, ...

  9. 【原】pageResponse - 让H5适配移动设备全家(移动端适配)

    上一篇文章<为什么选择iPhone5的分辨率作为H5视觉稿尺寸>最后留下了问题:是否需要视觉设计师设计多套的视觉稿供给前端工程师做页面适配呢?按照自己以前的方法,通常会要求设计师设计2套的 ...

  10. SVM一点心得体会

    支持向量机的学习说是刚刚开始,又不合理,只能说隔了很长的时间再看,终于在分类这块的层面上有了新的认识. 总的来说,支持向量机分为线性支持向量机和非线性支持向量机,线性支持向量机又可以分为硬间隔最大化线 ...