Apache Avro-[1]-序列化
来源:互联网 发布:湖南网络作协 编辑:程序博客网 时间:2024/06/07 19:30
入门
RPC
Avro官网:
http://avro.apache.org/
https://wiki.apache.org/hadoop/Avro/
https://github.com/phunt/avro-rpc-quickstart
jar下载地址:http://mirror.bit.edu.cn/apache/avro/avro-1.7.7/java/
官方实例:http://avro.apache.org/docs/current/gettingstartedjava.html
Apache Avro 与 Thrift 比较:http://www.alidata.org/archives/1307
Avro的三种序列化方法
参考(多谢分享):
http://blog.csdn.net/zhu_tianwei/article/details/44042691http://blog.csdn.net/u013054888/article/details/64444908
一、简介
Avro是Hadoop中的一个子项目,也是Apache中一个独立的项目,Avro是一个基于二进制数据传输高性能的中间件。在Hadoop的其他项目中例如HBase(Ref)和Hive(Ref)的Client端与服务端的数据传输也采用了这个工具,Avro可以做到将数据进行序列化,适用于远程或本地大批量数据交互。在传输的过程中Avro对数据二进制序列化后节约数据存储空间和网络传输带宽。做个比方:有一个100平方的房子,本来能放100件东西,现在期望借助某种手段能让原有面积的房子能存放比原来多150件以上或者更多的东西,就好比数据存放在缓存中,缓存是精贵的,需要充分的利用缓存有限的空间,存放更多的数据。再例如网络带宽的资源是有限的,希望原有的带宽范围能传输比原来高大的数据量流量,特别是针对结构化的数据传输和存储,这就是Avro存在的意义和价值。Avro还可以做到在同一系统中支持多种不同语言,也有点类似Apache的另一个产品:Thrift(Ref),对于Thrift不同的是Avro更加具有灵活性,Avro可以支持对定义的数据结构(Schema)动态加载,利于系统扩展。使用Avro可以通过2中方式来实现:1.二进制编码,Avro-specific方式依赖代码(文件)生成特定类,并内嵌JSON Schema;2.JSON编码,Avro-generic方式通过JSON文件动态加载Schema,不需要编译加载直接就可以处理新的数据源。我肤浅的认为,两者的区别在于同样的数据大小,在二进制编码下所产生的Avro数据的大小为100个字节,而在JSON编码下产生了450个字节。虽然看起来第1种二进制编码的方式占据一定优势,但是二进制传输最大的问题就是出了 bug 不方便追查,而JSON编码的方式更实用于系统与系统之间的数据通讯。 Avro支持本地和远程RPC(Ref)调用,RPC远程调用又分为Http和Netty2种,在这里主要介绍基于Http协议的Avro远程调用,首先需要定义一个JSON文件作为双方通信的传输协议规范,便于解析从对方发送过来的数据。在这个协议中可以看做分为3大部分: 1.描述(Protocol Declaration),定义命名空间,协议名称 等。 2.数据类型(types),根据规范中的Primitive和Complex Types数据类型,自己封装一套数据格式。 3.消息(messages),根据自己定义的数据类型,再去定义 a)请求、b)回应、c)异常(可选) 数据格式。特点:1.丰富的数据结构类型2.快速可压缩的二进制数据形式3.存储持久数据的文件容器4.远程过程调用(RPC)5.同动态语言的简单集成。读写数据文件和使用RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现。由于性能高、基本代码少和产出数据量精简等特点,Avro周围展开了众多活动——许多NoSQL实现,包括Hadoop、Cssandra等,都把Avro整合到它们的客户端API和储存功能中。Avro有C, C++, C#, Java, PHP, Python, and Ruby等语言的实现,下面我们以一个实例来说明Avro序列化和反序列化数据。Avro官网:http://avro.apache.org/jar下载地址:http://mirror.bit.edu.cn/apache/avro/avro-1.8.2/java/
定义了一个用户的记录,在模式定义中,必须包含它的类型(“type”: “record”)、一个名字(“name”: “User”)以及fields。在本例中fields包括了name, age和phone,上面的模式我们还定义了一个命名空间 (“namespace”: “cn.slimsmart.avro.demo”),namespace可以名字一起使用,从而组成模式的全名(即com.learn.User)
user.avsc如下:{ "namespace": "com.learn", "type": "record", "name": "User", "fields": [ { "name": "name", "type": "string" }, { "name": "age", "type": [ "int", "null" ] }, { "name": "phone", "type": [ "string", "null" ] } ]}二、编译模式
Avro可以允许我们根据模式的定义而生成相应的类,一旦我们定义好相关的类,我们程序中就不需要直接使用模式了。
可以用avro-tools jar包来生成代码,语法如下:
java -jar ./avro-tools-1.7.7.jar compile schema <schema file> <destination>
这里我们用java -jar ./avro-tools-1.8.2.jar compile schema user.avsc . (这里有个.)
这时候,在当前目录下会生成com.learn/User.java类如果你直接用Avro Maven plugin,
那么你就不需要手动的编译模式,因为Avro Maven plugin会自动给你编译好。
生成好了一个User.java类,用avro将它序列化存放到本地文件中,最后再将其反序列化。
package com.learn.Serialization.UseCode;import org.apache.avro.file.DataFileReader;import org.apache.avro.file.DataFileWriter;import org.apache.avro.io.DatumReader;import org.apache.avro.io.DatumWriter;import org.apache.avro.specific.SpecificDatumReader;import org.apache.avro.specific.SpecificDatumWriter;import java.io.File;import java.io.IOException;public class UserTestApp { public static void main(String[] args) { // 3种生成user对象的方法 User user1 = new User(); user1.setName("张山"); user1.setAge(23); user1.setPhone("123456789"); User user2 = new User("李斯", 45, "987654321"); User user3 = User.newBuilder().setName("王二").setAge(57).setPhone("456893256").build(); // 序列化user到文件中 String path = "./avro/src/main/java/com/learn/Serialization/UseCode/output/users.avro"; File file = new File(path); DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class); DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter); try { dataFileWriter.create(user1.getSchema(), new File(path)); dataFileWriter.append(user1); dataFileWriter.append(user2); dataFileWriter.append(user3); dataFileWriter.flush(); dataFileWriter.close(); } catch (IOException e) { } // 从文件中反序列化对象 DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class); DataFileReader<User> dataFileReader = null; try { dataFileReader = new DataFileReader<User>(file, userDatumReader); } catch (IOException e) { } User user = null; try { while (dataFileReader.hasNext()) { user = dataFileReader.next(user); System.out.println(user); } } catch (IOException e) { } }}//==输出// {"name": "张山", "age": 23, "phone": "123456789"}// {"name": "李斯", "age": 45, "phone": "987654321"}// {"name": "王二", "age": 57, "phone": "456893256"}
三、直接代码生成模式
除了先用tools生成目标类(User),还可以直接读取schema
package com.learn.Serialization.DirectNoCode;import org.apache.avro.Schema;import org.apache.avro.file.DataFileReader;import org.apache.avro.file.DataFileWriter;import org.apache.avro.generic.GenericData;import org.apache.avro.generic.GenericDatumReader;import org.apache.avro.generic.GenericDatumWriter;import org.apache.avro.generic.GenericRecord;import org.apache.avro.io.DatumReader;import org.apache.avro.io.DatumWriter;import java.io.File;import java.io.IOException;public class DirectUserTest { public static void main(String[] args) throws IOException { String path = "./avro/src/main/java/com/learn/Serialization/avrotools/user.avsc"; //Parser 读取我们的 schema 定义并创建一个 Schema 对象 Schema schema = new Schema.Parser().parse(new File(path)); //使用该 schema ,我们来创建一些 Users GenericRecord user1 = new GenericData.Record(schema); user1.put("name", "Alyssa"); user1.put("age", 10); //孩子太小没有电话 GenericRecord user2 = new GenericData.Record(schema); user2.put("name", "Ben"); user2.put("age", 20); user2.put("phone", "18301103342"); // Serialize user1 and user2 to disk File file = new File("./avro/src/main/java/com/learn/Serialization/DirectNoCode/output/users.avro"); DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema); DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter); dataFileWriter.create(schema, file); dataFileWriter.append(user1); dataFileWriter.append(user2); dataFileWriter.close(); // Deserialize users from disk DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema); DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, datumReader); GenericRecord user = null; while (dataFileReader.hasNext()) { // Reuse user object by passing it to next(). This saves us from // allocating and garbage collecting many objects for files with // many items. user = dataFileReader.next(user); System.out.println(user); } }}//输出//{"name": "Alyssa", "age": 10, "phone": null}//{"name": "Ben", "age": 20, "phone": "18301103342"}代码结构:
pox依赖
<dependencies> <dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.8.2</version> </dependency> </dependencies>
阅读全文
0 0
- Apache Avro-[1]-序列化
- 使用 avro-tools, jq 查看 Apache Avro 序列化文件
- Apache Avro 序列化与反序列化 (Java 实现)
- Avro数据序列化
- Avro 序列化
- Avro JSON 序列化
- 5.2 Avro序列化
- Avro总结(RPC/序列化)
- Avro总结(RPC/序列化)
- Avro总结(RPC/序列化)
- Avro总结(RPC/序列化)
- avro序列化与RPC
- Avro总结(RPC/序列化)
- Avro入门1–序列化与远程通信
- Apache Avro
- Apache Avro
- Avro序列化/反序列化
- Avro序列化与反序列化
- YII2.0引用CSS,JS文件样式与Url跳转
- 以太坊开发文档05
- #define中#和##以及 #@的作用
- vue 插入视频
- WPF图片预览之移动、旋转、缩放
- Apache Avro-[1]-序列化
- Protege使用教程(进阶篇)
- unity接安卓sdk出现打不开应用,提示硬件不支持
- Makefile常用函数总结
- ionic_content——左右滑动(如地图)
- 基于Dragonboard 410c进行开发的远程遥控机器人(二)
- npm 安装卸载指定版本ng-zorro-antd
- 文章标题
- SQLServer只赋予创建表权限