zookeeper原理解析-客户端与服务器端交互
Zookeeper集群中server数量总是确定的,所以集群中的server交互采用比较可靠的bio长连接模型;不同于集群中sever间交互zookeeper客户端其实数量是未知的,为了提高zookeeper并发性能,zookeeper客户端与服务器端交互采用nio模型。下面我们主要来讲讲zookeeper的服务器端与客户端的交互。读者对nio不了解的话不妨抽点时间去了解下,对于一些nio框架如netty,mina再如一些web容器如tomcat,jetty底层都实现一套nio框架,对于实现nio框架模型大家不妨去谷歌百度搜一下Doug Lea的scalable io in Java 这个ppt。
客户端
ClientCnxnSocketNIO是zookeeper的nio通讯层的客户端部分,下面伪代码示例其核心代码:
ClientCnxnSocketNIO{
doTransport() {
if (如果之前连接没有立马连上,则在这里处理OP_CONNECT事件) {
sendThread.primeConnection();
} else {
doIO
}
//队列中有发送的消息, 开启写
}
doIO() {
if (sockKey.isReadable()) {
sendThread.readResponse(incomingBuffer);
updateLastHeard();
}
if(sockKey.isWritable()) {
Packetp = outgoingQueue.getFirst() //从发送队列取
updateLastSend
p.requestHeader.setXid(cnxn.getXid());//设置客户端的xid
序列化
发送
从发送队列删除
加入到pendingQueue队列
}
}
}
ClientCnxn 是客户端操作ClientCnxnSocketNIO的工具,维护了发送任务线程SendThread,事件任务线程EventThead, 发送队列OutgoingQueue以及请求消息的等待队列PendingQueue。下面以伪代码来示例其核心代码
ClientCnxn {
outgoingQueue//待向服务器端发送的队列, 客户端提交请求放入这个队列
pendingQueue //发送以后等待响应的队列,
submitRequest(){
//client端一个封装成一个packet
outgoingQueue.add(packet);
selector.wakeup();
packet.wait(); //如果是同步调用wait,应该反馈后会
}
SendThread {
run() {
1.设置clientCnxnSocket 最后发送时间,最后的心跳时间
2. if(!clientCnxnSocket.isConnected()) {
startConnect() //主要工作clientCnxnSocket做
} else {
计算下次ping的时间, 发送心跳
委托给 clientCnxnSocket.doTranspor进行底层的nio传输
}
}
primeConnection(){
//构建ConnectRequest
//组合成通讯层的Packet对象,添加到发送队列,对于ConnectRequest其requestHeader为null
outgoingQueue.addFirst
clientCnxnSocket.enableReadWriteOnly();//确保读写事件都监听
}
readResponse(){
1.先读响应头,先对特殊的xid进行处理
2. packet = pendingQueue.remove() //由于client和server都是单线程处理,多队列处理,所以认为全局有序
3. 反序列化响应体response, 并设置到packet上
4.finishPacket 1)同步notifyAll,结束 2)异步加入到event线程的队列
}
}
EventThread{ //主要支持异步的回调
run() {
}
}
}
大家观察客户端操作类Zookeeper里面的操作类主要分为两个参数不带callback的同步方法和参数带callback的异步方法。
1. 同步调用方法实现类似Future同步转异步模式实现
1) Client提交请求对象封装成packet对象放入OutgoingQueue队列,并调用packet.wait()阻塞当前线程。
2) 每个Client都只有一个SendThread线程是线性处理OutgoingQueue中的请求消息的,SendThread线程通过ClientCnxnSocketNIO工具顺序从OutgoingQueue队列中取请求消息发送到服务器端,同时将请求packet加入到PendingQueue中
3) ClientCnxnSocketNIO工具接收处理服务器端响应
4) 从PendingQueue队列取出对应的packet,并调packet.notifyAll()唤醒阻塞的线程完成同步调用
2. 异步调用的总体流程跟同步类似关键区别在于
1) 向OutgoingQueue队列提交请求后,不会调用packet.wait()阻塞当前线程,主流程继续执行
2) 同同步调用
3) 同同步调用
4) 从PendingQueue队列取出对应的packet,并调packet.callback方法完成回调处理
Zookeeper服务器端
NIOServerCnxnFactory工厂类,zookeeperserver用来启动监听客户端连接,每当有客户端请求连接进来,NIOServerCnxnFactory都会为这个链接构建NIOServerCnxn 实例来单独处理与这个客户端的交互
NIOServerCnxn封装了处理读取客户端请求数据与及向客户端响应数据
下面通过伪代码来实例:
NIOServerCnxnFactory {
configure {
绑定端口
作为server监听
注册selectkey 的连接时间
}
run { //起到accept的作用
1. OP_ACCEPT, 将NIOServerCnxn(handler) attach到selectkey以便被读写事件使用
2. OP_READ 和 OP_WRITE取出handler NIOServerCnxn,并调doIo
}
}
NIOServerCnxn {
构造器 {
//设置selectkey对read感兴趣
}
doIo {
if(k.isReadable()) {
1. 读前四个字节, 代表请求内容长度,不包括自己的4字节
2. 读取到字节数组中
3. zkServer.processPacket()或者zkServer.processConnectRequest()
}
if(k.isWritable()) {
1.从outgoingBuffers取ByteBuffer
2.发送bytes
}
}
}
zookeeper原理解析-客户端与服务器端交互的更多相关文章
- 浅析Java web程序之客户端和服务器端交互原理(转)
转载自http://www.cnblogs.com/lys_013/archive/2012/05/05/2484561.html 1. 协议 a. TCP/IP整体构架概述 TCP/IP协议并不完全 ...
- [转]HTTP报文接口及客户端和服务器端交互原理
1. 协议 a. TCP/IP整体构架概述 TCP/IP协议并不完全符合OSI的七层参考模型.传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务.该模型的目的 ...
- 浅析Java web程序之客户端和服务器端交互原理
原文链接: https://www.iteye.com/topic/470019 1. 协议 a. TCP/IP整体构架概述 TCP/IP协议并不完全符合OSI的七层参考模型.传统的开放式系统互连参考 ...
- Request 接收参数乱码原理解析一:服务器端解码原理
“Server.UrlDecode(Server.UrlEncode("北京")) == “北京””,先用UrlEncode编码然后用UrlDecode解码,这条语句永远为true ...
- zookeeper原理解析-服务器端处理流程
1)处理器链 这部分内容我们主要讲解zookeeper请求在zookeeper server端的处理流程,对于不同角色的zookeeper具有不同的处理流程, ZookeepeerServer的sta ...
- zookeeper原理解析-数据存储
Zookeeper内存结构 Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeepe ...
- zookeeper原理解析-选举
1)QuorumPeerMain加载 Zookeeper集群启动的入口类是QuorumPeerMain来加载配置启动QuorumPeer线程.首先我们来看下QuorumPeer, 谷歌翻译quorum ...
- zookeeper原理解析-序列化
1)底层通信数据封装与操作 BinaryInputArchive& BinaryOutputArchive底层通信数据封装与操作 BinaryInputArchiv ...
- TCP网络协议通信原理(客户端和服务器端)
下面直接用代码来说明TCP协议的基础知识: 服务器端代码块: from socket import * from time import ctime ''' 指定主机地址.工作端口号.接收缓存的长度 ...
随机推荐
- 自定义UITabBarController标签视图控制器
首先创建一个类,继承自UItabBarController 然后在.m文件中: 这里我有两个宏定义: #define WIDTH (myView.frame.size.width / 4) //我在写 ...
- iOS 消息处理之performSelector
//// RootViewController.h// DSCategories//// Created by dasheng on 15/12/17.// Copyright © 2015年 ...
- 软件工程随笔(1)--jetbrain在软件工程中的应用
接下来几天我要写半年的软件工程学习后的感想,今天从介绍IDE开始.首先,本人至今为止全部项目都是在mypclise上完成的.本人采用myeclipse唯一的原因就是它使用方便.但是,我也承认myecl ...
- ASP.NET MVC 5 04 - 控制器
PS: 唉.本来这一篇前几天早就应该发了的,可是谁每月没有那么几天啊... 呵呵.开个玩笑.反正就是各种烦气,所以也就一直没上来继续发了. 年底了,摆正一下心态吧.好好干,整点钱,过年回家能跟亲朋好友 ...
- 随机生成长度为len的密码,且包括大写、小写英文字母和数字
一道华三面试题,随机生成长度为len的密码,且包括大写.小写英文字母和数字,主要Random类的使用,random.nextInt(len)表示生成[0,len)整数.具体实现见下面代码,已经很详细了 ...
- python随心笔记
print "hello,world" #打印hello,world print "1+1" #打印字符串 1+1 单引号和双引号是单行字符串 print [& ...
- Java开发代码性能优化总结
代码优化,可能说起来一些人觉得没用.可是我觉得应该平时开发过程中,就尽量要求自己,养成良好习惯,一个个小的优化点,积攒起来绝对是有大幅度效率提升的.好了,将平时看到用到总结的分享给大家. 代码优化的目 ...
- Hadoop技巧(01):插件,终端权限
阅读目录 序 HDFS权限 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 在ha ...
- Redis在游戏服务器中的应用
排行榜游戏服务器中涉及到很多排行信息,比如玩家等级排名.金钱排名.战斗力排名等.一般情况下仅需要取排名的前N名就可以了,这时可以利用数据库的排序功能,或者自己维护一个元素数量有限的top集合.但是有时 ...
- Go语言开发第一个Hello,World
在网上看到go语言的各种评价,也是闻名已久,但是没有自己实践过,也不知道它的好,它的坏,今天就来试试第一个小程序 第一步.如何下载 1)下载go安装程序 下载地址:https://golang.org ...