1.下载与安装

  官方网站:http://avro.apache.org/

  下载地址:http://labs.renren.com/apache-mirror//avro/avro-1.5.1/avro-src-1.5.1.tar.gz

  安装之前确保已经装了maven

  1. cd /usr/local/src
  2. wget http://labs.renren.com/apache-mirror//avro/avro-1.5.1/avro-src-1.5.1.tar.gz
  3. tar zxvf avro-src-1.5.1.tar.gz
  4. cd avro-src-1.5.1/lang/java
  5. 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编码,使用二进制编码会高效序列化,并且序列化后得到的结果会比较小。

  基本类型:

  1. null: no value
  2. boolean: a binary value
  3. int: 32-bit signed integer
  4. long: 64-bit signed integer
  5. float: single precision (32-bit) IEEE 754 floating-point number
  6. double: double precision (64-bit) IEEE 754 floating-point number
  7. bytes: sequence of 8-bit unsigned bytes
  8. string: unicode character sequence

  首先编写一个message.avpr文件,定义一个消息结构。

  1. {
  2. "namespace": "avro",
  3. "protocol": "messageProtocol",
  4. "doc": "This is a message.",
  5. "name": "Message",
  6. "types": [
  7. {"name":"message", "type":"record",
  8. "fields":[
  9. {"name":"name", "type":"string"},
  10. {"name":"type", "type":"int"},
  11. {"name":"price", "type":"double"},
  12. {"name":"valid", "type":"boolean"},
  13. {"name":"content", "type":"bytes"}
  14. ]}
  15. ],
  16. "messages":    {
  17. "sendMessage":{
  18. "doc" : "test",
  19. "request" :[{"name":"message","type":"message" }],
  20. "response" :"message"
  21. }
  22. }
  23. }

  其中定义了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:

  1. {
  2. "type": "record",
  3. "name": "test",
  4. "fields" : [
  5. {"name": "a", "type": "long"},
  6. {"name": "b", "type": "string"}]
  7. }

  实例化这个record,a字段的值是27(编码为0×36),b字段的值是“foo”(编码为06 66 6f 6f),那么这个record编码结果是:

  1. 36 06 66 6f 6f

