Go 微服务基础:Protobuf & gRPC
这篇文章写的稍微有点乱,因为写作过程中思路有大断流。
本文历时很多天,期间我的两大主要开发环境 —— Python 和 Golang 都炸了,顺便,包管理工具 Homebrew 也出了点小问题(一切都是因为一条没经过深思的错误的 brew upgrade
命令)。尝试手动修复,搞了一天,无果。没办法 Time Machine 恢复了一下,由于最近几天都没备份😭,S/L 大法不太灵,它一下子给我回到了十天前。各种手动检查、清理、git pull,又花费了一天。。。
不过这些怎么样都无所谓啦,我想说的是,大家在敲回车前还是要三思,尤其是使用管理员权限时。还有备份不要忘啊,再忙也要记得做备份哦。
我们开门见山,废话结束!这篇文章前半部分介绍了 Protocol Buffers 的安装使用和基本语法。后半部分基于 Golang,通过一个实例,介绍 Protobuf 与 gRPC 的使用。
文章目录
Protobuf
Protocol Buffers 是一种序列化数据结构的协议。对于透过管道或存储数据进行通信的程序开发上是很有用的。这个方法包含一个接口描述语言,描述一些数据结构,并提供程序工具根据这些描述产生代码,用于将这些数据结构产生或解析数据流。
—— WikiPedia
总而言之, Protocol Buffers,简称 Protobuf, 是一种数据描述语言(和 XML、JSON 这些类似)。Protobuf 配套的工具可以自动生成将各种语言中的数据结构序列化为 Protobuf 表示,然后反序列化到任意支持的语言中。
在 RPC 中,跨语言的数据编码、解码是个问题, Protobuf 是一种比较高效的解决方案。gRPC 就是基于 Protobuf 的一套 RPC 框架。
安装 Protobuf
在 macOS 上,使用 homebrew 可以快速安装 protobuf。 brew
绝对是我见过最省事的包管理,忽略国内众所周知的原因带来的一些小问题,几乎满足了一切日常安装需要:
$ brew install protobuf
...
$ protoc --version
libprotoc 3.13.0
我们要在 Golang 中使用 protobuf,需要把 ptotobuf “编译”成 Golang,需要安装 protoc-gen-go 工具来做这件事:
$ go install google.golang.org/protobuf/cmd/protoc-gen-go
下面先尝试使用它完成一次 HelloWorld,后面再介绍 Protobuf 的基本语法呀。
使用 Protobuf
首先,创建一个 hello.proto
文件:
$ vim hello.proto
写入如下 Protocol Buffers 代码:
syntax = "proto3";
package hello;
message Hello {
string world = 1;
int32 meaningless_count = 2;
}
编译,生成 Golang 代码:
$ protoc --go_out=. hello.proto
go_out
告诉 protoc 编译器加载 protoc-gen-go 工具来生成代码,把生成代码放到当前目录。忽略打印的 WARNING,protoc
在当前路径下生成了一个 hello.pb.go
的文件。里面有很多内容,包括:
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.13.0
// source: hello.proto
package hello
type Hello struct {
...
World string `protobuf:"bytes,1,opt,name=world,proto3" json:"world,omitempty"`
MeaninglessCount int32 `protobuf:"varint,2,opt,name=meaningless_count,json=meaninglessCount,proto3" json:"meaningless_count,omitempty"`
}
func (x *Hello) Reset() {
...}
func (x *Hello) String() string {
...}
func (*Hello) ProtoMessage() {
}
func (x *Hello) ProtoReflect() protoreflect.Message {
...}
func (*Hello) Descriptor() ([]byte, []int) {
...}
func (x *Hello) GetWorld() string {
...}
func (x *Hello) GetMeaninglessCount(