Apache Avro RPC 实例

Avro的模式主要由JSON对象来表示,Avro支持8种基本类型(Primitive Type)和6种复杂类型(Complex Type:records、enums、arrays、maps、unions 和fixed),基本类型可以由JSON字符串来表示。

Avro支持两种序列化编码方式:二进制编码和JSON编码,使用二进制编码会高效序列化,并且序列化后得到的结果会比较小。

  基本类型:

  1. null: no value
  2. boolean: a binary value
  3. int: 32-bit signed integer
  4. long: 64-bit signed integer
  5. float: single precision (32-bit) IEEE 754 floating-point number
  6. double: double precision (64-bit) IEEE 754 floating-point number
  7. bytes: sequence of 8-bit unsigned bytes
  8. string: unicode character sequence
1.定义一个消息结构
{
    "namespace": "cn.slimsmart.avro.demo",
    "protocol": "messageProtocol",
    "doc": "This is a message.",
    "name": "Message",
    "types": [
        {"name":"message", "type":"record",
            "fields":[
                {"name":"name", "type":"string"},
                {"name":"type", "type":"int"},
                {"name":"price", "type":"double"},
                {"name":"valid", "type":"boolean"},
                {"name":"content", "type":"string"}
                ]
        }
    ],
    "messages":    {
        "sendMessage":{
            "doc" : "message test",
            "request" :[{"name":"message","type":"message" }],
            "response" :"message"
        }         
    }   
}
其中定义了1种类型叫做message,有5个成员name、type、price、valid、content。还定义了1个消息服务叫做sendMessage,输入有一个参数,类型是message,返回message。

2.序列化

  Avro有两种序列化编码:binary和JSON。

3.rpc通信实现

Avro的RPC实现不需要定义服务接口,但需要从.avpr文件中解析协议,协议中定义了消息结构和消息服务。message.avpr中定义了一个类型叫message,定义了一个服务叫sendMessage。

添加依赖jar:

<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro</artifactId>
			<version>1.7.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.avro</groupId>
			<artifactId>avro-ipc</artifactId>
			<version>1.7.7</version>
		</dependency>

1)协议解析工具类

Utils.java

package cn.slimsmart.avro.demo;

import java.io.File;
import java.io.IOException;
import java.net.URL;

import org.apache.avro.Protocol;

public class Utils {

