本文正在参与 “网络协议必知必会”征文活动
前言
大部分的RPC框架为了效率会把传输的内容根据需要格式序列化成便于传输的编码,今天就说说上篇文章说的GRPC框架中的protobuf编码。
google官方文档:(Protocol Buffers)
protobuf
protobuf序列化后是一种二进制数据,体积非常小,所以传输效率非常高,最近在研究抖音的直播弹幕,发现也是使用protobuf。他有三个特点:
1.兼容性好,无关平台跨无关语言,可跨任意平台任意语言,二进制编码
2.性能强,序列化过后消息体积非常小
3.扩容性好,更新其中的字段不影响原数据
golang对protbuf编码
先写一个简单的protobuf文件test.proto:
syntax = "proto3";
option go_package = "./test";
package test;
message Data {
int32 code = 1;
string msg = 2;
string data = 3;
}
这个格式非常像goalng的struct(结构体),注意这个文件只是定义了格式并不用于传输。
syntax表示protobuf版本
option go_package指定编译后输出的文件位置
package 编译后生成的包名
定义了一个Data消息结构,元素 前面是数据类型,在序列化的时候会严格按照数据类型编译成二进制码进行传输,最后一列的1 2 3 表示消息序列,保证顺序。
然后下载windows上的protobuf的编译器:
protocolbuffers/protobuf
然后接下下载的包,把bin目录下的protoc.exe复制到自己设置的GOPATH/bin目录下
然后在GOPATH目录下执行
go get -u github.com/golang/protobuf/protoc-gen-go
生成编译器插件protoc-gen-go
然后在test.proto项目根目录下执行命令编译,跟protobuf格式文件生成goalng能够使用的编解码文件:
protoc --go_out=. *.proto
生成test.pb.go文件:
现在写一个main.go 文件实验进行protobuf序列化编码:
package main
import (
"io/ioutil"
"main/test"
"os"
"github.com/golang/protobuf/proto"
)
func main() {
msg := &test.Data{
Code: 200,
Msg: "成功",
Data: "测试",
}
//数据编码,把消息序列化成二进制数据
data, _ := proto.Marshal(msg)
ioutil.WriteFile("./test.txt", data, os.ModePerm) //序列化的文件写入test.txt
}
记得运行之前使用go mod init main和go mod tidy 初始化项目,并自动下载需要的包,接下来运行main.go:
看看这个test.txt文件大小:
突发奇想写个类似的json保存看下大小:
{"code": 200,"msg":"成功","data":"测试"}
protbuf序列化之后序列化比json数据小了一半,诚不欺我,亲测牛哇~