Avro远程RPC的实现

标签: Avro 分类: Java 创建时间:2019-10-14 07:51:35 更新时间:2024-11-15 10:49:42

RPC我还是第一次使用,而且Avro更是第一次学习。

1.编写Schema文件

新建user.avsc文件,内容如下,这里的namespace就是生成代码后的类的包路径:

1
2
3
4
5
6
7
8
9
{"namespace": "com.example",
"type": "record",
"name": "User",
"fields": [
{"name": "name", "type": "string"},
{"name": "favorite_number", "type": ["int", "null"]},
{"name": "favorite_color", "type": ["string", "null"]}
]
}

2.编写avdl文件,生成接口

新建avdl接口说明文件,内容如下,这里的namespace就是生成代码后的类的包路径:

1
2
3
4
5
6
7
8
9
10
@namespace("com.example.protocol")
protocol HelloProtocol {
import schema "user.avsc";
record Message {
string id;
string msg;
}
string hello(com.example.User user);
}

3.下载avro-tools-1.9.1.jar和avro-1.9.1.jar

管网下载,就不说了。

4.命令行执行生成rpc调用方法和序列化类

先执行idl命令,根据avdl文件生成json文件,然后执行compile protocol,生成接口文件。

1
2
3
4
## 1.生成协议的json文件
java -jar .\avro-tools-1.9.1.jar idl .\helloprotocol.avdl .\helloprotocol.json
## 2.自动生成接口类
java -jar .\avro-tools-1.9.1.jar compile protocol .\helloprotocol.json .

avro_tool工具将自动生成类文件夹:

文件夹中包括了序列化和反序列的User类:

以及供远程调用的远程接口及远程方法:

注意
执行protocol命令时,最后的点,是表示在当前目录下生成类和方法,否则会出现错误:

参考文章:
1.关于avro的编译 关于如何自动生成代码协议代码的说明
2.avro-tools将avdl转换为avsc不会生成正确的avsc

5.新建maven工程avro-rpc的服务端

在maven的pom.xml文件中添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>AvroRPCServer</artifactId>
<version>1.0-SNAPSHOT</version>

<name>AvroRPCServer</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<!-- 添加avro支持 -->
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.9.1</version>
</dependency>
<!-- 添加avro的rpc支持 -->
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-ipc</artifactId>
<version>1.9.1</version>
</dependency>
<!-- 添加avro的rpc netty服务器支持 -->
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-ipc-netty</artifactId>
<version>1.9.1</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.9.1</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.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

注意添加ipc支持,否则idea会报错:

6.实现协议接口

将第四章生成的HelloProtocol.java接口以及数据类User.java复制到工程目录中(注意你的类中包的名字)。然后新建类HelloService,并实现HelloProtocol接口,这里的user.getName()等方法根据自己写的属性进行替换,接口方法也需要适当的调整。

1
2
3
4
5
6
7
8
9
10

import org.apache.avro.AvroRemoteException;

public class HelloService implements HelloProtocol {
@Override
public CharSequence hello(User user) {
System.out.println(user.getName() + "," + user.getFavoriteNumber() + "," + user.getFavoriteColor());
return "hai i`m from avro service";
}
}

7.发布服务

实现了HelloService,就可以在主程序中发布服务了,监听了端口号65111。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import org.apache.avro.ipc.Responder;
import org.apache.avro.ipc.Server;
import org.apache.avro.ipc.netty.NettyServer;
import org.apache.avro.ipc.specific.SpecificResponder;

import java.net.InetSocketAddress;

/**
* Hello world!
*
*/
public class App
{
@SuppressWarnings("unused")
private static Server server;
public static void main( String[] args )
{
System.out.println( "Hello World!" );
//服务端协议
Responder responder=new SpecificResponder(HelloProtocol.class, new HelloService());
server=new NettyServer(responder, new InetSocketAddress(65111));
}
}

运行main程序,等待连接:

注意添加NettyServer的maven,否则报错:

8.新建RPC的客户端工程

新建AvroRPCClient的maven工程,pom.xml参考服务端。

9.复制类文件

同服务端一样,将avro-tool生成的User.java和HelloProtocol.java复制到工程目录中,注意包路径。

10.编写Main函数,调用远程接口

在main函数中,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.proheng;

import org.apache.avro.ipc.netty.NettyTransceiver;
import org.apache.avro.ipc.specific.SpecificRequestor;

import java.net.InetSocketAddress;

/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );

try{
NettyTransceiver client = new NettyTransceiver(new InetSocketAddress(65111));
HelloProtocol proxy = SpecificRequestor.getClient(HelloProtocol.class, client);
User user = new User();
user.setName("xiaofen");
user.setFavoriteNumber(1);
user.setFavoriteColor("dsf");
System.out.println(proxy.hello(user));
}catch (Exception e){
System.out.println(e);
}

}
}

运行客户端main,输出如下:

查看服务端输出:

测试成功!!!

小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。