## Zookeeper源码阅读(一)Jute和传输协议

前言

最近开始了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确实没有在别的地方见到用过,但是总体的生成步骤大概就是根据配置文件的内容去生成的,负责生成类的那些类在ort.apache.jute.compiler.jute下,有兴趣可以看下。

通信协议

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接口

猜你喜欢

转载自www.cnblogs.com/gongcomeon/p/9610936.html
今日推荐