3.3.enums

  一个enum被编码为一个int,比如,考虑这个enum。

  1. {"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:

  1. package avro;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.net.URL;
  5. import org.apache.avro.Protocol;
  6. public class Utils {
  7. public static Protocol getProtocol() {
  8. Protocol protocol = null;
  9. try {
  10. URL url = Utils.class.getClassLoader().getResource("message.avpr");
  11. protocol = Protocol.parse(new File(url.getPath()));
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. return protocol;
  16. }
  17. }

  服务端实现Server.java:

  1. package avro;
  2. import org.apache.avro.Protocol;
  3. import org.apache.avro.Protocol.Message;
  4. import org.apache.avro.generic.GenericRecord;
  5. import org.apache.avro.ipc.HttpServer;
  6. import org.apache.avro.ipc.generic.GenericResponder;
  7. public class Server extends GenericResponder {
  8. private Protocol protocol = null;
  9. private int port;
  10. public Server(Protocol protocol, int port) {
  11. super(protocol);
  12. this.protocol = protocol;
  13. this.port = port;
  14. }
  15. public Object respond(Message message, Object request) throws Exception {
  16. GenericRecord req = (GenericRecord) request;
  17. GenericRecord msg = (GenericRecord)(req.get("message"));
  18. // process the request
  19. return msg;
  20. }
  21. public void run() {
  22. try {
  23. HttpServer server = new HttpServer(this, port);
  24. server.start();
  25. } catch (Exception e) {
  26. e.printStackTrace();
  27. }
  28. }
  29. public static void main(String[] args) {
  30. if (args.length != 1) {
  31. System.out.println("Usage: Server port");
  32. System.exit(0);
  33. }
  34. int port = Integer.parseInt(args[0]);
  35. new Server(Utils.getProtocol(), port).run();
  36. }
  37. }

  客户端实现Client.java:

  1. package avro;
  2. import java.net.URL;
  3. import java.nio.ByteBuffer;
  4. import java.util.Arrays;
  5. import org.apache.avro.util.Utf8;
  6. import org.apache.avro.Protocol;
  7. import org.apache.avro.generic.GenericData;
  8. import org.apache.avro.generic.GenericRecord;
  9. import org.apache.avro.ipc.HttpTransceiver;
  10. import org.apache.avro.ipc.Transceiver;
  11. import org.apache.avro.ipc.generic.GenericRequestor;
  12. public class Client {
  13. private Protocol protocol = null;
  14. private String host = null;
  15. private int port = 0;
  16. private int size = 0;
  17. private int count = 0;
  18. public Client(Protocol protocol, String host, int port, int size, int count) {
  19. this.protocol = protocol;
  20. this.host = host;
  21. this.port = port;
  22. this.size = size;
  23. this.count = count;
  24. }
  25. public long sendMessage() throws Exception {
  26. GenericRecord requestData = new GenericData.Record(
  27. protocol.getType("message"));
  28. // initiate the request data
  29. GenericRecord request = new GenericData.Record(protocol.getMessages()
  30. .get("sendMessage").getRequest());
  31. request.put("message", requestData);
  32. Transceiver t = new HttpTransceiver(new URL("http://" + host + ":"
  33. + port));
  34. GenericRequestor requestor = new GenericRequestor(protocol, t);
  35. long start = System.currentTimeMillis();
  36. for (int i = 0; i < count; i++) {
  37. requestor.request("sendMessage", request);
  38. }
  39. long end = System.currentTimeMillis();
  40. System.out.println(end - start);
  41. return end - start;
  42. }
  43. public long run() {
  44. long res = 0;
  45. try {
  46. res = sendMessage();
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. return res;
  51. }
  52. public static void main(String[] args) throws Exception {
  53. if (args.length != 4) {
  54. System.out.println("Usage: Client host port dataSize count");
  55. System.exit(0);
  56. }
  57. String host = args[0];
  58. int port = Integer.parseInt(args[1]);
  59. int size = Integer.parseInt(args[2]);
  60. int count = Integer.parseInt(args[3]);
  61. new Client(Utils.getProtocol(), host, port, size, count).run();
  62. }
  63. }

5.参考资料

  (1) Avro Documentation: http://avro.apache.org/docs/current/index.html

RPC框架系列——Avro相关推荐

  1. RPC框架系列——Protocol Buffers

    http://blog.jeoygin.org/2011/09/rpc-framework-protocol-buffers.html 1.下载与安装 官方网站:http://code.google. ...

  2. RPC框架系列MessagePack

    1.下载与安装 官方网站:http://msgpack.org/ 下载地址:https://github.com/msgpack/msgpack-rpc, https://github.com/msg ...

  3. 使用Akka实现简单RPC框架

    使用Akka实现简单RPC框架 最近简单看了看Flink的RPC通讯相关的源码,它是通过Akka实现的,为了更好的阅读理解代码,又大体看了看Akka相关的知识.这篇文章主要记录了如果使用Akka来实现 ...

  4. 高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架

    优知学院 2019-01-22 18:43:51 之前持续分享的几十期阿里Java面试题中,几乎每次必问Dubbo,比如:"如何从0到1设计一个Dubbo的RPC框架",其实主要考 ...

  5. 新浪微博新兵训练营系列课程——平台RPC框架介绍

    新浪微博新兵训练营系列课程--平台RPC框架介绍 课程大纲 1.RPC简介 1.1 什么是RPC 1.2 RPC与其他远程调用方式比较 2.Motan RPC框架 2.1 RPC服务框架 2.2 Mo ...

  6. server如何调用 thrift_一文带你了解 Thrift,一个可伸缩的跨语言 RPC 框架(pinpoint 源码分析系列)...

    Thrift 是什么研究分布式调用链工具pinpoint的时候,在源码里看到了Thrift相关的代码,所以来了兴趣,想研究研究这个框架.Thrift 目前是 Apache 的一个项目,但是它是由fac ...

  7. [转]新兵训练营系列课程——平台RPC框架介绍

    原文:http://weibo.com/p/1001643875439147097368 课程大纲 1.RPC简介 1.1 什么是RPC 1.2 RPC与其他远程调用方式比较 2.Motan RPC框 ...

  8. RPC系列之Netty实现自定义RPC框架

    进行这个章节之前,需要去看一下RMI的实现哈,如果了解过的童鞋可以直接跳过,如果没有或者不知道RMI的童鞋,移驾到下面的链接看完之后再回来继续看这篇 RPC系列之入门_阿小冰的博客-CSDN博客RPC ...

  9. RPC框架原理及从零实现系列博客(二):11个类实现简单RPC框架

    项目1.0版本源码 https://github.com/wephone/Me... 在上一博文中 跟大家讲了RPC的实现思路 思路毕竟只是思路 那么这篇就带着源码给大家讲解下实现过程中的各个具体问题 ...

最新文章

  1. (C++)strlen(),strcmp(),strcpy(),strcat()用法
  2. Selenium Webdriver原理终于搞清楚了
  3. 函数式接口、方法引用
  4. Jacoco的原理(各个覆盖率的解释)
  5. ThreadLocal的重要方法介绍
  6. 东南大学4系短学期matlab,东南大学短学期混凝土教学实践
  7. 清明梦超能力者黄YY、异或树(线段树合并)
  8. 使用jackson对Java对象与JSON字符串相互转换的一些总结
  9. Android 一个Activity 里面放置多个 Fragment 实现点击切换的Tab 页面效果
  10. 关于HTML+CSS常用标签
  11. RDKit化学式 分子式搜索
  12. Window 平台下添加 tree 命令
  13. vivo安装android wear,vivo谷歌框架下载-vivo谷歌服务框架v4.1.2 安卓版 - 极光下载站...
  14. DOS攻击工具——pentmenu
  15. matlab语言与测绘,MATLAB语言及测绘数据处理应用
  16. c语言编程齿轮模数选择,斜齿轮变位系数分配-C程序.doc
  17. 前端项目实战11-hook usememo使用
  18. wpf label下划线不显示的问题
  19. 电压监测器:线性稳压IC 台湾合泰LDO系列
  20. 资料分享:送你一本《数据结构与算法:Python语言描述》电子书!

热门文章

  1. 9个精品AI开源免费实战项目助你掌握AI工程师基本技能
  2. 广告图片自动轮播控件
  3. Django站内消息通知
  4. 分析网络钓鱼的原理及防御措施
  5. DDR5内存条容量计算
  6. Nexus学习日记:N7K VDC命令详解
  7. (大白话版)子网划分、进制换算
  8. 网易校招编程题目之牛牛分苹果
  9. 组原4_指令偏移寻址
  10. 公司MES项目现场落地实施总结