微服务间的通信--Protobuf
微服务间的通信--Protobuf
微服务间的通信--Protobuf1. 概述2. 快速使用2.1 定义通信协议协议版本协议字段类型注释2.2 代码生成Golang 代码生成Golang 代码使用相关代码
1. 概述
上图是一个被拆解的 SONY 相机,里面的元器件在工作的时候各司其职,只做自己擅长的领域。他们可以来自于不同的厂家甚至国家,在全球化的今天,大部分优秀的产品都在针对某个单点进化,寻求更优质的服务和技术。
其实对于软件技术来说也是一样,并且更像全球化的一个缩影。
Microservices 没有固定且单一的定义,随着时间的流逝以及技术的不断演进,业界却已经默默的形成了一些共识,可以总结出的特征包括以下下几点。
具体的微服务在整个架构中,通过通信协议相互传递信息 例如 HTTP。
微服务是可以独立部署的。
微服务是围绕业务组织具体的功能的。
微服务不限语言、数据库、硬件和软件环境来实现服务。
服务颗粒度小,支持消息传递,受上下文限制并通过自动化流程来构建和发布。
从以上总结来看,微服务间的信息交互是整个 MSA ( Microservice Architecture ) 的基础,通信 协议 的质量决定了基于此建立的服务是否简洁、高效、稳定、可扩展、易于维护。最终体在产品中就是用户体验,尤其是针对需要快速响应的服务,比如:支付、广告竞价等。而 Protocol Buffers ( 通常称为 Protobuf ) 正是此中的佼佼者。
至于为什么,我们可以参考以下这篇文章,这里不赘述。
Beating JSON performance with Protobuf LINK
2. 快速使用
2.1 定义通信协议
让我们先来看一个非常简单的例子,假设我们需要定义一个登录请求,这个登录请求需要有 用户名
、密码
、重试次数
。我们可以将这个请求定义在一个后缀为.proto
的文件中。信息的内容如下:
/* LoginRequest represents a login request
* user_name: user name
* password: password
* retry_time: retry times, can not over 3 times */
syntax = "proto3"; // proto3 syntax
option go_package = "pb/request";
message LoginRequest {
string user_name = 1;
string password = 2;
int32 retry_times = 3;
}
协议版本
第一行定义了当前使用语法版本,最新的版本就是 proto3。也可以使用 proto2
协议字段类型
LoginRequest
消息体定义了具体的三个参数,每个参数都有具体的类型以及名字。每个字段都可以按照以下表格中的 .proto Type 来定义 – 并且最终应用在特定语言(Java + Go)中的类型也可在表中找到。
.proto Type | Notes | Java Type | Go Type |
---|---|---|---|
double | double | float64 | |
float | float | float32 | |
int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int | int32 |
int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | long | int64 |
uint32 | Uses variable-length encoding. | int | uint32 |
uint64 | Uses variable-length encoding. | long | uint64 |
sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int | int32 |
sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | long | int64 |
fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 228. | int | uint32 |
fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 256. | long | uint64 |
sfixed32 | Always four bytes. | int | int32 |
sfixed64 | Always eight bytes. | long | int64 |
bool | boolean | bool | |
string | A string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232. | String | string |
bytes | May contain any arbitrary sequence of bytes no longer than 232. | ByteString | []byte |
注释
Protobuf 支持 C/C++ 中的两种注释风格
斜线加星号
/* ... */
双斜线
//
2.2 代码生成
Golang 代码生成
到 Protobuf 官方 Repo 下载对应平台的
protoc
工具首先用
go
命令安装生成Go代码的工具, 此工具为生成Golang代码的插件go install google.golang.org/protobuf/cmd/protoc-gen-go
生成最终的代码
SRC_DIR: 源目录
DST_DIR: 生成的代码目录
protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/request.proto
最终生成
request.pb.go
文件,该文件不用修改,后期有任何更新可以重新生成。将上述代码保存到
request.proto
文件中
Golang 代码使用
生成的代码可以直接在项目中使用
func main() {
// 创建请求
loginRequest := request.LoginRequest{
UserName: "Gavin.Yang",
Password: "92d273941d98a8e1c1bb13ac163f0d4e40c5aa70",
RetryTimes: 0}
// 序列化
out, err := proto.Marshal(&loginRequest)
if err == nil{
fmt.Println(out)
}
}
相关代码
https://github.com/yyl719133368/imooc_demo
更多精彩推荐: