前言

最近开始了Zookeeper的源码阅读和分析,也从现在开始把之前和现在学习到的一些Zookeeper的源码知识和我的一些理解放到博客上。不得不说这是自己第一次去完整的看一个开源项目的完整源码,从开始的第一步感觉就遇到了坑= =而且多少还有些面对庞大代码的茫然。在整个过程中(过程还没完,到现在为止)零零散散看了不少博客的分析,但是感觉都是针对某个小部分的分析,希望自己能从头到尾把自己看的过程都写下来,如果以后有别的同学也想完整的了解了解Zookeeper的底层原理,希望我的博客能有点抛砖引玉的作用!

搭建环境

我主要参考了两篇博客:Zookeeper的源码阅读建议和Zookeeper源码阅读--环境搭建、启动服务demo。但是有个巨大巨大巨大的坑。。。不要从git上直接拉最新的代码,即使是master分支的!可以直接从Zookeeper的下载页面下载成熟的版本,想看最新的代码直接下最新发布的版本就可以了。为什么要这样呢???这里有点血泪教训。。。我记得前段时间从git上拉最新的代码下来按照博客里说的方式去跑单机版的server,死活启动不起来。。。各种修改办法都试过了,都没有效果。最后我尝试着下了成熟的发布版本,然后一跑就可以了。所以建议大家千万下载成熟的发布版本。

包简介

我这边简单说下包中类的大致作用,因为我也没有完全看完,所以这里会持续更新:

jute包:是Zookeeper使用的序列化工具Jute相关的。

common包:公共工具类;

client/server包:和client/server逻辑处理相关的类;

cli包:接收并执行用户输入的各种命令;

jmx包:jmx监控;

还有一些zookeeper包里的类:

Watcher/WathcedEvent:和监听事件有关的接口和类;

Zookeeper/ZookeeperMain:用户和Zookeeper交互;

Jute

正题开始。。。Jute对我自己也是比较陌生的,之前也没有接触过。也是在看Zookeeper代码的时候边看边查了一些,这边大致的总结下Jute的用法和在Zookeeper里的一些代码。

Record接口

@InterfaceAudience.Public
public interface Record {public void serialize(OutputArchive archive, String tag)throws IOException;public void deserialize(InputArchive archive, String tag)throws IOException;
}

所有需要序列化的类都必须实现Record接口。在serialize和deserialize方法中,OutputArchive/InputArchive类是Jute底层真正用来做序列化和反序列化的类,并且它们可以为多个对象进行序列化/反序列化操作,这也是方法中tag存在的作用,用来标识对象。

下面是org.apache.zookeeper.data.ID的serialize和deserialize方法的实现。

public void serialize(OutputArchive a_, String tag) throws java.io.IOException {a_.startRecord(this,tag);a_.writeString(scheme,"scheme");a_.writeString(id,"id");a_.endRecord(this,tag);}public void deserialize(InputArchive a_, String tag) throws java.io.IOException {a_.startRecord(tag);scheme=a_.readString("scheme");id=a_.readString("id");a_.endRecord(tag);
}

可以看到其实和其他的序列化工具一样,也都是一个写一个读。

OutputArchive和InputArchive接口

特别的是这里OutputArchive和InputArchive也是接口。其中他们的实现类如下:

Binary的实现一般是为了网络传输和本地磁盘存储的,也是最底层的序列化方式;

CSV的实现更多的是为了方便数据对象的可视化展现;

XML的是为了把数据保存为XML格式的文件。

特别的是:

在Zookeeper中有一个zookeeper.jute文件,里面定义了所有实体类的包,类名以及该类所有的成员变量及其类型。如下:

module org.apache.zookeeper.data {class Id {ustring scheme;ustring id;}class ACL {int perms;Id id;}...

Jute会根据这个配置文件生成一些类,这些都实现了Record接口且都在generated包下。但是对于生成类的详细步骤我也没有深入研究,也只知道个大概,因为Jute确实没有在别的地方见到用过,但是总体的生成步骤大概就是根据配置文件的内容去生成的,负责生成类的那些类在src/java/generated/org/apache/zookeeper下,有兴趣可以看下。

通信协议

zookeeper的通信协议是基于TCP/IP的,和http的报文的基本格式还是挺像的。都主要由请求头和请求主体组成。

len header body
0-3 xid(4-7) + type(8-11) len(12-15) + path(16-totalLen-1) + watch(totalLen)

请求头

请求头类是RequestHeader,也是Jute生成的类。

@InterfaceAudience.Public
public class RequestHeader implements Record {private int xid;private int type;...

请求头中xid是记录客户端请求发起的先后序号,用来标识单个客户端请求的先后顺序;

type代表的是请求的操作类型,对应的数字存储在OpCode接口中,种类太多了就不粘贴上来了。

请求体

  1. ConnectRequest
    public class ConnectRequest implements Record {private int protocolVersion;private long lastZxidSeen;private int timeOut;private long sessionId;private byte[] passwd;...
  2. GetDataRequest
    public class GetDataRequest implements Record {private String path;private boolean watch;
  3. SetDataRequest
    public class SetDataRequest implements Record {private String path;private byte[] data;private int version;

请求体里主要也就是这三种类型,很简单,而且都是Jute生成的。具体数据是什么看一下域的命名就知道了。

响应头

public class ReplyHeader implements Record {private int xid;private long zxid;private int err;

zxid代表服务端最新的事务id,err是错误码。

响应体

