Zookeeper源碼閱讀(一)Jute和傳輸協議

前言

最近開始了Zookeeper的源碼閱讀和分析,也從如今開始把以前和如今學習到的一些Zookeeper的源碼知識和個人一些理解放到博客上。不得不說這是本身第一次去完整的看一個開源項目的完整源碼,從開始的第一步感受就遇到了坑= =並且多少還有些面對龐大代碼的茫然。在整個過程當中(過程還沒完,到如今爲止)零零散散看了很多博客的分析,可是感受都是針對某個小部分的分析,但願本身能從頭至尾把本身看的過程都寫下來,若是之後有別的同窗也想完整的瞭解瞭解Zookeeper的底層原理,但願個人博客能有點拋磚引玉的做用!php

搭建環境

我主要參考了兩篇博客:Zookeeper的源碼閱讀建議Zookeeper源碼閱讀--環境搭建、啓動服務demo。可是有個巨大巨大巨大的坑。。。不要從git上直接拉最新的代碼,即便是master分支的!能夠直接從Zookeeper的下載頁面下載成熟的版本,想看最新的代碼直接下最新發布的版本就能夠了。爲何要這樣呢???這裏有點血淚教訓。。。我記得前段時間從git上拉最新的代碼下來按照博客裏說的方式去跑單機版的server,死活啓動不起來。。。各類修改辦法都試過了,都沒有效果。最後我嘗試着下了成熟的發佈版本,而後一跑就能夠了。因此建議你們千萬下載成熟的發佈版本。html

包簡介

我這邊簡單說下包中類的大體做用,由於我也沒有徹底看完,因此這裏會持續更新:java

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

common包:公共工具類;git

client/server包:和client/server邏輯處理相關的類;apache

cli包:接收並執行用戶輸入的各類命令;json

jmx包:jmx監控;網絡

還有一些zookeeper包裏的類:session

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

相關文章
相關標籤/搜索