ZooKeeper源码阅读(二):客户端
源代码:
http://svn.apache.org/repos/asf/zookeeper/trunk/
导入eclipse:
在包含build.xml目录下执行ant eclipse将产生.classpath文件
目录结构:
src/recipes:提供了各种Zookeeper应用例子
src/c:提供了c版客户端。zookeeper_st,zookeeper_mt两个library
src/contrib:别人贡献的代码?
src/generated:由jute生成的java实体类
客户端入口:org.apache.zookeeper.ZooKeeperMain
//读取命令行输入,用MyCommandOptions解析。
//内部类MyCommandOptions包含成员命令名command、参数列表cmdArgs
-option value –option value command cmdArgs
//根据以上解析的ip、端口,连接到ZooKeeper
zk = newZooKeeper(host,
Integer.parseInt(cl.getOption("timeout")),
newMyWatcher(), readOnly);
//执行命令,在ZooKeeperMain.run()
//ZooKeeperMain只是一个外壳,使用jline实现了命令提示功能。
//commandMapCli将提供的命令命令名与执行体CliCommand关联
//execute from commandMap
CliCommandcliCmd = commandMapCli.get(cmd);
if(cliCmd!=null) {
cliCmd.setZk(zk);
watch =cliCmd.parse(args).exec();
}
//最终转到调用ZooKeeper方法
//提供的命令:
quit:Zk.close()关闭zk连接,调用cnxn.close()
history:列出历史记录
redo index:重新执行历史记录
printwatches [on]:查看/设置watche开关状态
connect:connectToZK(host)连接zk
//ZooKeeper内部连接
cnxn = newClientCnxn(connectStringParser.getChrootPath(),
hostProvider,sessionTimeout,this,watchManager,
getClientCnxnSocket(),canBeReadOnly);
cnxn.start();
ClientCnxn包含SendThread和EventThread两个线程
SendThread将事件添加到waitEvents队列中,EventThread线程消费该队列。
//下面以ls命令为例
//调用zk.getChildren
public boolean exec() throwsKeeperException, InterruptedException {
String path= args[1];
boolean watch =cl.hasOption("w");
List<String> children = zk.getChildren(path, watch);
out.println(children);
return watch;
}
//getChildren生成request
RequestHeader h = newRequestHeader();
h.setType(ZooDefs.OpCode.getChildren);
GetChildrenRequest request = newGetChildrenRequest();
request.setPath(serverPath);
request.setWatch(watcher != null);
GetChildrenResponse response = newGetChildrenResponse();
ReplyHeader r = cnxn.submitRequest(h, request,response, wcb);
//submitRequest调用queuePacket
publicReplyHeadersubmitRequest(RequestHeaderh, Record request,
Recordresponse, WatchRegistration watchRegistration)
throwsInterruptedException {
ReplyHeaderr = new ReplyHeader();
Packetpacket = queuePacket(h,r, request, response,null,null,null,
null, watchRegistration);
synchronized(packet) {
while (!packet.finished) {
packet.wait();
}
}
return r;
}
//queuePacket将Packet添加到outgoingQueue队列中
packet= new Packet(h, r, request, response,watchRegistration);
packet.cb = cb;
packet.ctx = ctx;
packet.clientPath =clientPath;
packet.serverPath =serverPath;
outgoingQueue.add(packet);
//然后唤醒selector
sendThread.getClientCnxnSocket().wakeupCnxn();
//sendThread.run消费outgoingQueue
clientCnxnSocket.doTransport(to,pendingQueue,outgoingQueue,ClientCnxn.this);
//selector判断读/写事件
//doTransport调用doIO,doIO解析Response
//读事件
int rc =sock.read(incomingBuffer);
sendThread.readResponse(incomingBuffer);
//写事件
sock.write(p.bb);
//readResponse在finally块中调用finishPacket,finishPacket将设置packet.finish,
//此时submitRequest返回response。
try {
packet.replyHeader.setXid(replyHdr.getXid());
packet.replyHeader.setErr(replyHdr.getErr());
packet.replyHeader.setZxid(replyHdr.getZxid());
if(replyHdr.getZxid() > 0) {
lastZxid =replyHdr.getZxid();
}
if(packet.response !=null&& replyHdr.getErr() == 0) {
packet.response.deserialize(bbia,"response");
}
} finally {
finishPacket(packet);
}
ZooKeeper源码阅读(二):客户端的更多相关文章
- ZooKeeper源码阅读——client(二)
原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群 要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...
- Zookeeper 源码(二)序列化组件 Jute
Zookeeper 源码(二)序列化组件 Jute 一.序列化组件 Jute 对于一个网络通信,首先需要解决的就是对数据的序列化和反序列化处理,在 ZooKeeper 中,使用了Jute 这一序列化组 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- xxl-job源码阅读二(服务端)
1.源码入口 xxl-job-admin是一个简单的springboot工程,简单翻看源码,可以很快发现XxlJobAdminConfig入口. @Override public void after ...
- Spring 源码阅读 二
程序入口: 接着上一篇博客中看完了在AnnotationConfigApplicationContext的构造函数中的register(annotatedClasses);将我们传递进来的主配置类添加 ...
- zookeeper源码分析二FASTLEADER选举算法
如何在zookeeper集群中选举出一个leader,zookeeper使用了三种算法,具体使用哪种算法,在配置文件中是可以配置的,对应的配置项是"electionAlg",其中1 ...
- zookeeper 源码(二) session 和 处理事务请求
问题 session 如何生成的?sessionId为什么不直接使用时间戳+单机名 sessionid 关闭的时候的逻辑,sessionid 的维护是由各节点还是leader ? 会话相关 sessi ...
- SparkConf加载与SparkContext创建(源码阅读二)
紧接着昨天,我们继续开搞了啊.. 1.下面,开始创建BroadcastManager,就是传说中的广播变量管理器.BroadcastManager用于将配置信息和序列化后的RDD.Job以及Shuff ...
- JDK源码阅读(二) AbstractList
package java.util; public abstract class AbstractList<E> extends AbstractCollection<E> i ...
随机推荐
- J2SE知识点摘记(四)
1. 抽象类(abstract) 抽象类和抽象方法都必须用abstract关键字来修饰. 抽象类不能被直接实例化,也就是不能直接用new关键字去产生对象. 抽象方法只需声明,而不需实现. ...
- overload的一点思考
仅参数类型不同的重载方法,使用过程的一个困惑: 有没有必要使用instanceof方法? package overload.special; public class OverLoadTest { p ...
- xxx.java: Recompile with -Xlint:deprecation for details
警告而已.有些方法1 已经过时,有更好的方法可以代替,比如 new java.util.Date().getYear(); => cal.get(Calendar.YEAR);2 发现过问题,且 ...
- #include <stdio.h>
1 fflush 2 fgetc 3 fgets 4 fprintf 5 fputc 6 fputs 7 fscanf 8 fseek 9 ftell 10 perror 11 remove 12 r ...
- iOS获取本地ip(基本通用)
今天有个朋友问我怎样訪问手机ip,上网找了几个,用了近200多行代码,最后发现头文件用的居然还是Linux中的,OC没有这个头文件.感觉socket本身应该能够后去自己的ip就试了一下,果然7.8行代 ...
- C#程序之Main()方法
一.Main()方法的简介 1.一般情况下,一个C#可执行程序只有一个应用程序对象(也就是就程序入口),但是在某些情况,可能会有多个应用程序对象(程序入口),如单元测试中,这个时候我们就需要通过命令行 ...
- iOS状态栏字体设置为白色
info.plist 添加字段: view controller -base status bar appearence 设为NO [[UIApplication sharedApplication] ...
- C# datetimePicker控件格式设置
//必须先设置Format属性为Custom,然后才能自定义格式 this.dtPicker.Format = DateTimePickerFormat.Custom; this.dtPicker.C ...
- 浅谈C中的指针和数组(五)
前面写了一些C指针和数组的一些知识,但是还有一些很重要的知识没有交代,这里做一个补充. 首先看一下,普通变量(指针也是变量)和数组名查看地址的方式是不同的. 查看数组变量的地址,不需要使用 & ...
- Programming C#.Inheritance and Polymorphism
继承 C#中,创建派生类要在派生类的名字后面加上冒号,后面再跟上基类的名字: public class ListBox : Control 提示:C++程序员注意了,C#没有私有或者保护继承 多态 继 ...