Protobuf 在 Ubuntu18 下的安装和使用

Protocol Buffer 是 Google 搞的 RPC 服务的中间层数据协议。其实 RPC 服务之间可以用各种数据格式,例如 JSON、XML 等。但考虑编解码效率和传输效率的话,Protobuf 性能更好。

此外,Protobuf 还包含了一个编译器,可以把 proto 文件编译成各种语言对应的代码。

安装

下载源码

git clone https://github.com/protocolbuffers/protobuf.git

安装依赖库

Protocol Buffer 是 C++ 编写的,主要是安装 g++ 编译器:

sudo apt-get install autoconf automake libtool curl make g++ unzip

编译安装并更新共享库

cd protobuf/
./autogen.sh
./configure
make
sudo make install
sudo ldconfig

测试

protoc -h

安装 Golang 的 proto API

每种语言在使用 Protobuf 时,通过调用现成的库来实现转换。Go 语言的 API 库安装方式:

go get -v -u github.com/golang/protobuf/proto

安装 protoc-get-go 插件

Protobuf 官方不支持自动生成 Go 代码,需要安装一个插件。从 github 下载后,编译为可执行文件,放到 /bin 目录下即可:

# 安装
go get -v -u github.com/golang/protobuf/protoc-gen-go
# 编译
cd $GOPATH/src/github/golang/protobuf/protoc-gen-go
go build
# 放到 /bin 下
sudo cp protoc-gen-go /bin/

编译 proto 文件

假设当前目录下的 proto 文件名是 first.proto,执行下面命令:

protoc --go_out=. first.proto

得到 golang 代码 first.pb.go。proto 会在这个文件里自动创建 Go 语言的 struct,在项目中引入即可使用。

Protoc 基本语法

可以参考: https://colobu.com/2019/10/03/protobuf-ultimate-tutorial-in-go/

Protobuf 的使用流程:

  1. 编写 proto 文件
  2. 编译 proto 文件,得到各个语言的代码

推荐使用 proto3 语法,必须明确声明。如果没有声明,默认使用 proto2 语法。

消息 message

proto 文件由一个个具体的消息构成,包括请求消息和响应消息。每个消息则包含了各种类型的字段。

消息的每个字段包含前置的类型、字段名、Tag 标签。

每个字段前,可以加 repeated 关键字,表示该字段是数组。

syntax = "proto3";

// hello 请求
message HelloRequest {
	string name = 1;			// 姓名
	int32 age = 2;				// 年龄
	repeated string job = 3;	// 工作
}

message HelloResponse {
	int32 no = 1;
}

Tag

Tag 标签从 1 开始,定义后不可修改。[1-15]内的标识在编码时占用一个字节,包含标识和字段类型,对于常用字段最好放在前 15 个字段。

[19000-19999]之间的标识符是 proto 预留的,不可使用。

protoc 的编译结果

  • Go: 生成一个.pb.go文件,每个消息类型对应一个结构体
  • C++: 每个.proto文件生成一个.h文件和一个.cc文件,每个消息类型对应一个类
  • Java: 生成一个.java文件,同样每个消息对应一个类,同时还有一个特殊的Builder类用于创建消息接口

引入其他 proto 文件

import  "other.proto";

指定包名 package

项目太大时,难免有命名冲突。可以通过定义 proto 的包名避免 message 类型之间的名字冲突。

package foo.bar;

普通字段

保留字段和标签

可以使用 reserved 关键字指定保留字段名和标签。

message Foo {
    reserved 2, 15, 9 to 11;
    reserved "foo", "bar";
}

数据类型

除了基本数据类型外,proto 还支持复合数据类型,包括:枚举、map、数组、其它message。

.proto Go
double float64
float float32
int32 int32
int64 int64
uint32 uint32
uint64 uint64
sint32 int32
sint64 int64
fixed32 uint32
fixed64 uint64
sfixed32 int32
sfixed64 int64
bool bool
string string
bytes []byte

Oneof

使用 Oneof 定义的一组字段,最多允许这组字段中的一个出现。

syntax = "proto3";
package abc;
message OneofMessage {
    oneof test_oneof {
      string name = 4;
      int64 value = 9;
    }
}

oneof 字段不能同时使用repeated。

map类型

proto3 的 map 语法为 map map_name = fieldNumber,例如:

map m_name = 1;

枚举类型

枚举类型限定字段的值只能取某个特定的值,比如星期类型只能取周一到周日七个值。

枚举类型的定义采用C++ scoping规则,也就是枚举值是枚举类型的兄弟类型,而不是子类型,所以避免在同一个package定义重名的枚举字段。

嵌套类型

可以把 message 类型当做普通字段,嵌套使用。

message SearchResponse {
  message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
  }
  repeated Result results = 1;
}

你可能感兴趣的:(微服务)