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. test20181019 B君的第三题

    题意 B 君的第三题(urumqi) 题目描述 风雨如晦,鸡鸣不已. B 君最近在研究自己的学长都在做什么工作,每个学长属于一个公司. B 君会获得一些信息,比如x 和y 在相同公司,x 和y 在不同 ...

  2. Phonegap 工程项目介绍

    一.工程项目的路径在www下面,www下面的文件如下图 1. index.html <!DOCTYPE html> <!-- Licensed to the Apache Softw ...

  3. Mac 下使用brew install 报错: Cowardly refusing to `sudo brew install'

    Mac 下使用brew install 报错: localhost:infer-osx-v0.6.0 admin$ sudo brew install opam Error: Cowardly ref ...

  4. Ubuntu 16.04 natural scrolling

    http://ubuntuhandbook.org/index.php/2016/05/install-ubuntu-tweak-in-ubuntu-16-04/ download ubuntu-tw ...

  5. lambda架构简介

    1.Lambda架构背景介绍 Lambda架构是由Storm的作者Nathan Marz提出的一个实时大数据处理框架.Marz在Twitter工作期间开发了著名的实时大数据处理框架Storm,Lamb ...

  6. 需登录账号与密码的网页爬取demo

    public static String connect(String dataUrl){ String result = null; try { HttpClient httpclient = ne ...

  7. Python实现进度条总结

    先说一下文本系统的控制符:\r:   将光标移动到当前行的首位而不换行:\n:   将光标移动到下一行,并不移动到首位:\r\n: 将光标移动到下一行首位.     环境:root@ubuntu16: ...

  8. T-SQL 总结

    SP0_AddLinkedServer.sql [创建Linked SQL Server ] USE [master] GO ) drop procedure dbo.SP_Temp_AddLinke ...

  9. Vue基础知识之过滤器(四)

    过滤器 1.过滤器的用法,用 '|' 分割表达式和过滤器. 例如:{{ msg | filter}} {{msg | filter(a)}} a就标识filter的一个参数. 用两个过滤器:{{msg ...

  10. Linux nohup和&的功效

    nohup和&究竟有啥区别?不少同学进行了回复,但并不是所有同学都理解得全对,今天把自己挖的坑自己填了. 测试代码如下: 是一个输出hello与循环轮数的死循环程序,每输出一行就休眠1秒. 使 ...