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. 【C#】Lambda

    介绍 Lambda 表达式是一种可用于创建 委托 或 表达式目录树 类型的 匿名函数 . 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. Lambda 表达式对 ...

  2. Netty5.x 和3.x、4.x的区别及注意事项(官方翻译)

    Netty5.x 和3.x.4.x的区别及注意事项 (官方翻译) 本文档列出了Netty5新版本中值得注意变化和新特性列表.帮助你的应用更好的适应新的版本.   不像Netty3.x和4.x之间的变化 ...

  3. 利用WeX5给手机APP增加短信验证码功能

    帖子来源:http://bbs.wex5.com/thread-70908-1-1.html 遇到一个手机APP项目客户要求注册到APP上的用户手机号必须是真实的通过X5平台整合短信发送平台接口完成了 ...

  4. Azkaban 使用问题及解决

    什么是Azkaban Azkaban是一款基于Java编写的任务调度系统 任务调度:有四个任务脚A.B.C.D,其中任务A与任务B可以并行运行,然后任务C依赖任务A和任务B的运行结果,任务D依赖任务C ...

  5. MySQL 多表关联更新及删除

    目录: <MySQL中的两种临时表> <MySQL 多表关联更新及删除> <mysql查询优化之三:查询优化器提示(hint)> 一.      多表关联更新 问题 ...

  6. Charles 3断点篡改数据

    只是临时修改一次网络请求结果,使用重写过于麻烦.对于临时性的修改,最好使用断点. 断点功能主要修改requess和response内容,这个时候接口是在Charles代理层被拦截,还未到手机设备上. ...

  7. 《OpenCL异构并行编程实战》补充笔记散点,第一至四章

    ▶ 总体印象:适合 OpenCL 入门的书,有丰富的代码和说明,例子较为简单.先把 OpenCL 代码的基本结构(平台 → 设备 → 上下文 → 命令队列 → 创建缓冲区 → 读写缓冲区 → 编译代码 ...

  8. shell脚本实现tomcat进程—查、杀、启

    #!/bin/bash#获取XXX项目进程IDXXXpid=`ps -ef | grep XXX | grep -v grep | awk '{print $2}'` echo "XXX项目 ...

  9. hex文件和bin文件区别

    HEX文件和BIN文件是我们经常碰到的2种文件格式.因为自己也是新手,所以一直对这两个文件懵懵懂懂,不甚了解,最近在做STM32单片机的IAP更新,其中要考虑HEX文件和BIN文件,所以需要学习下这两 ...

  10. 自动把\r\n 替换成<p></p>

    function nl2p($string, $line_breaks = true, $xml = true) { // Remove existing HTML formatting to avo ...