Apache Avro-[2]-Rpc-Http和Netty两种方式

来源:互联网 发布:淘宝如何设置店铺分类 编辑:程序博客网 时间:2024/05/24 02:56

Avro的模式主要由JSON对象来表示,Avro支持8种基本类型(Primitive Type)和6种复杂类型(Complex Type:records、enums、arrays、maps、unions 和fixed),基本类型可以由JSON字符串来表示。
Avro支持两种序列化编码方式:二进制编码和JSON编码,使用二进制编码会高效序列化,并且序列化后得到的结果会比较小。
基本类型:
null: no value
boolean: a binary value
int: 32-bit signed integer
long: 64-bit signed integer
float: single precision (32-bit) IEEE 754 floating-point number
double: double precision (64-bit) IEEE 754 floating-point number
bytes: sequence of 8-bit unsigned bytes
string: unicode character sequence
参考:http://blog.csdn.net/zhu_tianwei/article/details/44042955,感谢分享

一、Http方式

1.定义一个消息结构
message.avpr
定义了1种类型叫做message,有5个成员name、type、price、valid、content。还定义了1个消息服务叫做sendMessage,输入有一个参数,类型是message,返回message
{    "namespace": "com.learn.PpcHttp",    "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"        }    }}

2.定义协议解析工具
/协议解析工具类//message.avpr//其中定义了1种类型叫做message,// 有5个成员name、type、price、valid、content。// 还定义了1个消息服务叫做sendMessage,输入有一个参数,类型是message,返回message。public class Utils {  public static Protocol getProtocol() {    Protocol protocol = null;    try {      URL url = Utils.class.getClassLoader().getResource("./RpcHttpRes/message.avpr");      protocol = Protocol.parse(new File(url.getPath()));    } catch (IOException e) {      e.printStackTrace();    }    return protocol;  }   public static void main(String[] args) {    Protocol protocol = getProtocol();    System.out.println(protocol);    //{"protocol":"messageProtocol","namespace":"com.learn.PpcHttp",    // "doc":"This is a message.","name":"Message",    // "types":[{"type":"record","name":"message",    // "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"}}}   }}
3.定义Client
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();  }}//{"name": "苹果", "type": 100, "price": 4.6, "valid": true, "content": "最新上架货物"}//{"name": "苹果", "type": 100, "price": 4.6, "valid": true, "content": "最新上架货物"}//{"name": "苹果", "type": 100, "price": 4.6, "valid": true, "content": "最新上架货物"}//{"name": "苹果", "type": 100, "price": 4.6, "valid": true, "content": "最新上架货物"}//{"name": "苹果", "type": 100, "price": 4.6, "valid": true, "content": "最新上架货物"}//377ms

4.定义Server
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(Protocol.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();  }}//  接收到数据:{"name": "香梨", "type": 36, "price": 5.6, "valid": true, "content": "价钱便宜"}//  接收到数据:{"name": "香梨", "type": 36, "price": 5.6, "valid": true, "content": "价钱便宜"}//  接收到数据:{"name": "香梨", "type": 36, "price": 5.6, "valid": true, "content": "价钱便宜"}//  接收到数据:{"name": "香梨", "type": 36, "price": 5.6, "valid": true, "content": "价钱便宜"}//  接收到数据:{"name": "香梨", "type": 36, "price": 5.6, "valid": true, "content": "价钱便宜"}

二、Netty方式+如何应用接口实现协议

参考:https://github.com/pzx888/avro-rpc-demo

Message.avsc,参考:http://blog.csdn.net/hjw199089/article/details/78801890,生成Message类

{    "name ": "Message ",    "namespace ": "com.learn.proto ",    "type ": "record "    "fields ": [        {            "name ": "to ",            "type ": "string "        },        {            "name ": "from ",            "type ": "string "        },        {            "name ": "body ",            "type ": "string "        }    ],}
定义Mail接口协议
@SuppressWarnings("all")@org.apache.avro.specific.AvroGeneratedpublic interface Mail {  public static final org.apache.avro.Protocol PROTOCOL = org.apache.avro.Protocol.parse("{\"protocol\":\"Mail\",\"namespace\":\"com.learn.proto\",\"types\":[{\"type\":\"record\",\"name\":\"Message\",\"fields\":[{\"name\":\"to\",\"type\":\"string\"},{\"name\":\"from\",\"type\":\"string\"},{\"name\":\"body\",\"type\":\"string\"}]}],\"messages\":{\"send\":{\"request\":[{\"name\":\"message\",\"type\":\"Message\"}],\"response\":\"string\"}}}");  CharSequence send(Message message) throws org.apache.avro.AvroRemoteException;   @SuppressWarnings("all")  public interface Callback extends Mail {    public static final org.apache.avro.Protocol PROTOCOL = Mail.PROTOCOL;    void send(Message message, org.apache.avro.ipc.Callback<CharSequence> callback) throws java.io.IOException;  }}

定义测试App,启动Server,启动Client
public class MailMain {    public static class MailImpl implements Mail {        // in this simple example just return details of the message        public Utf8 send(Message message) {            System.out.println("Sending message");            return new Utf8("Sending message to " + message.getTo().toString()                    + " from " + message.getFrom().toString()                    + " with body " + message.getBody().toString());        }    }    private static Server server;    private static void startServer() throws IOException {        server = new NettyServer(new SpecificResponder(Mail.class, new MailImpl()), new InetSocketAddress(65111));        // the server implements the Mail protocol (MailImpl)    }    public static void main(String[] args) throws IOException {        if (args.length != 3) {            System.out.println("Usage: <to> <from> <body>");            System.exit(1);        }        System.out.println("Starting server");        // usually this would be another app, but for simplicity        startServer();        System.out.println("Server started");        NettyTransceiver client = new NettyTransceiver(new InetSocketAddress(65111));        // client code - attach to the server and send a message        Mail proxy = (Mail) SpecificRequestor.getClient(Mail.class, client);        System.out.println("Client built, got proxy");        // fill in the Message record and send it        Message message = new Message();        message.setTo(new Utf8(args[0]));        message.setFrom(new Utf8(args[1]));        message.setBody(new Utf8(args[2]));        System.out.println("Calling proxy.send with message:  " + message.toString());        System.out.println("Result: " + proxy.send(message));        // cleanup        client.close();        server.close();    }}//设置运行参数  hjw_1  hjw_2  "this is message"//Server started//Client built, got proxy//Calling proxy.send with message:  {"to": "hjw_1", "from": "hjw_2", "body": "this is message"}//Sending message//Result: Sending message to hjw_1 from hjw_2 with body this is message