GPB简介

1. Gpb概述

在某电信项目中接触到GPB,用于和合作方的数据交换。 在大数据领域使用的非常多。

GPB的全称为Google Protocol Buffer,是谷歌公司用于在大数据存储及交换方面的一个开源的协议和开发库。优势在于定义好数据类型和格式,两方都可以非常高效的写入和读取,并且存储额外开销非常小。

通常我们在小型的数据交换,使用json和xml进行封装,但遇到大量数据时,比如每秒收集和传输1M甚至更多时,json等有很多的冗余数据,占用很多硬盘和带宽资源,这时GPB的优势就显现出来。

GPB是一种高效的结构化数据存储格式,可以将结构化数据序列化,即将数据保存在文件中,这在数据格式与编程语言无关,可以用于通讯协议和数据存储。当然GPB也有一定的劣势,例如其是二进制存储而不是文本存储,其开发和调试都需要工具来支持,在小量数据时,还是建议使用json等来交换数据。

2, 典型案例

假定我们有这样一个需求,我们为sina公司开发一个日志收集及存储系统,将所有的访问日志归档存储,假定每秒有10万用户访问sina,那么我们将有10万条记录需要收集,日志将访问,平均每条记录150字节将会10万*150=15M/s,即每秒收集15M的数据。假定我们收集的数据包括以下几部分

源IP,源端口,使用的UA代理,目标URL, 访问时间。

通常分为客户端和服务器,客户端收集数据然后发给服务器,因此我们定义好数据结构。

可能有多种的方式实现这个功能,方案1,客户端通常是读取syslog,然后封装为GPB,发送给服务器,服务端收取GPB然后按照自己的格式加入到大数据系统。

方案2,客户端写gpb文件,通过ftp等传递给服务器,然后服务器解析,或者直接保存。

总的来说均需要写入和读取。因此我们仅介绍写入和读取功能。因此分三部分介绍,分别为读取,写入,两者之间的协议定义。

3. GPB对象定义(协议定义)

我们用于交换数据的的访问日志,包含以下及部分:

  • srcIP IP地址,占用四个字节。
  • srcPort 源端口,占用两个字节。
  • Agent; 字符串, 设定最大占用64字节。
  • 目标url: 字符串, 设定最大占用128字节(如果超长即截断)
  • 访问时间, 自1970年的秒值。占用4个字节。