  1. ConnectResponse
    public class ConnectResponse implements Record {private int protocolVersion;private int timeOut;private long sessionId;private byte[] passwd;
  2. GetDataResponse
    public class GetDataResponse implements Record {private byte[] data;private org.apache.zookeeper.data.Stat stat;

    Stat类存的是znode的相关信息。

  3. SetDataResponse
    public class SetDataResponse implements Record {private org.apache.zookeeper.data.Stat stat;

这些和请求的都是一一对应的,很简单。

思考

去查Jute资料的时候了解到了挺多先进的序列化工具类似fastjson,protobuf,以后可以深入看看。

参考

我把我当时看的一些地方都简单说了说,因为这些地方都是些实体类,没有太多逻辑,所以没有详细介绍逻辑的部分,也算是抛砖引玉,如果想深入看看这个部分,可以参考下面的link。

zk源码分析之序列化

jute与protobuf

Jute分析

Record接口

转载于:https://www.cnblogs.com/gongcomeon/p/9610936.html

Zookeeper源码阅读(一)Jute和传输协议相关推荐

  1. zookeeper 源码阅读(3)

    接着zookeeper 源码阅读(2) 这里详细看下工厂模式创建的zkServer,后面在介绍分析那三种选举算法 public class QuorumPeer extends ZooKeeperTh ...

  2. zookeeper 源码阅读(2)

    接着zookeeper 源码阅读(1) Zookeeper服务器的启动,大致可以分为以下五个步骤 1. 配置文件解析. 2. 初始化数据管理器. 3. 初始化网络I/O管理器. 4. 数据恢复. 5. ...

  3. ZooKeeper源码阅读心得分享+源码基本结构+源码环境搭建

    首发CSDN:徐同学呀,原创不易,转载请注明源链接.我是徐同学,用心输出高质量文章,希望对你有所帮助. 一.心得分享 如何阅读ZooKeeper源码?从哪里开始阅读?最近把ZooKeeper源码看了个 ...

  4. zookeeper 源码阅读(1)

    对于源码阅读的几点建议和方式: 1.尽量本地调试可以跑起来代码 2.debug 日志梳理代码执行流程,这样起到事半功倍的作用 3.干巴巴看代码毫无意义,难度极大 zk 是分别有c语言编写的和java ...

  5. ZooKeeper 源码和实践揭秘

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:runnerzhang,腾讯 CSIG 后台开发工程 ...

  6. 干货 | ZooKeeper 源码和实践揭秘

    精选30+云产品,助力企业轻松上云!>>> 摘要:ZooKeeper 是个针对大型分布式系统的高可用.高性能且具有一致性的开源协调服务,被广泛的使用.对于开发人员,ZooKeeper ...

  7. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  8. Zookeeper源码分析(二) ----- zookeeper日志

    zookeeper源码分析系列文章: Zookeeper源码分析(一) ----- 源码运行环境搭建 原创博客,纯手敲,转载请注明出处,谢谢! 既然我们是要学习源码,那么如何高效地学习源代码呢?答案就 ...

  9. 【Dubbo源码阅读系列】之远程服务调用(上)

    今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...

最新文章

  1. 2002年3月英伟达发布核弹GPU与大算力自动驾驶芯片
  2. 关于const 修饰的一些知识
  3. Java集合框架之 Java HashMap 源码解析
  4. eWebEditor 错误 (不支持 ie7 ie8 maxthon 及其它浏览器)终极办法
  5. java代码杨辉三角_用java实现杨辉三角的示例代码
  6. Jar包冲突解决方法 Unknown lifecycle phase mvn Eclipse中执行maven命令
  7. Kotlin中使用RxJAVA的map()操作符遇到的问题
  8. Pix4D生成正射影像和DSM详细教程(可下载)
  9. PHP自学笔记 ---李炎恢老师PHP第一季 TestGuest0.8
  10. UE4蓝图 绑定输入
  11. javaWeb随机生成网页验证码图片
  12. PHPWord 表格居中和合并单元格
  13. Wireshark实验
  14. PHP给PDF文件加水印(mpdf插件)
  15. 工程部署: 低算力平台模型性能的优化
  16. 《系统集成项目管理》第七章 项目范围管理
  17. python时间戳是什么意思_Python-时间戳
  18. iOS 3DES加密解密(一行代码搞定)
  19. Bert实战--文本分类(一)
  20. 基于C语言的 WAV 文件双声道转单声道的实现

热门文章

  1. sat2 计算机科目,SAT2各科目含金量
  2. 阿里云 IP 地理位置库(淘宝IP库)实践(前篇)
  3. 自动调参NNI 模型设置与log信息设置
  4. Spring系列学习之Spring LDAP
  5. windows写入延缓失败怎么办?
  6. 研究生宿舍大盘点!是谁留下了羡慕的泪水?
  7. while和switch循环如何使用
  8. java.util.sortedmap_Java SortedMap 接口
  9. 四六级口语|考研复试口语|满满干货
  10. Miniconda基本使用