RPC框架系列——Avro
1.下载与安装
官方网站:http://avro.apache.org/
下载地址:http://labs.renren.com/apache-mirror//avro/avro-1.5.1/avro-src-1.5.1.tar.gz
安装之前确保已经装了maven
- cd /usr/local/src
- wget http://labs.renren.com/apache-mirror//avro/avro-1.5.1/avro-src-1.5.1.tar.gz
- tar zxvf avro-src-1.5.1.tar.gz
- cd avro-src-1.5.1/lang/java
- mvn clean install -DskipTests
安装后,avro-1.5.1.jar位于avro-src-1.5.1/lang/java/avro/target
2.消息结构与服务接口
Avro的模式主要由JSON对象来表示,Avro支持8种基本类型(Primitive Type)和6种复杂类型(Complex Type:records、enums、arrays、maps、unions 和fixed),基本类型可以由JSON字符串来表示。
Avro支持两种序列化编码方式:二进制编码和JSON编码,使用二进制编码会高效序列化,并且序列化后得到的结果会比较小。
基本类型:
- null: no value
- boolean: a binary value
- int: 32-bit signed integer
- long: 64-bit signed integer
- float: single precision (32-bit) IEEE 754 floating-point number
- double: double precision (64-bit) IEEE 754 floating-point number
- bytes: sequence of 8-bit unsigned bytes
- string: unicode character sequence
首先编写一个message.avpr文件,定义一个消息结构。
- {
- "namespace": "avro",
- "protocol": "messageProtocol",
- "doc": "This is a message.",
- "name": "Message",
- "types": [
- {"name":"message", "type":"record",
- "fields":[
- {"name":"name", "type":"string"},
- {"name":"type", "type":"int"},
- {"name":"price", "type":"double"},
- {"name":"valid", "type":"boolean"},
- {"name":"content", "type":"bytes"}
- ]}
- ],
- "messages": {
- "sendMessage":{
- "doc" : "test",
- "request" :[{"name":"message","type":"message" }],
- "response" :"message"
- }
- }
- }
其中定义了1种类型叫做message,有5个成员name、type、price、valid、content。还定义了1个消息服务叫做sendMessage,输入有一个参数,类型是message,返回message。
3.序列化
Avro有两种序列化编码:binary和JSON。
3.1.Binary Encoding
基本类型:
null:0字节
boolean:1个字节——0(false)或1(true)
int和long使用变长的zig-zag编码
float:4个字节
double:8个字节
bytes:1个long,后边跟着字节序列
string:1个long,后边跟着UTF-8编码的字符
3.2.records
按字段声明的顺序编码值,如下面一个record schema:
- {
- "type": "record",
- "name": "test",
- "fields" : [
- {"name": "a", "type": "long"},
- {"name": "b", "type": "string"}]
- }
实例化这个record,a字段的值是27(编码为0×36),b字段的值是“foo”(编码为06 66 6f 6f),那么这个record编码结果是:
- 36 06 66 6f 6f
3.3.enums
一个enum被编码为一个int,比如,考虑这个enum。
- {"type": "enum", "name": "Foo", "symbols": ["A", "B", "C", "D"] }
这将被编码为一个取值范围为[0,3]的int,0表示“A”,3表示“D”。
3.4.arrays
arrays编码为block序列,每个block包含一个long的count值,紧跟着的是array items,一个block的count为0表示该block是array的结尾。
3.5.maps
mapss编码为block序列,每个block包含一个long的count值,紧跟着的是key/value对,一个block的count为0表示该block是map的结尾。
3.6.union
union编码以一个long值开始,表示后边的数据是union中的哪种数据类型。
3.7.fixed
编码为指定数目的字节。
4.rpc通信实现
Avro的RPC实现不需要定义服务接口,但需要从.avpr文件中解析协议,协议中定义了消息结构和消息服务。message.avpr中定义了一个类型叫message,定义了一个服务叫sendMessage。
工具类Utils.java:
- package avro;
- import java.io.File;
- import java.io.IOException;
- import java.net.URL;
- import org.apache.avro.Protocol;
- public class Utils {
- public static Protocol getProtocol() {
- Protocol protocol = null;
- try {
- URL url = Utils.class.getClassLoader().getResource("message.avpr");
- protocol = Protocol.parse(new File(url.getPath()));
- } catch (IOException e) {
- e.printStackTrace();
- }
- return protocol;
- }
- }
服务端实现Server.java:
- package avro;
- import org.apache.avro.Protocol;
- import org.apache.avro.Protocol.Message;
- import org.apache.avro.generic.GenericRecord;
- import org.apache.avro.ipc.HttpServer;
- import org.apache.avro.ipc.generic.GenericResponder;
- public class Server extends GenericResponder {
- private Protocol protocol = null;
- private int port;
- public Server(Protocol protocol, int port) {
- super(protocol);
- this.protocol = protocol;
- this.port = port;
- }
- public Object respond(Message message, Object request) throws Exception {
- GenericRecord req = (GenericRecord) request;
- GenericRecord msg = (GenericRecord)(req.get("message"));
- // process the request
- …
- return msg;
- }
- public void run() {
- try {
- HttpServer server = new HttpServer(this, port);
- server.start();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- if (args.length != 1) {
- System.out.println("Usage: Server port");
- System.exit(0);
- }
- int port = Integer.parseInt(args[0]);
- new Server(Utils.getProtocol(), port).run();
- }
- }
客户端实现Client.java:
- package avro;
- import java.net.URL;
- import java.nio.ByteBuffer;
- import java.util.Arrays;
- import org.apache.avro.util.Utf8;
- import org.apache.avro.Protocol;
- import org.apache.avro.generic.GenericData;
- import org.apache.avro.generic.GenericRecord;
- import org.apache.avro.ipc.HttpTransceiver;
- import org.apache.avro.ipc.Transceiver;
- import org.apache.avro.ipc.generic.GenericRequestor;
- public class Client {
- private Protocol protocol = null;
- private String host = null;
- private int port = 0;
- private int size = 0;
- private int count = 0;
- public Client(Protocol protocol, String host, int port, int size, int count) {
- this.protocol = protocol;
- this.host = host;
- this.port = port;
- this.size = size;
- this.count = count;
- }
- public long sendMessage() throws Exception {
- GenericRecord requestData = new GenericData.Record(
- protocol.getType("message"));
- // initiate the request data
- …
- GenericRecord request = new GenericData.Record(protocol.getMessages()
- .get("sendMessage").getRequest());
- request.put("message", requestData);
- Transceiver t = new HttpTransceiver(new URL("http://" + host + ":"
- + port));
- GenericRequestor requestor = new GenericRequestor(protocol, t);
- long start = System.currentTimeMillis();
- for (int i = 0; i < count; i++) {
- requestor.request("sendMessage", request);
- }
- long end = System.currentTimeMillis();
- System.out.println(end - start);
- return end - start;
- }
- public long run() {
- long res = 0;
- try {
- res = sendMessage();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return res;
- }
- public static void main(String[] args) throws Exception {
- if (args.length != 4) {
- System.out.println("Usage: Client host port dataSize count");
- System.exit(0);
- }
- String host = args[0];
- int port = Integer.parseInt(args[1]);
- int size = Integer.parseInt(args[2]);
- int count = Integer.parseInt(args[3]);
- new Client(Utils.getProtocol(), host, port, size, count).run();
- }
- }
5.参考资料
(1) Avro Documentation: http://avro.apache.org/docs/current/index.html
RPC框架系列——Avro相关推荐
- RPC框架系列——Protocol Buffers
http://blog.jeoygin.org/2011/09/rpc-framework-protocol-buffers.html 1.下载与安装 官方网站:http://code.google. ...
- RPC框架系列MessagePack
1.下载与安装 官方网站:http://msgpack.org/ 下载地址:https://github.com/msgpack/msgpack-rpc, https://github.com/msg ...
- 使用Akka实现简单RPC框架
使用Akka实现简单RPC框架 最近简单看了看Flink的RPC通讯相关的源码,它是通过Akka实现的,为了更好的阅读理解代码,又大体看了看Akka相关的知识.这篇文章主要记录了如果使用Akka来实现 ...
- 高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架
优知学院 2019-01-22 18:43:51 之前持续分享的几十期阿里Java面试题中,几乎每次必问Dubbo,比如:"如何从0到1设计一个Dubbo的RPC框架",其实主要考 ...
- 新浪微博新兵训练营系列课程——平台RPC框架介绍
新浪微博新兵训练营系列课程--平台RPC框架介绍 课程大纲 1.RPC简介 1.1 什么是RPC 1.2 RPC与其他远程调用方式比较 2.Motan RPC框架 2.1 RPC服务框架 2.2 Mo ...
- server如何调用 thrift_一文带你了解 Thrift,一个可伸缩的跨语言 RPC 框架(pinpoint 源码分析系列)...
Thrift 是什么研究分布式调用链工具pinpoint的时候,在源码里看到了Thrift相关的代码,所以来了兴趣,想研究研究这个框架.Thrift 目前是 Apache 的一个项目,但是它是由fac ...
- [转]新兵训练营系列课程——平台RPC框架介绍
原文:http://weibo.com/p/1001643875439147097368 课程大纲 1.RPC简介 1.1 什么是RPC 1.2 RPC与其他远程调用方式比较 2.Motan RPC框 ...
- RPC系列之Netty实现自定义RPC框架
进行这个章节之前,需要去看一下RMI的实现哈,如果了解过的童鞋可以直接跳过,如果没有或者不知道RMI的童鞋,移驾到下面的链接看完之后再回来继续看这篇 RPC系列之入门_阿小冰的博客-CSDN博客RPC ...
- RPC框架原理及从零实现系列博客(二):11个类实现简单RPC框架
项目1.0版本源码 https://github.com/wephone/Me... 在上一博文中 跟大家讲了RPC的实现思路 思路毕竟只是思路 那么这篇就带着源码给大家讲解下实现过程中的各个具体问题 ...
最新文章
- (C++)strlen(),strcmp(),strcpy(),strcat()用法
- Selenium Webdriver原理终于搞清楚了
- 函数式接口、方法引用
- Jacoco的原理(各个覆盖率的解释)
- ThreadLocal的重要方法介绍
- 东南大学4系短学期matlab,东南大学短学期混凝土教学实践
- 清明梦超能力者黄YY、异或树(线段树合并)
- 使用jackson对Java对象与JSON字符串相互转换的一些总结
- Android 一个Activity 里面放置多个 Fragment 实现点击切换的Tab 页面效果
- 关于HTML+CSS常用标签
- RDKit化学式 分子式搜索
- Window 平台下添加 tree 命令
- vivo安装android wear,vivo谷歌框架下载-vivo谷歌服务框架v4.1.2 安卓版 - 极光下载站...
- DOS攻击工具——pentmenu
- matlab语言与测绘,MATLAB语言及测绘数据处理应用
- c语言编程齿轮模数选择,斜齿轮变位系数分配-C程序.doc
- 前端项目实战11-hook usememo使用
- wpf label下划线不显示的问题
- 电压监测器:线性稳压IC 台湾合泰LDO系列
- 资料分享:送你一本《数据结构与算法:Python语言描述》电子书!