	public static Protocol getProtocol() {
        Protocol protocol = null;
        try {
            URL url = Utils.class.getClassLoader().getResource("message.avpr");
            protocol = Protocol.parse(new File(url.getPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return protocol;
    }
}
2)服务端

package cn.slimsmart.avro.demo;

import org.apache.avro.Protocol;
import org.apache.avro.Protocol.Message;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.ipc.HttpServer;
import org.apache.avro.ipc.generic.GenericResponder;

public class Server extends GenericResponder {

	private Protocol protocol = null;
	private int port;

	public Server(Protocol protocol, int port) {
		super(protocol);
		this.protocol = protocol;
		this.port = port;
	}

	@Override
	public Object respond(Message message, Object request) throws Exception {
		GenericRecord req = (GenericRecord) request;
		GenericRecord reMessage = null;
		if (message.getName().equals("sendMessage")) {
			GenericRecord msg = (GenericRecord)req.get("message");
            System.out.print("接收到数据:");
            System.out.println(msg);
            //取得返回值的类型
            reMessage =  new GenericData.Record(protocol.getType("message")); 
            //直接构造回复
            reMessage.put("name", "苹果");
            reMessage.put("type", 100);
            reMessage.put("price", 4.6);
            reMessage.put("valid", true);
            reMessage.put("content", "最新上架货物");
        }
		return reMessage;
	}

	public void run() {
		try {
			HttpServer server = new HttpServer(this, port);
			server.start();
			server.join();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new Server(Utils.getProtocol(), 9090).run();
	}
}

3)客户端

package cn.slimsmart.avro.demo;

import java.net.URL;

import org.apache.avro.Protocol;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.ipc.HttpTransceiver;
import org.apache.avro.ipc.Transceiver;
import org.apache.avro.ipc.generic.GenericRequestor;

public class Client {

	private Protocol protocol = null;
	private String host = null;
	private int port = 0;
	private int count = 0;

	public Client(Protocol protocol, String host, int port, int count) {
		this.protocol = protocol;
		this.host = host;
		this.port = port;
		this.count = count;
	}

	public long sendMessage() throws Exception {
		GenericRecord requestData = new GenericData.Record(protocol.getType("message"));
		requestData.put("name", "香梨");
		requestData.put("type", 36);
		requestData.put("price", 5.6);
		requestData.put("valid", true);
		requestData.put("content", "价钱便宜");
		
		// 初始化请求数据
		GenericRecord request = new GenericData.Record(protocol.getMessages().get("sendMessage").getRequest());
		request.put("message", requestData);

		Transceiver t = new HttpTransceiver(new URL("http://" + host + ":" + port));
		GenericRequestor requestor = new GenericRequestor(protocol, t);
		
		long start = System.currentTimeMillis();
		for (int i = 0; i < count; i++) {
			  Object result = requestor.request("sendMessage", request);
			  if (result instanceof GenericData.Record) {
				  GenericData.Record record = (GenericData.Record) result;
				  System.out.println(record);
			  }
		}
		long end = System.currentTimeMillis();
		System.out.println((end - start)+"ms");
		return end - start;
	}

	public long run() {
		long res = 0;
		try {
			res = sendMessage();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}

	public static void main(String[] args) throws Exception {
		new Client(Utils.getProtocol(), "127.0.0.1", 9090, 5).run();
	}
}
Avro IPC提供了如下几种服务端和客户端实现:

1.基于jetty的http实现

HttpServer 和HttpTransceiver

2.基于netty的实现

NettyServer和NettyTransceiver

3.基于TCP的实现

SocketServer和SocketTransceiver

4.基于UDP的实现

DatagramServer和DatagramTransceiver

5.基于加密的TCP实现

SaslSocketServer和SaslSocketTransceiver

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Apache Avro是一个数据序列化系统,旨在支持快速、节省空间的数据交换和远程过程调用。它使用JSON格式定义数据结构,并支持动态类型,使其易于在不同编程语言之间进行交互。 使用Avro的步骤如下: 1. 定义数据结构:使用Avro的JSON格式定义数据结构,包括字段名、类型和默认值等信息。 例如,定义一个Person对象: ``` { "namespace": "example.avro", "type": "record", "name": "Person", "fields": [ {"name": "name", "type": "string"}, {"name": "age", "type": "int"} ] } ``` 2. 生成代码:使用Avro工具生成指定语言的代码,包括数据结构类和序列化/反序列化类等。 例如,使用Avro工具生成Java代码: ``` $ java -jar avro-tools-1.9.2.jar compile schema person.avsc . ``` 3. 序列化数据:使用生成的代码将数据序列化为字节数组。 例如,使用Java代码创建Person对象并序列化: ``` Person person = new Person("Alice", 30); ByteArrayOutputStream out = new ByteArrayOutputStream(); DatumWriter<Person> writer = new SpecificDatumWriter<Person>(Person.class); Encoder encoder = EncoderFactory.get().binaryEncoder(out, null); writer.write(person, encoder); encoder.flush(); byte[] bytes = out.toByteArray(); ``` 4. 反序列化数据:使用生成的代码将字节数组反序列化为数据对象。 例如,使用Java代码反序列化字节数组: ``` ByteArrayInputStream in = new ByteArrayInputStream(bytes); DatumReader<Person> reader = new SpecificDatumReader<Person>(Person.class); Decoder decoder = DecoderFactory.get().binaryDecoder(in, null); Person person2 = reader.read(null, decoder); ``` 这样,就完成了数据的序列化和反序列化。 以下是一个完整的Java代码示例: ``` import org.apache.avro.Schema; import org.apache.avro.Schema.Parser; import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericRecord; import org.apache.avro.io.DatumReader; import org.apache.avro.io.DatumWriter; import org.apache.avro.io.Decoder; import org.apache.avro.io.DecoderFactory; import org.apache.avro.io.Encoder; import org.apache.avro.io.EncoderFactory; import org.apache.avro.specific.SpecificDatumReader; import org.apache.avro.specific.SpecificDatumWriter; import org.apache.avro.specific.SpecificRecord; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class AvroExample { public static void main(String[] args) throws IOException { // Define schema String schemaJson = "{\n" + " \"namespace\": \"example.avro\",\n" + " \"type\": \"record\",\n" + " \"name\": \"Person\",\n" + " \"fields\": [\n" + " {\"name\": \"name\", \"type\": \"string\"},\n" + " {\"name\": \"age\", \"type\": \"int\"}\n" + " ]\n" + "}"; Schema schema = new Parser().parse(schemaJson); // Serialize data Person person = new Person("Alice", 30); ByteArrayOutputStream out = new ByteArrayOutputStream(); DatumWriter<Person> writer = new SpecificDatumWriter<Person>(Person.class); Encoder encoder = EncoderFactory.get().binaryEncoder(out, null); writer.write(person, encoder); encoder.flush(); byte[] bytes = out.toByteArray(); // Deserialize data ByteArrayInputStream in = new ByteArrayInputStream(bytes); DatumReader<Person> reader = new SpecificDatumReader<Person>(Person.class); Decoder decoder = DecoderFactory.get().binaryDecoder(in, null); Person person2 = reader.read(null, decoder); System.out.println(person2.getName()); // Alice System.out.println(person2.getAge()); // 30 } public static class Person implements SpecificRecord { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } @Override public void put(int i, Object o) { } @Override public Object get(int i) { if (i == 0) { return name; } else if (i == 1) { return age; } return null; } @Override public Schema getSchema() { return null; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值