Go微服务实战|第1章:gRPC 简介
Synopsis: gRPC 是谷歌开源的高性能、轻量级 RPC 通信框架,基于 Protocol Buffers 序列化协议进行开发,支持多种语言(C++、Golang、Python、Java 等),本篇只介绍 Golang 的 gRPC 使用。同时,由于 gRPC 支持 HTTP/2 协议,使用二进制帧进行数据传输,还可以为通信双方建立持续的双向数据流,使其在 Android、iOS 等客户端后端服务的开发领域具有良好的前景。gRPC 提供了一种简单的方法来定义服务,同时客户端可以充分利用 HTTP/2 stream 的特性,从而有助于节省带宽、降低 TCP 的连接次数、节省CPU的使用等
代码已上传到 https://github.com/wangy8961/grpc-go-tutorial/tree/v0.1 ,欢迎star
1. net/rpc
Go 语言的标准库 net/rpc 内置了 RPC(Remote Procedure Call) 实现,详细代码请参考: https://github.com/wangy8961/go-rpc-tutorial
其中,HTTP-RPC 和 TCP-RPC 内部采用 gob 对数据进行编解码,效率很高,但只适用于 Golang 语言,不能实现 跨语言 提供 RPC 服务
另外,https://golang.org/pkg/net/rpc/jsonrpc/ 和 https://godoc.org/github.com/ethereum/go-ethereum/rpc 包实现了 JSON-RPC。但是,我们在实现 RPC 时,其实跟实现 RESTful API 一样,除了数据交互以外,还需要考虑很多其它问题,比如 endpoint 的设计、错误处理、API 的效率、如何扩展、负载均衡、跨语言性、接口的认证/监控/日志等
所以,如果有一个 RPC 框架已经帮我们做好了这些事情呢?那就是我们接下来要讨论的 gRPC
2. gRPC
2.1 What is gRPC ?
gRPC 是 Google 开源的、高性能的通用 RPC 框架,可以 跨语言和平台 工作!它默认使用 Protocol Buffers 来描述服务接口和基础消息交换格式
与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定其能够被远程调用的方法(包含其参数和返回类型):
- 在服务器端,服务器实现此服务接口并运行
gRPC服务器来处理客户端调用 - 在客户端,会有一个
stub(referred to as just a client in some languages) ,that provides the same methods as the server.

如上图所示,gRPC 客户端和服务器可以在各种环境中相互运行和通信,Client / Server 都可以使用任何 gRPC 支持的语言来编写
在 gRPC 中,客户端 应用程序可以像调用本地对象一样,直接调用不同计算机上的 服务端 应用程序中的方法,这样就可以更轻松地创建分布式应用程序和服务
2.2 Protocol Buffers v3
Protocol Buffers 是 Google 开源的,一种与语言无关,平台无关,可扩展的,用来将结构化数据序列化成 二进制数据编码格式 的方法,用于通信协议,数据存储等。RPC 调用过程中客户端和服务端必须基于同一种 基础消息交换格式,才能让双方明白需要交换的数据到底代表什么意思! 不同的 RPC 框架可能选用的编解码协议各不相同,比如 gob、JSON、messagepack 等,相比于 JSON 或 XML 这种 文本数据编码格式 而言,Protocol Buffers 的数据体积更小、读写速度更快
gRPC 目前使用 Protocol Buffers V3(简称 proto3),它是 proto2 的升级版,性能更优,并增加了对 iOS 和 Android 等移动设备的支持
在 Protocol Buffers 中需要被序列化的数据,会被构造成 消息,每个消息可以包含一些字段:
// Defining A Message Type
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
上面的消息中 3 个字段的类型都是简单的 标量值类型(scalar types),另外,你还可以为字段指定复合类型,比如 枚举类型(enumerations) ,消息也支持 嵌套(Nested Types),在一个消息中包含另一个消息类型:
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
详细的
开发指南请参考: https://developers.google.com/protocol-buffers/docs/proto3
2.3 HTTP/2

gRPC 使用 Protocol Buffers 将需要传输的数据 payload 编码成二进制数据后,采用 HTTP/2 协议进行传输。读者可以访问 https://imagekit.io/demo/http2-vs-http1 来了解 HTTP/2 和 HTTP/1.1 之间的区别
HTTP/2详解: https://github.com/bagder/http2-explained/tree/master/zh
3. grpc-go
gRPC 目前主要有 grpc-c、grpc-go、grpc-java、grpc-node 几种实现,请参考: https://github.com/grpc
而我们将会使用 grpc-go 这个包,由于我们的 Go 版本为 1.12,且使用了 Go Modules 来管理包依赖关系,所以要使用 grpc-go 包只需要在源代码中 import "google.golang.org/grpc" 即可
4. 示例
4.1 Defining gRPC service
创建一个扩展名为 .proto 的 普通文本文件,比如 grpc-go-tutorial/greet/greetpb/greet.proto:
syntax = "proto3";
option go_package="greetpb";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
4.2 Generate gRPC-Go interface
现在我们需要从服务定义文件 greet.proto 生成 gRPC 服务端和客户端接口代码,从 Protocol Buffers 文件生成指定语言的服务接口代码,需要 protoc 编译器和指定语言的插件
(1)Install Protocol Compiler
要安装用于生成 gRPC 服务代码的 protoc 编译器,最简单的方法是到 https://github.com/protocolbuffers/protobuf/releases 去下载你的操作系统对应的预编译二进制文件,比如 protoc-3.8.0-rc-1-linux-x86_64.zip,然后解压到指定的位置即可:
[root@CentOS ~]# mkdir ~/protoc-3.8.0 [root@CentOS ~]# cd ~/protoc-3.8.0/ [root@CentOS protoc-3.8.0]
1 条评论
评论者的用户名
评论时间Tiffany疯孩子
2020-05-06T02:41:59Z目前go的资料网上还不是特别多,有的都是很基础的,大佬写的这个还是很不错的~~很丰富!!!大佬~加油更新!!支持~~