gRPC
简介
gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。
HTTP2.0
grpc采用HTTP2.0,相对于HTTP1.0 在更快的传输和更低的成本两个目标上做了改进。有以下几个基本点:
- 引入帧、流的概念,在TCP连接中,可以区分出多个request/response
- 一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗
- 引入二进制编码,降低header带来的空间占用
HTTP1.1核心问题在于:在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送。这直接导致了TCP资源的闲置。
HTTP2为了解决这个问题,提出了流的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的请求。基于流的概念,进一步提出了帧,一个请求的数据会被分成多个帧,方便进行数据分割传输,每个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不用再同时建多个连接,提升了TCP的利用效率。
gRPC的异步通信
不管是 Client 还是 Server,异步 gRPC 都是利用 CompletionQueue API 进行异步操作。基本的流程:
- 绑定一个 CompletionQueue 到一个 RPC 调用
- 利用唯一的 void* Tag 进行读写
- 调用 CompletionQueue::Next() 等待操作完成,完成后通过唯一的 Tag 来判断对应什么请求/返
回进行后续操作
gRPC 的 CompletionQueue(CQ)是一个事件队列,用于处理 gRPC 异步操作的完成事件。它是 gRPC 实现异步通信的核心机制之一。
CompletionQueue 可以理解为一个事件循环,它会不断地从网络层接收到来自服务端的响应或客户端请求的完成事件,并将这些事件加入到队列中。在客户端代码或服务端代码中,我们可以通过异步 API 来向 CompletionQueue 注册我们感兴趣的事件,然后等待 CompletionQueue 返回这些事件的完成状态。
在客户端,我们可以通过 CompletionQueue 来实现异步的 gRPC 调用。当我们调用 gRPC 的异步 API 时,会向 CompletionQueue 注册一个请求完成事件。当服务端响应到达时,CompletionQueue 会将该事件放入队列中,并通知客户端代码请求已完成。此时客户端可以从 CompletionQueue 中取出该事件,获取响应数据,并进行后续处理。
在服务端,我们可以通过 CompletionQueue 来实现异步的 gRPC 处理。当服务端接收到客户端的请求时,会向 CompletionQueue 注册一个请求完成事件。当处理完成时,服务端将该事件放入队列中,并通知 CompletionQueue 请求已完成。此时服务端可以从 CompletionQueue 中取出该事件,获取请求数据,并进行后续处理。
总之,CompletionQueue 是 gRPC 实现异步通信的核心机制,它可以帮助我们实现高效、低延迟的 gRPC 应用程序。
grpc网络模型
grpc同步模型
grpc会启动多个线程的epoll来处理描述符,不管异步还是同步,每个epoll都对应一个线程。
其中监听scceptfd会被轮询地放在所有线程的epoll中,保证线程上的负载均衡。目前grpc的分配策略是轮询(round-robin)
grpc异步模型
异步处理的epoll方式和同步是类似的,但对于rpc函数的响应提供了更灵活的处理机制,可以将一些耗时的处理逻辑放到外部的线程池进行处理。
grpc四种模式
一元RPC模式
服务器 流RPC模式
客户端流RPC模式
双向流RPC模式