一、gRPC原理
1、什么是RPC
RPC 即远程过程调用协议(Remote Procedure Call Protocol),可以让我们像调用本地函数一样发起远程调用。RPC 凭借其强大的治理功能,成为解决分布式系统通信问题的一大利器。
gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架(g就是谷歌的意思),基于 HTTP2 协议设计,序列化使用 PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。
上面的图就是一个客户端远程连接一个服务器,调用它的函数。由于使用了 PB 所以双方都要有 PB 序列化和反序列化。那么上面的操作就是通过PB序列化后,通过网络HTTP2发送给服务端,然后解析并执行,最后返回。
2、gRPC的特性
-
gRPC基于服务的思想:定义一个服务,描述这个服务的方法以及入参出参,服务器端有这个服务的具体实现,客户端保有一个存根,提供与服务端相同的服务。
-
gRPC默认采用protocol buffer作为IDL(Interface Description Lanage)接口描述语言,服务之间通信的数据序列化和反序列化也是基于protocol buffer的,因为protocol buffer的特殊性,所以gRPC 框架是跨语言的通信框架(与编程语言无关性),也就是说用Java开发的基于gRPC的服务,可以用 GoLang编程语言调用。
-
gRPC同时支持同步调用和异步调用,同步RPC调用时会一直阻塞直到服务端处理完成返回结果, 异步RPC是客户端调用服务端时不等待服务段处理完成返回,而是服务端处理完成后主动回调客户端告诉客户端处理完成。
-
gRPC是基于http2协议实现的,http2协议提供了很多新的特性,并且在性能上也比http1提搞了许多,所以gRPC的性能是非常好的。
-
gRPC并没有直接实现负载均衡和服务发现的功能,但是已经提供了自己的设计思路。已经为命名 解析和负载均衡提供了接口。
-
基于http2协议的特性:gRPC允许定义如下四类服务方法:
一元RPC:客户端发送一次请求,等待服务端响应结构,会话结束,就像一次普通的函数调用这样简单。
服务端流式RPC:客户端发起一起请求,服务端会返回一个流,客户端会从流中读取一系列消息,直到没有结果为止。
客户端流式RPC:客户端提供一个数据流并写入消息发给服务端,一旦客户端发送完毕,就等待服务器读取这些消息并返回应答。
双向流式RPC:客户端和服务端都一个数据流,都可以通过各自的流进行读写数据,这两个流是相互独立的,客户端和服务端都可以按其希望的任意顺序读写。
3、gRPC的使用场景
服务间通信:gRPC非常适合用于微服务架构中,为服务之间的通信提供高性能、类型安全和易于维护的通信机制。它支持多种编程语言,使得不同微服务可以使用不同的编程语言实现,同时轻松地进行跨语言通信。
分布式系统通信:在分布式系统中,gRPC可用于不同节点之间的通信,包括数据同步、任务分发和集群管理等场景。
4、gRPC设计的动机
1、协议可插拔:不同的服务可能需要使用不同的消息通信类型和编码机制,例如,JSON、XML和 Thirft,所以协议应允许可插拔机制,还有负载均衡,服务发现,日志,监控等都支持可插拔机制。
2、阻塞和非阻塞:支持客户端和服务器交换的消息序列的异步和同步处理。这对于在某些平台上扩展和处理至关重要。
3、流处理:存储系统依靠流和流控制来表达大型数据集,其他服务,如语音到文本或股票行情,依赖于流来表示与时间相关的消息序列。
4、流控制:计算能力和网络容量在客户端和服务器之间通常是不平衡的。流控制允许更好的缓冲区管理,以及过度活跃的对等体提供对DOS的保护。
5、互通性:报文协议必须遵循普通互联网基础框架。
二、数据封装和数据传输问题
1、网络传输中的内容封装数据体积问题
我们都知道json格式,json格式更利于人的观看,而Protobuf是二进制数据,更加利于机器。
JSON
优点:在body中用JSON对内容进行编码,极易跨语言,不需要约定特定的复杂编码格式和Stub文件。 在版本兼容性上非常友好,扩展也很容易。
缺点:JSON难以表达复杂的参数类型,如结构体等;数据冗余和低压缩率使得传输性能差。
因此gRPC丢弃json、xml这种传统策略,使用 Protocol Buffer,gRPC是Google开发的一种跨语言、跨平台、可扩展的用于序列化数据协议。
2、HTTP效率
HTTP1.0:每个请求都需要与服务器建立一个新的TCP连接,并且在请求完成后立即关闭连接。这意味着如果需要发送多个请求,就需要建立多个TCP连接,这会增加网络开销和延迟。尽管HTTP1.0默认使用无连接,但通过在请求头中设置Connection字段为Keep-Alive,可以保持TCP连接不断开,从而减少网络开销和延迟。
HTTP1.1 Pipeline(顺序):默认支持长连接,允许在同一个TCP连接中发送多个请求和接收多个响应,但是在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送(管道化技术)。这直接导致了TCP资源的闲置。虽然服务器仍然需要按照请求的顺序发送响应,但管道化技术可以减少网络延迟和提高传输效率。
HTTP2.0Duplexing (谁快谁先):提出了流的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的请求。基于流的概念,进一步提出了 帧 ,一个请求的数据会被分成多个帧,方便进行数据分割传输,每个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二 进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不用再同时建多个连接,提升了TCP的利用效率。
gRPC采用HTTP2.0,相对于HTTP1.0 在更快的传输 和更低的成本两个目标上做了改进。有以下几个基本点:
HTTP2 未改变HTTP的语义(如GET/POST等),只是在传输上做了优化。
引入帧、流的概念,在TCP连接中,可以区分出多个request/response。
一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗。
引入二进制编码,降低header带来的空间占用。
三、gPRC四种模式
1、一元RPC模式
一元 RPC 模式也被称为简单 RPC 模式。在该模式中,当客户端调用服务器端的远程方法时,客户端发送请求至服务器端并获得一个响应,与响应一起发送的还有状态细节以及 trailer 元数据。
2、服务器端流RPC模式
在一元 RPC 模式中,gRPC 服务器端和 gRPC 客户端在通信时始终只有一个请求和一个响应。在服务器端流 RPC 模式中,服务器端在接收到客户端的请求消息后,会发回一个响应的序列。这种多个响应所组成的序列也被称为"流"。在将所有的服务器端响应发送完毕之后,服务器端会以 trailer 元数据的形式将其状态发送给客户端,从而标记流的结束。
比如我们搜索一块地方的全部旅游景点,我们发送一个请求,那么会返回多个旅游景点。
3、客户端流RPC模式
在客户端流 RPC 模式中,客户端会发送多个请求给服务器端,而不再是单个请求。服务器端则会发送一个响应给客户端。但是,服务器端不一定要等到从客户端接收到所有消息后才发送响应。基于这样的逻 辑,我们可以在接收到流中的一条消息或几条消息之后就发送响应,也可以在读取完流中的所有消息之后再发送响应。
客户端流RPC模式,适用于客户端需要连续发送大量数据的场景。
4、双向流RPC模式
在双向流 RPC 模式中,客户端以消息流的形式发送请求到服务器端,服务器端也以消息流的形式进行响应。调用必须由客户端发起,但在此之后,通信完全基于 gRPC 客户端和服务器端的应用程序逻辑。
本期gRPC的基础讲解完毕,后面我会出gRPC同步和异步的代码讲解。0voice · GitHub