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

Netty框架中运用Protobuf实现高效通信协议

在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。

Netty中使用protobuf

  1. 环境准备

下载protoc代码生成器和源码包:http://code.google.com/p/protobuf/downloads/list

  • protobuf-2.4.1.tar.bz2:主要是生成protobuf-2.4.1.jar,操作需要安装maven,可以到网上下载这个Jar包,所以这里略。
  • protoc-2.4.1-win32.zip:生成XXX.Proto执行文件。

     

    参考http://blog.csdn.net/dreamdoc/article/details/6577180相关代码

     

  1. 制作.Proto文件

格式参考如下:

注:可以按如上内容编写文本文件,然后修改后缀为.Proto。

  1. proto文件结构

从上面的代码可以看出,proto文件的结构非常简单。

  • package java_package 定义生成的java类的package名称。
  • message定义一种类型,类型以Java中的一个class,Book是类名,在生成Java代码时,就是使用这个类名。
  • option optimize_for = LITE_RUNTIME:表示生成的java代码继承GeneratedMessageLite ,继承GeneratedMessageLite的好处是可张念以用jboss提供的编解码器,可以认为是必写项。

 

  • 该类型中包含的字段格式: [限定符 类型 字段名称 = tag [default = 默认值]]

 

  1. 支持的默认类型

.proto Type

Notes

C++ Type

Java Type

double

 

double

double

float

 

float

float

int32

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.

int32

int

int64

Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.

int64

long

uint32

Uses variable-length encoding.

uint32

int1

uint64

Uses variable-length encoding.

uint64

long1

sint32

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.

int32

int

sint64

Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.

int64

long

fixed32

Always four bytes. More efficient than uint32 if values are often greater than 228.

uint32

int1

fixed64

Always eight bytes. More efficient than uint64 if values are often greater than 256.

uint64

long1

sfixed32

Always four bytes.

int32

int

sfixed64

Always eight bytes.

int64

long

bool

 

bool

boolean

string

A string must always contain UTF-8 encoded or 7-bit ASCII text.

string

String

bytes

May contain any arbitrary sequence of bytes.

string

ByteString

    除此之外,还支持枚举,自定义类型等。

  1. protobuf的限定符

  • required:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;如果该项不设值,在序列化时会抛出RuntimeException,推荐不使用该字段,该字段一旦使用,无法更改。

     

    由于一些历史原因,基本数值类型的repeated的字段并没有被尽可能地高效编码。在新的代码中,用户应该使用特殊选项[packed=true]来保证更高效的编码。如:repeated int32 samples = 4 [packed=true];

     

    required是永久性的:在将一个字段标识为required的时候,应该特别小心。如果在某些情况下不想写入或者发送一个required的字段,将原始该字段修饰符更改为optional可能会遇到问题——旧版本的使用者会认为不含该字段的消息是不完整的,从而可能会无目的的拒绝解析。在这种情况下,你应该考虑编写特别针对于应用程序的、自定义的消息校验函数。Google的一些工程师得出了一个结论:使用required弊多于利;他们更愿意使用optional和repeated而不是required。当然,这个观点并不具有普遍性。

     

  • optional:消息格式中该字段可以有0个或1个值(不超过1个)。不存在时使用默认值,默认值可自定义如[default = 10]。系统默认值如下:int = 0,bool = false,string=""

     

  • repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List。

     

  1. guide style

Protocol Buffers官方提供了一个Guide Style。其中介绍了一些定义proto的优秀实践。一句话总结就是名称时,message名称以驼峰方式定义,字段名则需要以如author_name方式定义。字段名在生成Java代码时,会自动转换为符合Java风格的命名方式。

  1. 生成. Java文件