package bj;
message WebLog{
{
  required int32 time = 1;
  required int32 srcIP = 2;
  required int32 srcPort = 3;
  required string url = 4;
  optional string Agent = 5;
}

两种类型,一种为整形数字,另外一种为字符串。还有两种修饰符,一种为required,表示必须带有,如果没有将判断为错误。另外一种为optional,表示可选的,如果没有不做处理。GPB在保存时仅保存了数字索引,因此其占用空间非常小,但因此其保存的文件失去了一定的自解释性。

保存为文件weblog.proto,然后编译生成C++代码,命令为:

protoc --cpp_out=./ weblog.proto

这将生成weblog.pb.cc weblog.pb.h两个文件,这样两者之间的协议就定义好了,客户端使用这个头文件中定义的方法来写入数据,服务器通过方法来读取数据。

使用protoc命令来编译gpb协议定义文件时,对于C++来说,编译器会为每一个消息创建一个对应的类,如果定义了packet,那将定义一个名字空间。 –cpp_out表示在指定的目录里面生成c++代码,可以使用“protoc -h”来查看更多的用法。下一步我们来编写读取代码。

4. gpb数据生成

写入文件:

int write()
{
   bj::WebLog log;
   int now = time(NULL);
   log.set_timestamp(now);
   log.set_srcip(1);
   log.set_srcport(2);
   log.set_url("http://www.sina.com.cn/news");
   log.set_agent("firefox");

   fstream output("a.log", ios::out | ios::app | ios::binary);

   if(!log.SerializeToOstream(&output)){
      cout << "Failed to write msg."<<endl;
      return -1;
   }
   return 0;
}

追加到最后。

5. gpb数据读取

int read()
{
  bj::WebLog log;
  fstream fin("a.log", ios::in | ios::binary);
  if(!log.ParseFromIstream(&fin))
  {
      cout<<"Failed to parrse word! "<< endl;
      return -1;
  }
  cout<<log.url()<<endl;
  cout<<log.agent()<<endl;
  return 0;

}

读取第一个并输出。

6. Python使用

python setup.py build
python setup.py  test
python setup.py  install

 

 

<think>好的,我现在需要帮助用户了解如何在Java中使用Google Protocol Buffers(GPB)。首先,我需要回忆一下自己之前学过的关于Protocol Buffers的知识,以及用户提供的引用内容。 根据用户提供的引用,特别是引用[3],Protocol Buffers是谷歌开发的一种跨平台、语言中立的结构化数据序列化机制,比XML更小、更快、更简单。用户还提到Java的使用,所以需要重点放在Java环境下的步骤。 首先,使用Protocol Buffers通常需要几个步骤:定义.proto文件,生成Java代码,然后在项目中使用这些生成的类进行序列化和反序列化。引用[4]中的Go代码示例可能对理解流程有帮助,但用户需要的是Java版本,所以需要调整语法和依赖项。 接下来,我需要确保步骤清晰,结构正确。用户可能需要安装protobuf编译器,这在引用[3]中提到需要安装C++的Unix环境,但Java用户可能需要不同的安装步骤,或者使用Maven依赖来自动处理。比如,Java用户可能更倾向于使用protobuf-maven-plugin来自动生成代码,这样避免手动安装编译器。 然后,在代码示例部分,需要展示如何定义.proto文件,例如用户可能想定义一个简单的消息类型,比如User,包含username和age字段。之后,生成对应的Java类,并展示如何序列化和反序列化。引用[4]中的示例是用Go写的,但可以转换为Java的代码结构。 此外,用户可能关心GPB的用途,比如在RPC通信中的使用,如gRPC,但用户的问题主要集中在GPB本身的使用,所以需要专注于序列化部分。引用[1]提到GPB的用途超越简单的访问器和序列化,但用户的问题可能更基础,所以先介绍基本用法,再提及更高级的用途。 在注意事项部分,需要提到版本兼容性,因为不同版本的protobuf可能有不同的API,比如Java中使用的是proto2还是proto3,语法可能不同。引用[3]中提到定义结构化数据的方式,所以需要提醒用户注意.proto文件的语法版本。 最后,生成相关问题需要考虑用户可能的后续疑问,比如性能优化、与其他格式比较、在gRPC中的应用等。根据用户提供的引用,引用[2]提到了Java中的Protocol Buffers处理,可能涉及错误处理,如Unknown phone type的情况,所以在问题中可以包含如何处理未知字段的问题。 需要确保所有步骤正确,代码示例没有错误,并且符合Java的语法和最佳实践。同时,检查是否所有引用都被正确引用,例如引用[3]提供了安装和基本概念,引用[4]展示了序列化/反序列化的流程,但需要转换为Java代码。</think>### 如何在Java中使用Google Protocol Buffers (GPB) Google Protocol Buffers(GPB)是一种高效的结构化数据序列化工具,适用于跨语言通信和数据存储。以下是在Java中使用GPB的步骤: --- #### 1. **定义.proto文件** 首先创建一个`.proto`文件,定义数据结构。例如,定义一个`User`消息: ```protobuf syntax = "proto3"; // 指定语法版本[^3] message User { string username = 1; int32 age = 2; } ``` - `syntax = "proto3"` 表示使用Protocol Buffers的第三版语法。 - 字段后的数字(如`1`, `2`)是唯一标识符,不可重复[^3]。 --- #### 2. **生成Java类** 使用`protoc`编译器将`.proto`文件生成Java代码: ```bash protoc --java_out=./src/main/java user.proto ``` - 生成的Java类包含数据的构造、序列化和反序列化方法[^3]。 - 若使用Maven,可添加插件自动生成代码: ```xml <build> <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protoSourceRoot>src/main/resources/proto</protoSourceRoot> </configuration> </plugin> </plugins> </build> ``` --- #### 3. **在Java代码中使用** 引入依赖(Maven配置): ```xml <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.21.12</version> </dependency> ``` 序列化与反序列化示例: ```java // 创建对象 User user = User.newBuilder() .setUsername("mszlu") .setAge(20) .build(); // 序列化为字节数组 byte[] data = user.toByteArray(); // 反序列化 User parsedUser = User.parseFrom(data); System.out.println(parsedUser); // 输出: username: "mszlu" age: 20 [^4] ``` --- #### 4. **高级功能** - **扩展性**:通过添加新字段(保留旧标识符)实现向后兼容。 - **RPC支持**:GPB可与gRPC结合,用于跨服务通信[^1]。 - **性能优化**:二进制格式比JSON/XML更小、解析更快。 --- #### 注意事项 - **版本一致性**:确保`protoc`编译器版本与Java依赖版本一致。 - **未知字段处理**:反序列化时忽略未知字段(不报错),可通过`getUnknownFields()`获取[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值