这是我参与「第三届青训营 -后端场」笔记创作活动的第6篇笔记
现如今,微服务变得越来越流行,而服务间的通信也变得越来越重要,服务间通信本质是交换信息,而交换信息的中介/桥梁正是我们的API。
诚然,目前构建API最受欢迎的仍然是使用Restful(HTTP-JSON),因为它简单、快速、易懂。
但是在本文中,我们不妨尝试探索使用gRPC来构建我们的API,并在这个过程比较gRPC与Restful两者的异同。
最后,让我们来思考下,一个API应该是怎样的?如果从宏观的角度看,一个API应该是非常简单的,因为它就做了两件事:
- 1.客户端发送一个请求(Request)
- 2.服务端接收请求,并返回一个响应(Response)
这种思想在gRPC中也体现得非常明显,而从微观上看,构建一个API,我们可能需要考虑到:
- 1.我们使用什么数据模型?JSON、XML还是二进制流
- 2.我们使用什么协议传输?HTTP、TCP、还是HTTP/2
- 3.我们如何调用方法,以及处理错误
- 4.我们如何应对数据量大的情况
- 5.我们如何减少接口的延时等
- ...
话不多说,让我们进入正题。
什么是gRPC
在聊聊什么是gRPC前,我们先来聊聊什么是RPC。
RPC,全称Remote Procedure Call,中文译为远程过程调用。通俗地讲,使用RPC进行通信,调用远程函数就像调用本地函数一样,RPC底层会做好数据的序列化与传输,从而能使我们更轻松地创建分布式应用和服务。
而gRPC,则是RPC的一种,它是免费且开源的,由谷歌出品。使用gRPC,我们只需要定义好每个API的Request和Response,剩下的 gRPC这个框架会帮我们自动搞定。
另外,gRPC的典型特征就是使用protobuf(全称protocol buffers)作为其接口定义语言(Interface Definition Language,缩写IDL),同时底层的消息交换格式也是使用protobuf。
gRPC基本通信流程
这是官方文档的一张图,通过这张图,我们可以大致了解下gRPC的通信流程:
1.gRPC通信的第一步是定义IDL,即我们的接口文档(后缀为.proto)
2.第二步是编译proto文件,得到存根(stub)文件,即上图深绿色部分。
3.第三步是服务端(gRPC Server)实现第一步定义的接口并启动,这些接口的定义在存根文件里面
4.最后一步是客户端借助存根文件调用服务端的函数,虽然客户端调用的函数是由服务端实现的,但是调用起来就像是本地函数一样。
以上就是gRPC的基本流程,从图中还可以看出,由于我们的proto文件的编译支持多种语言(Go、Java、Python等),所以gRPC也是跨语言的。
gRPC VS Restful
gRPC和Restful之间的对比,历来是学习gRPC的必修课,我会从文档规范、消息编码、传输协议、传输性能、传输形式、浏览器的支持度以及数据的可读性、安全性等方面进行比较。
文档规范
文档规范这种东西有点见仁见智,在我看来,gRPC使用proto文件编写接口(API),文档规范比Restful更好,因为proto文件的语法和形式是定死的,所以更为严谨、风格统一清晰;而Restful由于可以使用多种工具进行编写(只要人看得懂就行),每家公司、每个人的攥写风格又各有差异,难免让人觉得比较混乱。
另外,Restful文档的过时相信很多人深有体会,因为维护一份不会过时的文档需要很大的人力和精力,而公司往往都是业务为先;而gRPC文档即代码,接口的更改也会体现到代码中,这也是我比较喜欢gRPC的一个原因,因为不用花很多精力去维护文档。