Zookeeper 源码(二)序列化组件 Jute

一、序列化组件 Jute

对于一个网络通信,首先需要解决的就是对数据的序列化和反序列化处理,在 ZooKeeper 中,使用了Jute 这一序列化组件来进行数据的序列化和反序列化操作。同时,为了实现一个高效的网络通信程序,良好的通信协议设计也是至关重要的。Zookeeper 团队曾想过将 Jute 替换成 Apache 的 Avro 或是 Google 的 protobuf 但是考虑到新老版本序列化组件的兼容性和当前 Jute 的序列化能力并不是 ZooKeeper 的性能瓶颈。

import org.apache.jute.*;
import org.apache.zookeeper.server.ByteBufferInputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer; public class JuteHeader implements Record { private long sessionId;
private String type; public JuteHeader() {
} public JuteHeader(long sessionId, String type) {
this.sessionId = sessionId;
this.type = type;
} @Override
public void serialize(OutputArchive outputArchive, String tag) throws IOException {
outputArchive.startRecord(this, tag);
outputArchive.writeLong(sessionId, "sessionId");
outputArchive.writeString(type, "type");
outputArchive.endRecord(this, tag);
} @Override
public void deserialize(InputArchive inputArchive, String tag) throws IOException {
inputArchive.startRecord(tag);
sessionId = inputArchive.readLong("sessionId");
type = inputArchive.readString("type");
inputArchive.endRecord(tag);
} public static void main(String[] args) throws IOException { final String tag = "header";
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
new JuteHeader(100001L, "xxx").serialize(boa, tag); // 包装成 ByteBuffer 用于网络传输
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); // 反序列化
ByteBufferInputStream bbis = new ByteBufferInputStream(bb);
BinaryInputArchive bbia = BinaryInputArchive.getArchive(bbis);
JuteHeader header = new JuteHeader();
header.deserialize(bbia, tag); baos.close();
bbis.close();
} }

二、Zookeeper 通信协议

基于 TCP/IP 协议,ZooKeeper 实现了自己的通信协议来完成客户端与服务端、服务端与服务端之间的网络通信。ZooKeeper 通信协议整体上的设计非常简单,对于请求,主要包含请求头和请求体,而对于晌应,则主要包含响应头和响应体,

协议的请求头组成如下:

Packet 类中的 createBB() 将 packet 对象序列化:

public void createBB() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
boa.writeInt(-1, "len"); // We'll fill this in later
if (requestHeader != null) {
requestHeader.serialize(boa, "header");
}
if (request instanceof ConnectRequest) {
request.serialize(boa, "connect");
// append "am-I-allowed-to-be-readonly" flag
boa.writeBool(readOnly, "readOnly");
} else if (request != null) {
request.serialize(boa, "request");
}
baos.close();
this.bb = ByteBuffer.wrap(baos.toByteArray());
this.bb.putInt(this.bb.capacity() - 4);
this.bb.rewind();
} catch (IOException e) {
LOG.warn("Ignoring unexpected exception", e);
}
}

请求头:

public class RequestHeader implements Record {
private int xid;
private int type; public void serialize(OutputArchive a_, String tag) throws java.io.IOException {
a_.startRecord(this,tag);
a_.writeInt(xid,"xid");
a_.writeInt(type,"type");
a_.endRecord(this,tag);
} public void deserialize(InputArchive a_, String tag) throws java.io.IOException {
a_.startRecord(tag);
xid=a_.readInt("xid");
type=a_.readInt("type");
a_.endRecord(tag);
}
}

请求体有多种,如 ConnectRequest、CreateRequest ...:

