一、概述
Apache Avro不仅仅是一个数据序列化协议,更提供一个良好定义的IPC消息协议,同时提供更高级别的RPC封装,使得基于Apache Avro的RPC调用变得更快捷。
Apache Avro 提供了三种不同的文件格式分别用来定义数据序列化协议(Schema ),接口协议(Protocol ),接口定义语言(IDL)分别以.avsc,.avpr,.avdl作为文件标识。
二、maven引入
<dependencies>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-ipc</artifactId>
<version>1.11.0</version>
</dependency>
</dependencies>
三、编写 avsc 文件和 avdl 文件
在src/main下新建目录avro,avro目录下新建文件user.avsc
{
"namespace": "com.example.avro", // 相当于声明一个包
"type": "record", // 相当于Java中的class
"name": "User", // 类名
"fields": [
{"name": "name", "type": "string"},
{"name": "age", "type": "int"},
{"name": "address", "type": ["string", "null"]}
]
}
avro目录下新建文件 userprotocol.avdl
@namespace("com.example.protocol")
protocol UserProtocol {
import schema "user.avsc";
string hello(com.example.avro.User user);
}
四、avro-tools编译
1.编译 avsc 文件
下载avro-tools.jar,使用avro-tools.jar编译avsc文件,
编译到java目录下
java -jar avro-tools-1.11.0.jar compile schema src/main/avro/user.avsc src/main/java
src/main/avro/user.avsc 源目录;src/main/java目标目录
2.编译 avdl 文件
avdl文件转化为avpr文件
java -jar avro-tools-1.11.0.jar idl src/main/avro/userprotocol.avdl src/main/avro/userprotocol.avpr
生成 userprotocol.avpr
{
"protocol" : "UserProtocol",
"namespace" : "com.example.protocol",
"types" : [ {
"type" : "record",
"name" : "User",
"namespace" : "com.example.avro",
"fields" : [ {
"name" : "name",
"type" : "string"
}, {
"name" : "age",
"type" : "int"
}, {
"name" : "address",
"type" : [ "string", "null" ]
} ]
} ],
"messages" : {
"hello" : {
"request" : [ {
"name" : "user",
"type" : "com.example.avro.User"
} ],
"response" : "string"
}
}
}
3.编译 avpr 文件
编译到java目录下
java -jar avro-tools-1.11.0.jar compile protocol src/main/avro/userprotocol.avpr src/main/java
五、使用maven插件编译
<dependencies>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-ipc</artifactId>
<version>1.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.11.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
<goal>idl-protocol</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>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
六、使用
会在 java目录下生成 User.java 和 UserProtocol.java 文件
1.接口实现
public class UserProtocolImpl implements UserProtocol {
@Override
public CharSequence hello(User user) {
return "hello, " + user.getName();
}
}
2. server
public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
Responder responder = new SpecificResponder(UserProtocol.class,new UserProtocolImpl());
SaslSocketServer server = new SaslSocketServer(responder,new InetSocketAddress(9999));
server.setDaemon(false);
server.start();
}
}
3. client
public class Client {
public static void main(String[] args) throws IOException {
SaslSocketTransceiver transceiver = new SaslSocketTransceiver(new InetSocketAddress(9999));
UserProtocol client = SpecificRequestor.getClient(UserProtocol.class, transceiver);
User user = new User();
user.setName("zhang san");
CharSequence msg = client.hello(user);
System.out.println(msg);
}
}
对于server的client的实现有如下几种
- 基于jetty的http实现:HttpServer 和HttpTransceiver
- 基于netty的实现:NettyServer和NettyTransceiver
- 基于TCP的实现:SocketServer和SocketTransceiver
- 基于UDP的实现:DatagramServer和DatagramTransceiver
- 基于加密的TCP实现:SaslSocketServer和SaslSocketTransceiver