热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

高性能RPCoverMINAgoogleprotobuf代码实例(一)

2019独角兽企业重金招聘Python工程师标准作者的其他文章还不错!原文:http:maoyidao.iteye.comblog1636923最近团队在开发基

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

作者的其他文章还不错 !

原文: 

http://maoyidao.iteye.com/blog/1636923


最近团队在开发基于移动互联网的项目&#xff0c;又一次涉及到post service&#xff0c;即在服务器集群之间投递消息。是的&#xff0c;又是一个RPC服务。RPC实现方式从笨重的CORBA&#xff0c;SOAP over HTTP&#xff0c;XMPP over TCP&#xff0c;到轻量级的protobuf&#xff0c;scribe和Avro。这里不想比较各自的应用场景&#xff08;另外后面三种RPC方式极为接近&#xff0c;都是通过提供Object <-> 二进制映射来提高高效的传输&#xff09;&#xff0c;本文的目的是给大家一点可以实际操作的代码&#xff1a;java如何用protobuf 实现rpc

 

和protobuf-socket-rpc的区别

protobuf-socket-rpc&#xff08;code.google.com/p/protobuf-socket-rpc/&#xff09;是googlecode为rpc写的简单实现。本文介绍的代码和googlecode不同之处在于&#xff1a;

1&#xff0c;基于NIO

2&#xff0c;增加了校验码

高性能RPC over google protobuf

 

Google&#39;s protocol buffer library makes writing rpc services easy, but it does not contain a rpc implementation. The transport details are left up to the user to implement.

google把这问题留给了我们&#xff0c;那么看看应该怎么实现。hellow world伪代码应该是这样的&#xff1a;

 

Java代码   收藏代码
  1. MessageLite message &#61; getMessage(); // get a proto message object by proto file  
  2.   
  3. OutputStream out &#61; getOutputStream();  
  4. InputStream in &#61; getInputStream();  
  5. message.writeDelimitedTo(out); //  Like writeTo(OutputStream), but writes the size of the message as a varint before writing the data  
  6. messageBuilder.mergeDelimitedFrom(in);  
 

好了&#xff0c;这样就实现了序列化和反序列化。在真正的内容之前加入内容长度&#xff0c;这是一种最简单的实现。为了能可靠的进行传输&#xff0c;我在消息长度前加入了2个byte的验证码&#xff0c;下面就开始逐步构建我的rpc代码。

 

定义你的proto文件&#xff0c;为传输多种消息&#xff0c;需要有“命令”字段&#xff1a;比如&#xff1a;Maoyidao.proto

List 1&#xff1a;

 

Java代码   收藏代码
  1. package com.maoyidao.rpc;  
  2.   
  3. message MaoyidaoPacket {  
  4.   required int32 cmd &#61; 1;           
  5.   required int32 subcmd &#61; 2;     
  6.   optional bytes content &#61; 3;        
  7. }  

 

 

OK&#xff0c;compile it to Java class: protoc -I&#61;$SRC_DIR --java_out&#61;$DST_DIR $SRC_DIR/addressbook.proto

你会得到一个MaoyidaoPacket 类&#xff0c;然后你需要这样获得实例&#xff1a;

List 2&#xff1a;

 

Java代码   收藏代码
  1. Maoyidao.MaoyidaoPacket packet &#61; Maoyidao.MaoyidaoPacket.newBuilder()  
  2.    .setCmd(mycmd)  
  3.    .setSubcmd(mysubcmd)  
  4.    .setContent(ByteString.copyFromUtf8("some message")).build();   

 

 

我们先不讨论怎么基于MINA创建一个NIO&#xff0c;先假设我们获得了一个OutputStream&#xff0c;看看怎么把消息写出去&#xff08;其中的关键是用一些特殊的字符来区分你的消息&#xff0c;这是RPC over TCP的基本要求&#xff09;&#xff1a;

List 3&#xff1a;

 

Java代码   收藏代码
  1. private final void writeObject(OutputStream os, Maoyidao.MaoyidaoPacket packet)  {        
  2.         ByteArrayOutputStream baos &#61; new ByteArrayOutputStream();  
  3.         com.google.protobuf.CodedOutputStream cos &#61; com.google.protobuf.CodedOutputStream.newInstance(baos);      
  4.         cos.writeRawVarint32(3);  
  5.         cos.writeRawVarint32(7);  
  6.         cos.writeRawVarint32(packet.getSerializedSize());  
  7.         vpacket.writeTo(cos);  
  8.         cos.flush();          
  9.         os.write(baos.toByteArray());                 
  10.             baos.close();  
  11.     }  
  12. }  

 

注意我不仅写了分隔符&#xff0c;还写了content长度。

 