将编写的.Proto文件与下载的protoc.exe文件放在同一指定的目录,进入dos并系统编译命令:protoc XXX.proto --java_out=C:/,这时会在你所指令的目录生成相应的java文件。

  1. 它的一些缺点

  • 不支持大数据集的处理,少于1M
  • 不支持Date,Map这些Java内建的对象

 

  1. 客户端示例

  • 如果Message类中用到repeated 定义的类型,则在客户端中按如下代码操作: builder.addBody(Message.Body.newBuilder().setContent(bytes).build());
  • 也可用下面默认的方式传输二进制,这时在节点7中就要使用默认的protobuf解码方式,

    byte[] test = "asdfa".getBytes();        

    ChannelBuffer channelBuffer = ChannelBuffers.buffer(test.length);

    // 将 获得到的数组写入 channelBuffer中

    channelBuffer.writeBytes(test);

    // 发送到服务器端

    ChannelFuture lastWriteFuture = channel.write(channelBuffer);

  1. 服务器端示例

  1. ServerHandler示例

  • 如果使用默认的Protobuf解码方式传输二进制,则接收时按以下代码接收:

if((e.getMessage() instanceof ChannelBuffer)){

        ChannelBuffer channelBuffer =(ChannelBuffer)e.getMessage();

        byte[] bytes = channelBuffer.array();

}

  1. PipelineFactory示例

  • 其中,以下两行代码是默认的Protobuf解码类型,如果到自定义解码,这两行可以注释掉,反之把自定义的加码解码注释掉.

pipeline.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());

pipeline.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());

  • org.jboss.netty.handler.codec.frame ,这个包里面有三种封包方法(主要用在传输字符串):

    1.DelimiterBasedFrameDecoder 是利用分隔符来进行包的界定;2.FixedLengthFrameDecoder 是利用固定的长度来进行包的界定;3.LengthFieldBasedFrameDecoder 和 LengthFieldPrepender 是利用在发送数据的时候在里面加上头字段,头字段里面包含了包的长度。


推荐阅读
  • Redux入门指南
    本文介绍Redux的基本概念和工作原理,帮助初学者理解如何使用Redux管理应用程序的状态。Redux是一个用于JavaScript应用的状态管理库,特别适用于React项目。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • This request pertains to exporting the hosted_zone_id attribute associated with the aws_rds_cluster resource in Terraform configurations. The absence of this attribute can lead to issues when integrating DNS records with Route 53. ... [详细]
  • 本文介绍了如何在 Node.js 中使用 `setDefaultEncoding` 方法为可写流设置默认编码,并提供了详细的语法说明和示例代码。 ... [详细]
  • HTML5 表单新增属性详解
    本文深入探讨了HTML5中表单的新增属性,帮助读者全面掌握这些新特性。内容涵盖autocomplete、autofocus、list等常用属性,并详细解释了form、novalidate、enctype和accept-charset等高级属性的功能与应用场景。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • CSS高级技巧:动态高亮当前页面导航
    本文介绍了如何使用CSS实现网站导航栏中当前页面的高亮显示,提升用户体验。通过为每个页面的body元素添加特定ID,并结合导航项的类名,可以轻松实现这一功能。 ... [详细]
  • 本文回顾了2017年的转型和2018年的收获,分享了几家知名互联网公司提供的工作机会及面试体验。 ... [详细]
  • Symfony是一个功能强大的PHP框架,以其依赖注入(DI)特性著称。许多流行的PHP框架如Drupal和Laravel的核心组件都基于Symfony构建。本文将详细介绍Symfony的安装方法及其基本使用。 ... [详细]
  • 采用IKE方式建立IPsec安全隧道
    一、【组网和实验环境】按如上的接口ip先作配置,再作ipsec的相关配置,配置文本见文章最后本文实验采用的交换机是H3C模拟器,下载地址如 ... [详细]
  • 本文介绍如何使用PHP在WordPress中根据分类类别ID或名称获取所有相关文章,提供详细的方法和代码示例。 ... [详细]
  • 本文详细介绍了 Java 中 org.geotools.data.shapefile.ShapefileDataStore 类的 getCurrentTypeName() 方法,并提供了多个代码示例,帮助开发者更好地理解和使用该方法。 ... [详细]
author-avatar
-____Ddddear_534
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有