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的资料网上还不是特别多,有的都是很基础的,大佬写的这个还是很不错的~~很丰富!!!大佬~加油更新!!支持~~