请选择 进入手机版 | 继续访问电脑版
搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

Protocol Buffers

[复制链接]
查看: 44|回复: 0

1万

主题

2万

帖子

5万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
52003
发表于 2019-12-3 00:03 | 显示全部楼层 |阅读模式
Google Protobuf

Why Protobuf

protobuf它是Google供给的一个技术, 一个类库, 也可以说是一套标准, 学java的人都晓得java有自己的序列化机制, 对差此外java步伐来说,他们可以操纵同一种序列化机制举行数据的转达, 可是java的序列化机制并不适用于其他的说话比如python
假如想让他们同享数据,我们就得界说中数据格式, 比如xml, 经过xml界说出一个工具, 这样java,python都可以分析xml, 可是在收集上传输xml的话能否是有点浪费资本呢? xml中有大量的冗余的标签没有现实的意义还不能去除, 严重影响性能. 致使传输的服从急剧低落
protobuf的出现就是为了迎战这个服从低的题目
什么是protobuf?

protobuf 全称是: protocol buffers 是一种说话中立的用于序列化结构化数据 ,相对于XML这类格式的数据来说,protobuf极为小, 呆板灵活,我们只要界说好数据的格式, 便可以操纵代码天生器天生代码,我们只需要操纵它天生出来的代码就能实现轻松编写,读取结构化数据, 而且现在Protobuf支持 C++ , C# , Dart , Go , Java , Python多种说话
安装情况

想操纵protobuf的话我们要先去下载两个工具, 第一个就是protobuf的编译器也就是protoc , 我们一会将操纵它把我们界说的 .proto 文件编译成java代码, 然后我们间接操纵它天生的java代码就ok
下载链接: https://github.com/protocolbuffers/protobuf/releases>
按照一样的系统挑选差此外编译器就ok,我用的windows, 所以挑选 :protoc-3.11.0-win64.zip
假如我们想用java玩protobuf , 一样得在上面的链接中将protobuf-java-3.11.0.zip 下载到当地
上手操纵

整体思绪:
首先我们只要按照需求拟订出 .proto 文件中抵消息的描摹就ok. 由于代码自动天生:

  • 客户端代码生曾计谋: stub(装)
  • 办事端代码生曾计谋: skeleton(骨架)
序列化encode和反序列decode化也叫做编码息争码:
操纵流程:

  • 界说结果分析文件: 描摹接口工具(结构体), 工具成员,接口方式等一系列信息(这是个文本文件自力于任何酿成说话)
  • 经过RPC框架供给的编译器将接口分析文件编译成具体的说话实现
  • 在客户端和办事端别离引入RPC编译器天生的文件,即可举行RPC远程进程挪用
参照项目官方地址 https://github.com/protocolbuffers/protobuf/tree/master/java
我们需要增加maven依靠导入运转时情况, 确保我们下面导入的运转时依靠和protoc的版本同等
  1.   com.google.protobuf  protobuf-java  3.11.0  com.google.protobuf  protobuf-java-util  3.11.0
复制代码
一: 编写 .proto 文件

这个 .proto 文件, 是一个描摹性质的文件,我们操纵这个文件去描摹通讯的双方每次发送的数据的格式是怎样样的,就像XML能描摹出一个工具出来
下面是 .proto 文件的示例,语法和java 神似
  1. // proto有两个版本, 2和3, 这里操纵的 proto2syntax = "proto2"; // 以pakcet包名起头, 为了避免命名的辩说package tutorial;  // 假如我们没有表示的指定 java_package 的话, 他就是用上面的packet当做天生的java类的包名  // 表示的指定了 java_package , 终极天生的java代码包的名字就用 java_package 为准// 即即是 表示的供给了 java_package, 也得供给上面的packet(避免在其他说话中出现命名的辩说)option java_package,  = "com.example.tutorial"; // 终极经过protoc处置赏罚后 会天生一个 叫AddressBookProtos的内部类, 这个类中包含了我们指定的下面的全数类// 假如我们没有表示的指定的话,终极就会将文件名转换为驼峰命名法获得的名,当做类名字option java_outer_classname = "AddressBookProtos";// message实在是不同典范的 field的聚合,比如 string, int32,bool,float,double// 第一个消息message Person {  // 这类即是1, 即是2, 并不是赋值, 而是举行一种唯一的标志,在同一个范围中 ,标志不反复  // 以下面的123, 跳过罗列后的4  // required 表示这个字段是必必要有的,假如不供给的话会抛出很是  required string name = 1;  required int32 id = 2;  // 表示这个字段的值是可选的  optional string email = 3;      // 罗列典范的消息  enum PhoneType {    MOBILE = 0;    HOME = 1;    WORK = 2;  }  // 消息中的小 PhoneNumber  message PhoneNumber {    required string number = 1;    // Default表示这个字段的值, 默许就是罗列中的HOME值, 假如用户供给新的值, 会覆盖默许值      optional PhoneType type = 2 [default = HOME];  }  // repeated 表示是可反复的,可以尽情次, 可以大白成java中的list  repeated PhoneNumber phones = 4;}// 第二个消息// 可以操纵下面这类消息的嵌套message AddressBook {  repeated Person people = 1;}
复制代码
二. 编译 .proto 文件

编译的命令以下:
  1. protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto例: protoc --java_out=src/main/java src/protobuf/Person.proto
复制代码
在上面的命令中我们需要指定两个文件目录,一个是 源代码的途径, 另有就是 方针途径
Protocol Buffers  游戏 1496926-20191202192712484-1816226905

看一下天生的这个类的继续系统
Protocol Buffers  游戏 1496926-20191202192711524-2115700597

也不怕絮聒, 再说一次, 按照我们供给的 .proto文件, 最概况的是StudentProtobuf是我们在java_outer_classname指定的名字, 内部类Student,是我们指定的 消息典范

  • 消息Student仅仅存在get方式,而且它是一个不成变的, 一经构建出来, 就不成再改变
  • 消息的构建需要借助于构建器, 看上图, 构建器是消息内置工具
  • 消息Student 中存在一个构建器, 这个构建器的感化就是经过构建者形式完成对Student的构建, 机关器供给了抵消息Student的一系列set方式
所以就有了下面的构建工具的一幕
  1.        StudentProtobuf.Student  student = StudentProtobuf.Student.newBuilder()                .setEmail("123123@qq.com")                .setId(1)                .setName("张三").build();
复制代码
不要实行去点窜这个天生的类, 由于每次重新天生, 城市举行一次覆盖
然后protoc就会帮我们天生指定的文件AddressBookProtos.java 名子就是我们在 .proto文件中的 java_outer_classname指定的名字
Protocol Buffers  游戏 1496926-20191202192711070-163772753

补充 Message Method
这是Message中内置的一些方式

  • isInitialized(): 检查能否全数的 required典范的描摹字段都被赋值了
  • toString(): 用人类可读的方式表示这些字段
  • mergeFrom(Message other): (builder only)将其他的消息合并到次消息中
  • clear(): (builder only)扫除全数字段的空状态
  • byte[] toByteArray();: 将消息序列化成二进制数组
  • static Person parseFrom(byte[] data);: 从给定的二进制数组中反序列化成 工具
  • void writeTo(OutputStream output);: 序列化消息并将其写入OutputStream
  • static Person parseFrom(InputStream input);: 读取和分析来自InputStream的消息。
三. 测试操纵

代码以下, 固然是在一个java文件中完成的,可是也是具有现实意义的, 就像前面说的 proto可以实现比XML更好,更快,更灵敏的工具的描摹, 一样也是跨越说话的
  1. // 构建工具StudentProtobuf.Student  student = StudentProtobuf.Student.newBuilder()         .setEmail("123123@qq.com")         .setId(1)         .setName("张三").build();// 转换成字节数组 byte[] bytes = student.toByteArray();// todo 从收集合传输发往其他客户端 // 其他客户端,将工具反序列化出来 StudentProtobuf.Student stu = StudentProtobuf.Student.parseFrom(bytes); System.out.println(stu.getName()); System.out.println(stu.getEmail()); System.out.println(stu.getId());
复制代码
RMI: remote method invocation 远程方式挪用
只针对java, 办事端和客户端之间之间举行通讯, 一样平常他的流程是这样的, 在client端生将消息序列化转换成字节码, 然后经过收集的传输感化,流向办事端, 办事负端再将这些数据返回序列化会消息信息举行下一步处置赏罚操纵
Netty对Protobuf的支援

Netty+Protobuf是可以实现 RPC(remote procedure call,远程进程挪用,到达跨说话的挪用利用挪用, 而且他们之间结合和传统web service对照他的上风是在编解码的服从上很高,在收集上的传输数据很快
思绪: netty和protobuf之间的整合是必定的事变, protobuf 可以很好的完成工具的序列化, 而netty可以将这些已经完成序列化的数据发送进来
Netty办事端和客户真个编码实在挺呆板化的,** 我们的关注点是netty供给了哪些针对protobuf编解码的处置赏罚器**, 以及怎样给netty增加上这些处置赏罚器, 实例代码以下:
毫无疑问,在netty启动进程中静态的增加多个处置赏罚器必定是经过实现 ChannelInitializer 类来实现
  1. public class MyClientInitializer extends ChannelInitializer {    @Override    protected void initChannel(SocketChannel socketChannel) throws Exception {        ChannelPipeline pipeline = socketChannel.pipeline();        // todo 次第        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());        pipeline.addLast(new ProtobufDecoder(StudentProtobuf.Student.getDefaultInstance()));        pipeline.addLast(new ProtobufVarint32FrameDecoder());        pipeline.addLast(new ProtobufEncoder());        // 自界说的处置赏罚器        pipeline.addLast(new MyClientHandler());    }}
复制代码
如上代码中的 ProtobufVarint32LengthFieldPrepender 和 ProtobufVarint32FrameDecoder 这两个解码器都能处置赏罚半包信息, ProtobufDecoder中的泛型就是消息的实体的典范,表示依照这个典范完成数据的反序列化
踩坑

如上几个处置赏罚器的增加次第中, ProtobufEncoder 这个处置赏罚器, 必定的放在处置赏罚半包数据的那两个处置赏罚器的背面, 不处置赏罚半包数据, 就得不到完整的数据, 对不完整的数据举行解码, 就会出现以下的很是
Protocol Buffers  游戏 1496926-20191202192710639-315411394


免责声明:假如加害了您的权益,请联系站长,我们会实时删除侵权内容,感谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 妈妈网-中国妈妈第一,是怀孕、育儿、健康等知识交流传播首选平台 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表