目录

概述

序列化

RPC


概述

1.AVRO是Apache提供的开源框架,可以完成序列化以及RPC过程

2.原来是Apache Hadoop项目的子项目,后来不止可以用于Hadoop,也可以用于其他框架中进行序列化以及RPC,所以单立出来成为了Apache的顶级项目

3.AVRO在序列化数据的时候是以字符串形式体现,以json形式来作为约束

4.RPC用于完成数据的通信,使得前端人员在使用的时候看起来好像和后端一样

序列化

1.序列化的目的是完成数据的传输和交换

2.序列化的衡量标准:

对CPU的占用率多少以及序列化的时间长短

序列化之后产生的数据量越小越好

序列化之后的数据是否能跨平台跨语言(android(java/colin)和IOS(ObjectiveC/swift) 游戏底层用C)传输 - 核心思想是将对象转化为与语言无关的数据(字符串)

3.Avro在序列化的时候考虑使用的是字符串形式,也就意味着Avro将对象转化为字符串,然后在不同语言之间传输

4.创建AVRO项目:

4.1pom文件:

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<compiler-plugin.version>2.3.2</compiler-plugin.version>
	<avro.version>1.7.5</avro.version>
</properties>
<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-simple</artifactId>
		<version>1.6.4</version>
		<scope>compile</scope>
	</dependency>
	<dependency>
		<groupId>org.apache.avro</groupId>
		<artifactId>avro</artifactId>
		<version>1.7.5</version>
	</dependency>
	<dependency>
		<groupId>org.apache.avro</groupId>
		<artifactId>avro-ipc</artifactId>
		<version>1.7.5</version>
	</dependency>
</dependencies>
<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>${compiler-plugin.version}</version>
		</plugin>
		<plugin>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro-maven-plugin</artifactId>
			<version>1.7.5</version>
			<executions>
				<execution>
					<id>schemas</id>
					<phase>generate-sources</phase>
					<goals>
						<goal>schema</goal>
						<goal>protocol</goal>
						<goal>idl-protocol</goal>
					</goals>
					<configuration>
						<!-- 存放asdv文件的目录 -->
						<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
						<!-- 产生的java文件的存放目录 -->
						<outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
					</configuration>
				</execution>

			</executions>
		</plugin>
	</plugins>
</build>

4.2.新建文件夹:src\main\avro  新建文件:Person.avsc

{
    "namespace":"avro.pojo", // 表示包名
    "type":"record", // 声明类
    "name":"Person", // 类名
    "fields":
    [
        {"name":"name","type":"string"}, // 声明了一个属性String name
        {"name":"age","type":"int"},
        {"name":"gender","type":"boolean"}
    ]
}

pom文件右击  runAs 选择第四个Maven generate-resources 产生源码——success,成功可以在/src/main/avro/目录下发现产生了一个类,

public class PersonTest {

	// 创建对象
	@Test
	public void test() {
		// 方式一:利用无参构造创建
		Person p1 = new Person();
		p1.setName("Amy");
		p1.setAge(15);
		p1.setGender(false);
		System.out.println(p1);
		// 方式二:利用含参构造创建
		Person p2 = new Person("Sam", 18, true);
		System.out.println(p2);
		// 方式三:利用建造者模式创建
		Person p3 = Person.newBuilder(p1).setAge(17).build();
		System.out.println(p3);
	}

	// 序列化
	@Test
	public void serial() throws IOException {

		// 创建对象
		Person p1 = new Person();
		p1.setName("Amy");
		p1.setAge(15);
		p1.setGender(false);
		Person p2 = new Person("Sam", 18, true);

		// 创建序列化流
		DatumWriter<Person> dw = new SpecificDatumWriter<>(Person.class);
		// 表示利用这个流将序列化的数据写到文件中,泛型<Person>:要序列化的东西
		DataFileWriter<Person> df = new DataFileWriter<>(dw);
		// 指定写出的文件,SCHEMA:表示按照person的约束,数据写在a.txt
		df.create(Person.SCHEMA$, new File("a.txt"));
		// 序列化对象,有几个对象,append几次
		df.append(p1);
		df.append(p2);
		// 关流
		df.close();
	}

	// 反序列化
	@Test
	public void deSerial() throws IOException {

		// 创建反序列化流
		DatumReader<Person> dr = new SpecificDatumReader<>(Person.class);
		// 从文件中读取数据
		DataFileReader<Person> df = new DataFileReader<>(new File("a.txt"), dr);
		// 将DataFileReader读取数据的方法进行包装成迭代器, 提供了迭代遍历的方式
		while (df.hasNext()) {
			System.out.println(df.next());
		}
		// 关流
		df.close();
	}
}

RPC

1.RPC 的全称是 Remote Procedure Call(远程过程调用)是一种进程间通信方式

2.RPC设计的目的在于可以让调用者可以像以本地调用方式一样调用远程服务,具体实现的方式是调用接口的方式来调用

3.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。 即程序员无论是调用本地的还是远程的,本质上编写的调用代码基本相同

原因:

A,B两台服务器要进行数据通信,A服务器要进行数据接收,数据解析,数据封包发送B服务器,B服务器收到A服务的包后,需要解码,接收数据,解析,计算结果并封包发送,传回A服务器,这样大部分都浪费在了数据的包装,解析,而真正的业务是计算数据,所以我们可以用RPC把数据的包装解析等过程完成,使A,B两服务器实现同一接口可以保证两边服务器方法一样,这个接口也叫做stub存根,这样整体上我访问的是A服务器,B服务器以及RPC对外来访问者是不可见的,就好像我在本地访问,实际调用的是远程的服务器

 

代码实现客户端

pom文件::与Avro的序列化pom文件一致

模拟计算机做计算功能:做一个约束

新建文件夹:src\main\avro , 新建文件:Calc.avdl

@namespace("avro.service")
protocol CalcService {
    int add(int i, int j);
    double max(double i, double j);
}

pom文件右击  runAs 选择第四个Maven generate-resources 产生源码——success,成功可以在/src/main/avro/目录下发现产生了一个类,

public class ClientStart {
	
	public static void main(String[] args) throws IOException {
		
		// 启动Netty的客户端
		NettyTransceiver transceiver = new NettyTransceiver(new InetSocketAddress("localhost", 8090));
		// 利用SpecificRequestor给服务器发起请求,返回值代表指定的接口的代理对象,代理对象在底层进行数据的解析和传输
		CalcService proxy = SpecificRequestor.getClient(CalcService.class, transceiver);
		int result = proxy.add(3, 5);
		System.out.println(result);
	}
}

服务器端:与前端一致,将客户端的pom,约束文件Calc.avdl,copy过来

写生成类的实现类

public class CalcServiceImpl implements CalcService {

	@Override
	public int add(int i, int j) throws AvroRemoteException {
		return i + j;
	}

	@Override
	public double max(double i, double j) throws AvroRemoteException {
		return i > j ? i : j;
	}
}

启动类

public class ServerStart {
	
	@SuppressWarnings("unused")
	public static void main(String[] args) {
		
		// 开启服务器
		NettyServer server = new NettyServer(new SpecificResponder(CalcService.class, new CalcServiceImpl()), new InetSocketAddress(8090));
	}
}