1.概述
- AVRO是Apache提供的一套用于进行序列化和RPC的框架
- AVRO原本是Hadoop的子工程之一,后来被独立出来成为了单独的顶级工程
2.AVRO创建对象的6种方式
1.创建maven工程,引入pom依赖
<dependencies>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13-rc-1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2.按照pom 文件的sourceDirectory配置的路径创建avro文件目录,在avro文件目录中创建配置类(用于自动生成pojo)
目录结构如图
配置文件中的代码
// 提供AVRO的格式文件
{
"namespace":"cn.wy.pojo", // 相当于声明一个包
"type":"record", // 相当于Java中的class
"name":"User", // 类名
"fields":
[
{"name":"name","type":"string"},
{"name":"age","type":"int"},
{"name":"gender","type":"string"},
{"name":"weight","type":"double"},
{"name":"height","type":"double"}
]
}
3.配置文件编写完毕,点击compile
4.执行compile完成后可看到生成的对应目录下的对应文件
5.创建对象的6种方式
代码示例如下(方式6,建造者模式,是在有相同类型属性及参数几乎相同的情况下(可以理解为双胞胎),复制出一份,给出不同的属性值即可):
@Test
public void create() {
// 方式一:先创建对象后赋值属性
User u1 = new User();
u1.setName("Bob");
u1.setAge(19);
u1.setGender("male");
u1.setHeight(185.2);
u1.setWeight(65.4);
System.out.println(u1);
// 方式二:在创建对象的时候给值
User u2 = new User("Grace", 22, "female",
49.5, 165.8);
System.out.println(u2);
// 方式三:适合于反射场景
User u3 = new User();
u3.put("name", "Helen");
u3.put("age", 17);
u3.put("gender", "female");
u3.put("height", 170.5);
u3.put("weight", 52.8);
System.out.println(u3);
// 方式四:适合于编号给值 - 是AVRO底层最常用的方式
User u4 = new User();
u4.put(0, "Mike");
u4.put(1, 19);
u4.put(2, "male");
u4.put(3, 70.4);
u4.put(4, 185.7);
System.out.println(u4);
// 方式五:建造者模式
User u5 = User.newBuilder()
.setName("Jack")
.setAge(18)
.setGender("male")
.setHeight(179.8)
.setWeight(58.9).build();
System.out.println(u5);
// 方式六:建造者模式
User u6 = User.newBuilder(u5)
.setName("John").build();
System.out.println(u6);
}
运行结果:
3.序列化与反序列化
1.序列化实际上就是将一个对象按照指定规则转化为指定的数据形式
2.序列化的目的/作用:存储和传输
3.序列化的衡量标准
- 对资源(内存和CPU)的占用
- 序列化之后产生的数据量
- 是否跨平台跨语言
数据在不同的语言直接传输,需要做到的是与语言无关:如字符串,数字,布尔值。
多种语言要应用在一个项目中可以通过这些语言实现:Shell、Python、Perl、Ruby等(可以这样理解,多种不同的语言程序可以认为是不同棱角的石块,儿Shell这些语言就像胶水一样将他们粘连在一起成为一个整体)
4.AVRO考虑到跨语言的问题,所以将数据转化为以json为基础的字符串形式
5.AVRO中不允许属性值为null
代码示例
// 序列化
@Test
public void serial() throws IOException {
// 创建对象
User u1 = new User("Henry", 19, "male", 64.5, 185.2);
User u2 = new User("Mark", 17, "male", 70.4, 183.6);
User u3 = new User("Lily", 18, "female", 50.2, 164.8);
// 创建序列化流
DatumWriter<User> dw = new SpecificDatumWriter<>(User.class);
// 创建文件流
DataFileWriter<User> dfw = new DataFileWriter<>(dw);
// 指定文件
// dfw.create(u1.getSchema(), new File("E:\\a.txt"));
// dfw.create(User.getClassSchema(), new File("E:\\a.txt"));
dfw.create(User.SCHEMA$, new File("E:\\a.txt"));
// 序列化对象
dfw.append(u1);
dfw.append(u2);
dfw.append(u3);
// 关流
dfw.close();
}
// 反序列化
@Test
public void deSerial() throws IOException {
// 创建反序列化流
DatumReader<User> dr = new SpecificDatumReader<>(User.class);
// 创建文件流
DataFileReader<User> dfr = new DataFileReader<>(
new File("E:\\a.txt"), dr);
// 反序列化 - 将反序列化过程设计成了迭代器模式
while (dfr.hasNext()) {
User u = dfr.next();
System.out.println(u);
}
// 关流
dfr.close();
}
运行结果:
1.序列化
已经生成的文件
文件中的内容,因为是以json为基础封装的数据,所以有部分无法看明白
2.反序列化
4.RPC
1.RPC(Remote Procedure Call,远程过程调用)指的是程序员在一台服务器上远程调用另一台服务器上的方法而不用显式的实现这个方法
2.RPC是Nelson提出的,RPC成了分布式的基础
3.RPC的特点:简洁、高效、易懂
4.在RPC中,stub(存根)用于保证节点之间的方法的一致性。在Java中,一般使用接口作为存根