读进来的时候要用相同的方式解析&#xff0c;假设我们得到了一个Bytebuffer&#xff0c;熟悉NIO的同学知道&#xff0c;你总是会从ByteBuffer中读取数据。同时我需要用到com.google.protobuf.CodedInputStream&#xff1a;Reads and decodes protocol message fields. This class contains two kinds of methods: methods that read specific protocol message constructs and field types (e.g. readTag() and readInt32()) and methods that read low-level values (e.g. readRawVarint32() and readRawBytes(int)).&#xff09;这样我就可以从inputstream中读到校验码&#xff1a;

 

 

Java代码   收藏代码
  1. ByteBuffer in &#61; getByteBuffer();  
  2. CodedInputStream cis &#61; CodedInputStream.newInstance(in);  
  3.   
  4. int flag1 &#61; cis.readRawVarint32();  
  5. int flag2 &#61; cis.readRawVarint32();  
  6. if(flag1 !&#61; 3 || flag2 !&#61; 7){  
  7.     // find some error  
  8. }  
  9.   
  10. int contentLength &#61; cis.readRawVarint32();  
  11. int contentLength0 &#61; contentLength &#43; CodedOutputStream.computeRawVarint32Size(contentLength);  
  12.   
  13. if(in.remaining() >&#61; contentLength0){              
  14.     try {  
  15.         Maoyidao.MaoyidaoPacket.Builder builder &#61; Maoyidao.MaoyidaoPacket.newBuilder();  
  16.         CodedInputStream.newInstance(getBytesFromIn(in,contentLength0)).readMessage(  
  17.             builder, ExtensionRegistry.getEmptyRegistry());               
  18.         out.write(builder.build());  
  19.         in.position(in.position() &#43; protocolLength);  
  20.         return true;  
  21.     } catch (Exception e) {  
  22.         //   
  23.     }             
  24. }  
  25.   
  26. // ByteBuffer没有足够的数据&#xff0c;等待下一次  
  27. // do something  
 

截止目前&#xff0c;我们完成了带校验码的基于protobuf的消息序列化和反序列。在这个实现中&#xff0c;我更偏向把protobuf当做一个序列化工具来使用&#xff0c;整体还是依赖MINA本身提供的架构&#xff0c;这部分将在本系列的下一篇中详细阐述。

 

 

本文系maoyidao原创&#xff0c;转载请引用原链接&#xff1a;

http://maoyidao.iteye.com/blog/1636923


转:https://my.oschina.net/u/257088/blog/195953



推荐阅读
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Kryo的语法与java序列化相似.创建kryo对象以及输出输入,并使用kryos方法之一来执行序列化反序列化kryo.writeClassAndObject(output,ob ... [详细]
  • PNG在IE6下透明问题的解决办法
    2019独角兽企业重金招聘Python工程师标准做Web开发的朋友一定都知道PNG是一个相当不错的图片格式,但是这个好的格式却在IE6时代造成了麻烦࿰ ... [详细]
  • 1、创建高级对象使用构造函数来创建对象构造函数是一个函数,调用它来例示并初始化特殊类型的对象。可以使用new关键字来调用一个构造函数。下面给出了使用构造函数的新示例。 ... [详细]
  • linux js文件怎么打开文件夹路径,js 获取文件本地路径
    1.代码获取文件本地路径选择导入数据源:functionbrowseFolder(){try{varMessage“\u8bf7\u9009\u62e9\u6587\u4ef6\u ... [详细]
  • 为什么80%的码农都做不了架构师?#0系列目录#聊聊远程通信Java远程通讯技术及原理分析聊聊Socket、TCPIP、HTTP、FTP及网 ... [详细]
  • Java学习日志(241网络编程自定义服务端与客户端)
    为什么80%的码农都做不了架构师?自定义服务端*演示客户端与服务端客户端:浏览器服务端:自定义*importjava.net.*;importjava ... [详细]
  • log4cpp概述与使用实例一、log4cpp概述Log4cpp是一个开源的C类库,它提供了C程序中使用日志和跟踪调试的功能,它的优点如下࿱ ... [详细]
  • *变量的赋值变量是基本数据类型时:此时赋值的是变量所保存的数据值变量是引用数据类型时:此时赋值的是变量所保存的数据的地址值方法中参数的传递机制方法必须 ... [详细]
  • MyBatis缓存分为一级缓存和二级缓存一级缓存在SqlSession上二级缓存在SqlSessionFactory上如何配置一级缓存??默认开启&#x ... [详细]
  • Java反序列化漏洞(ysoserial工具使用、shiro反序列化利用)
    Java反序列化机制Java通过writeObject序列化将对象保存为二进制数据流,通过readObject反序列化将序列化后的二进制重新反序列化为Java对象& ... [详细]
  • php实现中文文件下载
    php教程|PHP源码php实现中文文件下载php教程-PHP源码php代码爱之谷2015源码,ubuntu16桌面,tomcat9解压缩半,python爬虫带页面,php批量删除 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
author-avatar
孤独丶Angle_251
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有