protobuf,json,xml,binary,Thrift之间的对比

golang 使用 protobuf 的教程

golang使用protobuf

一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明显的。

protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,详情访问protobuf的google官方网站。

protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

protobuf简单总结如下几点:

1.灵活(方便接口更新)、高效(效率经过google的优化,传输效率比普通的XML等高很多);

2.易于使用;开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

3.语言支持;原生支持c++,java,python

 

个人总结的适用protobuf的场合:

1.需要和其它系统做消息交换的,对消息大小很敏感的。那么protobuf适合了,它语言无关,消息空间相对xml和json等节省很多。
2.小数据的场合。如果你是大数据,用它并不适合。
3.项目语言是c++,java,python的,因为它们可以使用google的源生类库,序列化和反序列化的效率非常高。其它的语言需要第三方或者自己写,序列化和反序列化的效率不保证。
4.总体而言,protobuf还是非常好用的,被很多开源系统用于数据通信的工具,在google也是核心的基础库。

此外,还有更牛叉的facebook的thrift,2007年由Facebook开发,之后在2008年加到Apache计划中。是一个跨语言的轻量级RPC消息和数据交换框架,Thrift能生成的语言有: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml,这是它的一大优点。

 

在 Golang 中使用 Protobuf

安装 goprotobuf

1.从 https://github.com/google/protobuf/releases 获取 Protobuf 编译器 protoc(可下载到 Windows 下的二进制版本

wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
tar zxvf protobuf-2.6.1.tar.gz
cd protobuf-2.6.1
./configure
make
make install
protoc   -h

2.获取 goprotobuf 提供的 Protobuf 编译器插件 protoc-gen-go(被放置于 $GOPATH/bin 下,$GOPATH/bin 应该被加入 PATH 环境变量,以便 protoc 能够找到 protoc-gen-go)

此插件被 protoc 使用,用于编译 .proto 文件为 Golang 源文件,通过此源文件可以使用定义在 .proto 文件中的消息。

go get github.com/golang/protobuf/protoc-gen-go
cd github.com/golang/protobuf/protoc-gen-go
go build
go install
vi /etc/profile 将$GOPATH/bin 加入环境变量
source profile

3.获取 goprotobuf 提供的支持库,包含诸如编码(marshaling)、解码(unmarshaling)等功能

go get github.com/golang/protobuf/proto
cd github.com/golang/protobuf/proto
go build
go install

使用 goprotobuf
这里通过一个例子来说明用法。先创建一个 .proto 文件 test.proto:

package example;

enum FOO { X = 17; };

message Test {
required string label = 1;
optional int32 type = 2 [default=77];
repeated int64 reps = 3;
optional group OptionalGroup = 4 {
    required string RequiredField = 5;
    }
}

编译此 .proto 文件:

protoc --go_out=. *.proto

这里通过 –go_out 来使用 goprotobuf 提供的 Protobuf 编译器插件 protoc-gen-go。这时候我们会生成一个名为 test.pb.go 的源文件。

在使用之前,我们先了解一下每个 Protobuf 消息在 Golang 中有哪一些可用的接口:

  1. 每一个 Protobuf 消息对应一个 Golang 结构体

  2. 消息中域名字为 camel_case 在对应的 Golang 结构体中为 CamelCase

  3. 消息对应的 Golang 结构体中不存在 setter 方法,只需要直接对结构体赋值即可,赋值时可能使用到一些辅助函数,例如:

    msg.Foo = proto.String("hello")
  4. 消息对应的 Golang 结构体中存在 getter 方法,用于返回域的值,如果域未设置值,则返回一个默认值

  5. 消息中非 repeated 的域都被实现为一个指针,指针为 nil 时表示域未设置

  6. 消息中 repeated 的域被实现为 slice

  7. 访问枚举值时,使用“枚举类型名_枚举名”的格式(更多内容可以直接阅读生成的源码)

  8. 使用 proto.Marshal 函数进行编码,使用 proto.Unmarshal 函数进行解码

现在我们编写一个小程序:

/*
# @Time    : 2018/11/19 16:42
# @Author  : Mickel Xiang
# @File    : test_protobuff.go
# @Function: -----------
*/
package main

import (
   "log"
// 辅助库
"github.com/golang/protobuf/proto"
// test.pb.go 的路径
"./protocol/example"
)

func main() {    // 创建一个消息 Test
   test := &example.Test{        // 使用辅助函数设置域的值
      Label: proto.String("hello"),
      Type:  proto.Int32(17),
      Optionalgroup: &example.Test_OptionalGroup{
         RequiredField: proto.String("good bye"),
      },
   }    // 进行编码
   data, err := proto.Marshal(test)
   if err != nil {
      log.Fatal("marshaling error: ", err)
   }    // 进行解码
   newTest := &example.Test{}
   err = proto.Unmarshal(data, newTest)
   if err != nil {
      log.Fatal("unmarshaling error: ", err)
   }    // 测试结果
   if test.GetLabel() != newTest.GetLabel() {
      log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
   }
}

ProtoBuf(protocol buffer) 网络传输协议

转自:http://blog.csdn.net/wenyiqingnianiii/article/details/52741312

ProtoBuf是Google开源的一套二进制流网络传输协议,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、Go 和Python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

优点:传输效率快(比xml和json快10-20倍),文档型协议; 
缺点:使用不太方便;

这里简单解释一下什么是文档型协议,向我们的xml和json一般在使用的时候都需要保存一份说明文档和一个实际的java类,而protobuf在使用的时候其定义的格式就是说明文档,简单明了而且可以将其编译成各个平台的类库,以java平台为例,其编程成jar之后,若定义文件发生了变化,则在使用jar包的话就会报错,必须重新编译,这也就保证了App端与服务器端的协议统一性。

网络传输协议实践

由于ProtoBuf的传输效率和文档型协议的特性,公司产品选择了Protobuf作为网络传输协议。下面我就以一个简单的登录操作,介绍一下对ProtoBuf的实际应用。

可以看到在Protobuf中定义网络请求,分为两个部分,请求部分和应答部分,其message request定义的是请求信息,而message response定义的是应答信息。 

请求信息中的字段就是我们请求中需要传递的字段,应答信息中的字段就是App端获取的服务器端的应答信息集合。

每个字段都有修饰符,那么修饰符是做什么的呢? 
在protobuf中定义了三种修饰符,分别为:required,optional,repeated。其中:

  • required:表示的是这个字段必须要传递,不可为空;

  • optional:表示的是这个字段可传可不传,可以为空;

  • repeated:表示这个字段传递的是列表数据

在message的定义过程中,message还可以嵌套另外的message信息,比如应答信息中的UserStatus,其和java中对象的概念很类似。

(3)将proto文件编译成jar包 
这里就不在具体介绍怎么讲proto文件编译成jar了,google已经提供了相应的编译工具。

(4)在Android代码中使用 
由于我们将proto文件编译成了jar包,首先我们需要将jar引入到我们的工程,然后就可以使用了。这里简单看一下具体的使用代码。

可以发现我们在代码中直接有对应的登录请求message类,这样我们就可以直接通过java类调用了,O(∩_∩)O哈哈~。

总结:

本文主要介绍了App开发过程中常见了三种网络传输协议,以及各自的优劣势,还重点介绍了protobuf协议的使用方式等。当然了这里我还是比较推荐protobuf的。

转载于:https://my.oschina.net/mickelfeng/blog/2878219

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值