vlambda博客
学习文章列表

微服务间的通信--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_nameuser name 
passwordpassword 
retry_timeretry timescan 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++ 中的两种注释风格

  1. 斜线加星号 /* ... */

  2. 双斜线  //

2.2 代码生成

Golang 代码生成

  1. 到 Protobuf 官方 Repo 下载对应平台的 protoc 工具

  2. 首先用 go命令安装生成Go代码的工具, 此工具为生成Golang代码的插件

    go install google.golang.org/protobuf/cmd/protoc-gen-go
  3. 生成最终的代码

    SRC_DIR: 源目录

    DST_DIR: 生成的代码目录

    protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/request.proto

    最终生成 request.pb.go文件,该文件不用修改,后期有任何更新可以重新生成。

  4. 将上述代码保存到 request.proto 文件中

Golang 代码使用

生成的代码可以直接在项目中使用

func main() {
 // 创建请求
loginRequest := request.LoginRequest{
UserName: "Gavin.Yang",
Password: "92d273941d98a8e1c1bb13ac163f0d4e40c5aa70",
RetryTimes: 0}

 // 序列化
outerr := proto.Marshal(&loginRequest)
if err == nil{
fmt.Println(out)
}
}

相关代码

https://github.com/yyl719133368/imooc_demo



更多精彩推荐: