博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多语言跨平台远程过程调用【Avro】
阅读量:5889 次
发布时间:2019-06-19

本文共 4731 字,大约阅读时间需要 15 分钟。

hot3.png

##开始

Avro是Apache的Hadoop家族的项目之一。具有性能高、基本代码少和产出数据量精简等特点。不过这是他们宣传广告,我最近也分别研究了Avro和Protobuf。基本的测试代码,不吐不快。

##安装

###Java

Avro是应运Hadoop而生的,因此主要也是以Java写就。 Java的安装比较简单,往项目中放入Avro及Avro-rpc的jar包便可。我喜欢使用Maven,因此Maven坐标如下:

org.apache.avro
avro
1.7.2
org.apache.avro
avro-ipc
1.7.2

###Python

熟悉Python模块安装应该很简单。avro的Python模块可以在 [ Python][] 下载。下载<code>tar.gz</code>或者<code>zip</code>解压到硬盘任意目录。

打开终端,并用cd切换到avro解压的目录,执行:

python setup.py install

Ubuntu系统需要Root权限:

sudo python setup.py install

如果没有看到特殊的错误,一般都能顺利安装上。

##协议[Protocol]

Avro协议是以JSON结构性描述文本。协议定义了基本的通信的数据类型,名称。并且还包含可调用的方法等。如下我的示例是一个实现简单的HelloWord程序。

<pre class="prettyprint lang-javascript"> { "namespace":"avro", "doc":"This is a message.", "protocol":"messageProtocol", "name":"HelloWorld", "types":[ { "name":"nameMessage", "type":"record", "fields":[ {"name":"name", "type":"string"} ] } ], "messages":{ "sayHello":{ "doc":"say Hello to manbers", "request":[ { "name":"name", "type":"string" } ], "response":"nameMessage" } } } </pre>

我把它命名为helloward.json。之所以我命名为json后缀的文件是因为很多编辑器都能认识,并且还能格式化。<<Hadoop权威指南>>中命名为avro后缀的文件,这点在编辑器中支持不是很好。并且Avro协议是不论协议文件的,它只认内容。

上面的协议相当于我新定义了一种复杂数据类型,名字为nameMessage,并且包含一个属性name,类型为string。 用Java语言通俗的说,我新定义了一个Bean, 这个Bean中只有一个<code>String name</code>的属性。因此她也是包涵在types下面的,相当与新定义了数据类型。

record是复杂类型,也就是可以通过简单类型合成的组装类型。关于支持的简单数据类型见:

messages在协议中包含特殊的含义。相当于曝露给外部可以调用的接口。如上面的协议,相当与包含了sayHello的方法,方法入口参数为String name,返回值为一个自定义的类型nameMessage, 其实也是一个String类型的键值对。

##服务端[Java]