public class ConnectRequest implements Record {
private int protocolVersion;
private long lastZxidSeen;
private int timeOut;
private long sessionId;
private byte[] passwd; public void serialize(OutputArchive a_, String tag) throws java.io.IOException {
a_.startRecord(this,tag);
a_.writeInt(protocolVersion,"protocolVersion");
a_.writeLong(lastZxidSeen,"lastZxidSeen");
a_.writeInt(timeOut,"timeOut");
a_.writeLong(sessionId,"sessionId");
a_.writeBuffer(passwd,"passwd");
a_.endRecord(this,tag);
}
public void deserialize(InputArchive a_, String tag) throws java.io.IOException {
a_.startRecord(tag);
protocolVersion=a_.readInt("protocolVersion");
lastZxidSeen=a_.readLong("lastZxidSeen");
timeOut=a_.readInt("timeOut");
sessionId=a_.readLong("sessionId");
passwd=a_.readBuffer("passwd");
a_.endRecord(tag);
}
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

Zookeeper 源码(二)序列化组件 Jute的更多相关文章

  1. zookeeper源码 — 二、集群启动—leader选举

    上一篇介绍了zookeeper的单机启动,集群模式下启动和单机启动有相似的地方,但是也有各自的特点.集群模式的配置方式和单机模式也是不一样的,这一篇主要包含以下内容: 概念介绍:角色,服务器状态 服务 ...

  2. ZooKeeper源码阅读——client(二)

    原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群   要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...

  3. Zookeeper源码(启动+选举)

    简介 关于Zookeeper,目前普遍的应用场景基本作为服务注册中心,用于服务发现.但这只是Zookeeper的一个的功能,根据Apache的官方概述:"The Apache ZooKeep ...

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

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

  5. Zookeeper 源码(三)Zookeeper 客户端源码

    Zookeeper 源码(三)Zookeeper 客户端源码 Zookeeper 客户端主要有以下几个重要的组件.客户端会话创建可以分为三个阶段:一是初始化阶段.二是会话创建阶段.三是响应处理阶段. ...

  6. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  7. Unity UGUI图文混排源码(二)

    Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...

  8. Django-restframework 源码之认证组件源码分析

    Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...

  9. Tomcat8源码笔记(七)组件启动Server Service Engine Host启动

    一.Tomcat启动的入口 Tomcat初始化简单流程前面博客介绍了一遍,组件除了StandardHost都有博客,欢迎大家指文中错误.Tomcat启动类是Bootstrap,而启动容器启动入口位于 ...

随机推荐

  1. 使用GitHub进行项目创建——初级,非指令版,纯软件操作

    主要步骤如下: 1.申请一个GitHub账号,官网按照步骤来就行 2.下载一个GitHub DeskTop(https://desktop.github.com/),命令什么的以后说不定会写把 3.创 ...

  2. 《DSP using MATLAB》 Problem 2.3

    本题主要是显示周期序列的. 1.代码: %% ------------------------------------------------------------------------ %% O ...

  3. (转)类的sizeof

    来源:http://www.360doc.com/content/12/0315/17/3349869_194600377.shtml

  4. ssh框架中spring整合hibernate的配置文件模板(带详细注释)

    applicationContext.xml的配置文件模板 <?xml version="1.0" encoding="UTF-8"?> <b ...

  5. MacOS 如何截屏

    在Mac OS X下有很强大的截屏功能,它不仅仅是对屏幕的全屏COPY,而是包括很多细节在里面,就从这点来看,已经比过所有版本的Windows了. 下面我来向大家详细介绍一下: 对全屏的截图我们可以通 ...

  6. 使用IAR编译STM8S 怎样生产烧录文件

      IAR编译后能够生成的烧录文件格式有4中,例如以下 第一种是Motorola,其生成文件和STVD生成烧录文件.s19格式一样的,即能够通用 另外一种是16进制,keil等等常都用到的. 第三种是 ...

  7. IDEA java开发学习笔记

    JDK8下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 配置环境变量 ...

  8. Dictionary字典类介绍

    说明     必须包含名空间System.Collection.Generic      Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)      键必须是唯一的,而值不 ...

  9. Java多线程编程核心技术,第五章

    1,Timer timer = new Timer(true)现在是守护进程 2,timer是按照顺的,没有异步 3,timer方法,schedule(TimerTask task, Date fir ...

  10. 遍历树节点(多层)的方法(java)

    前序遍历,后序遍历,广度遍历,深度遍历,遍历一级节点.以及按钮如何响应点击事件. import java.awt.*; import java.awt.event.*; import java.uti ...