<pre class="prettyprint lang-java"> public class AvroHttpServer extends GenericResponder { private static Log log = LogFactory.getLog(AvroHttpServer.class); public AvroHttpServer(Protocol protocol) { super(protocol); } public Object respond(Message message, Object request) throws Exception { GenericRecord req = (GenericRecord) request; GenericRecord reMessage = null; if (message.getName().equals("sayHello")) { Object name = req.get("name"); // do something... //取得返回值的类型 reMessage = new GenericData.Record(super.getLocal().getType("nameMessage")); //直接构造回复 reMessage.put("name", "Hello, " + name.toString()); log.info(reMessage); } return reMessage; } public static void main(String[] args) throws Exception { int port = 8088; try { Server server = new HttpServer( new AvroHttpServer(Protocol.parse( new File("helloword.json"))), port); server.start(); server.join(); } catch (Exception e) { e.printStackTrace(); } } } </pre>

如上边的Java代码,Avro默认可以支持的Server有很多,如NettyServer,SocketServer等。目前为止我之发现了Avro Python客户端只支持的Http的方式的。

上面的代码能正常运行,并且运行后进程不会退出,一直等待客户端链接。

##客户端

###Java

我是Java程序员, 因此每个例子我都会用Java首先实现一遍。

<pre class="prettyprint lang-java"> private Protocol protocol; private GenericRequestor requestor = null; @Before public void setUp() throws Exception { protocol = Protocol.parse(new File("src/main/resources/helloword.json")); Transceiver t = new HttpTransceiver(new URL("http://localhost:8088")); requestor = new GenericRequestor(protocol, t); } @Test public void testSendMessage() throws Exception { GenericRecord requestData = new GenericData.Record(protocol.getType("nameMessage")); // initiate the request data requestData.put("name", "zhenqin"); System.out.println(requestData); Object result = requestor.request("sayHello", requestData); if (result instanceof GenericData.Record) { GenericData.Record record = (GenericData.Record) result; System.out.println(record.get("name")); } System.out.println(result); } </pre>

上面的是一个JUnit的测试用例,可以直接用来测试。

###Python

<pre class="prettyprint lang-python"> #!/usr/bin/env python #!encoding:utf-8 import json import avro.protocol as proto import avro.ipc as ipc import avro.io as avroio import avro.schema as schema __author__ = 'zhenqin' PROTOCOL = proto.parse(open("helloword.json", "r").read()) def testPro(): client = ipc.HTTPTransceiver("zhenqin-k45vm", 8088) requestor = ipc.Requestor(PROTOCOL, client) message = dict() message["name"] = "ZhenQin" v = requestor.request('sayHello', message) print("Result: " + str(v)) # cleanup client.close() if __name__ == '__main__': testPro() </pre>

Python如上边的代码,helloword.json是HelloWord的协议。运行无论是Java或者Python,都会成功的输出:

Result: {u'name': u'Hello, ZhenQin'}

上面提到,Python目前仅仅支持Http的方式调用,因为avro python只提供了一个HTTPTransceiver, 我查看HTTPTransceiver的代码, 都很简单,但是以我的Python造诣还不能够给写一个SocketTransceiver。我相信Python高人能轻易实现一个支持Socket通信的SocketTransceiver不是难事。

在说一遍,Python目前只有一个HTTPTransceiver实现, 因此服务端Java还必须使用HttpServer,它是一个嵌入的Jetty的Http服务器。

##写在后边的话

测试了Avro, 我怎么觉得它更像是以json的webservice呢? 开发是如此的罗嗦? 并且丝毫体现不了便捷。难道多语言跨平台的RPC调用真的有这么难麽?当然也有简单的方式是把服务端的Responder换成ReflectResponder就可以直接注册接口和实现类的对象,但是这样会失去对多语言的支持。

希望广大同行能给以指正。

Protobuf, Next。

转载于:https://my.oschina.net/zhzhenqin/blog/151040

你可能感兴趣的文章
步步为营 .NET 代码重构学习笔记 二、提炼方法(Extract Method)
查看>>
步步为营 C# 技术漫谈 七、事务处理(Transaction)
查看>>
AutoMapper在MVC中的运用03-字典集合、枚举映射,自定义解析器
查看>>
lodash用法系列(1),数组集合操作
查看>>
【Tomcat】Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析
查看>>
cxrichedit导入WORD
查看>>
ArcGIS模型构建器案例教程-批量修改工作空间所有要素类的空间参考
查看>>
用GibbsLDA做Topic Modeling
查看>>
linux驱动面试题目汇总
查看>>
csharp skype send message in winform
查看>>
jQuery plugin: Tablesorter 2.0
查看>>
csharp:datagridview enter Half Width and Full Width characters
查看>>
MMORPG 游戏服务器端设计--转载
查看>>
C#实现无标题栏窗体点击任务栏图标正常最小化或还原的解决方法
查看>>
[转]GetLastInputInfo计时用户离开电脑及软件在指定时间锁定等
查看>>
Windows 操作系统与 .NET Framework
查看>>
Box2dの自定义多边形
查看>>
HDU 1425 ( sort )
查看>>
Windows Phone 7 框架和页面
查看>>
Directx11教程(31) 纹理映射(1)
查看>>