玩转gRPC—深入概念与原理

简介: 玩转gRPC—深入概念与原理

本篇文章属于一篇知识的捡漏和复盘类的文章,主要目的就是为了复盘一下gRPC的相关概念,并剖析其原理,相关知识点和使用大家可以参看之前的几篇文章:

以上的几篇文章都不同程度的讲述和RPC协议相关知识和Google开源的RPC框架gRPC的相关知识,但是可能都比较浅显和不成体系,因此想利用这篇文章系统深入的讲述下gRPC,下面开始:

1 使用gRPC的基本架构

网络异常,图片无法展示
|


由上图我们可以看出,使用gRPC通信的基本架构中基本分为五部分,他们分别是:

  • Service:提供的服务
  • Client:gRPC客户端
  • gRPC Server:gRPC服务端接口
  • gRPC Stub:gRPC客户端接口
  • Proto Request/Proto Response(s) :中间文件(代码/协议)

2 Protocol Buffers

2.1 什么是Protocol Buffers?

Protocol Buffers,是Google公司开发的一种数据描述语言,简称protobuf。

特点

  • 支持多种编程语言
  • 序列化数据体积小
  • 反序列化速度快
  • 序列化和反序列化代码自动生成

2.2 Protocol Buffers和gRPC什么关系?

首先要说明的是gRPC是RPC协议是一种实现,是一个框架;Protocol Buffers,是Google公司开发的一种数据描述语言。

gRPC和Protocol Buffers的关系就好比浏览器和HTML的关系,不相互依赖,但是需要相互配合使用,才能达到最好的效果。

2.3 Protocol Buffers基本语法

Protocol Buffers是一个带有.proto扩展名的普通文本文件。

协议缓冲区数据被构造为消息,其中每条消息都是一个小的信息逻辑记录,包含一系列称为字段的键值对。这是一个简单的例子:

message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}
复制代码

一旦你指定了你的数据结构,你就可以使用协议缓冲区编译器protoc从你的原型定义中以你喜欢的语言生成数据访问类。这些为每个字段提供了简单的访问器,例如name()and set_name(),以及将整个结构序列化/解析到原始字节的方法。

在普通的 proto 文件中定义 gRPC 服务,将 RPC 方法参数和返回类型指定为协议缓冲区消息

// The greeter 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;
}
复制代码

gRPC 使用protoc特殊的 gRPC 插件从 proto 文件生成代码:将获得生成的 gRPC 客户端和服务器代码,以及用于填充、序列化和检索消息类型的常规协议缓冲区代码。

3 gRPC的四种服务提供方法

3.1 Unary RPC

一元 RPC,其中客户端向服务器发送单个请求并获得单个响应,就像正常的函数调用一样。

rpc SayHello(HelloRequest) returns (HelloResponse);
复制代码

3.2 Server streaming RPC

服务器流式 RPC,其中客户端向服务器发送请求并获取流以读回一系列消息。客户端从返回的流中读取,直到没有更多消息为止。gRPC 保证单个 RPC 调用中的消息顺序。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
复制代码

3.3 Client streaming RPC

客户端流式 RPC,其中客户端写入一系列消息并将它们发送到服务器,再次使用提供的流。一旦客户端完成了消息的写入,它就会等待服务器读取它们并返回它的响应。gRPC 再次保证了单个 RPC 调用中的消息顺序。

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
复制代码

3.4 Bidirectional streaming RPC

双向流式 RPC,双方使用读写流发送一系列消息。这两个流独立运行,因此客户端和服务器可以按照他们喜欢的任何顺序读取和写入:例如,服务器可以在写入响应之前等待接收所有客户端消息,或者它可以交替读取消息然后写入消息,或其他一些读取和写入的组合。保留每个流中消息的顺序。

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse)
复制代码

4 gRPC的生命周期

网络异常,图片无法展示
|


4.1 服务的提供

RPC服务的提供主要包括以上四种服务提供方法。

4.2 截止日期/超时

gRPC 允许客户端指定在 RPC 因错误而终止之前,他们愿意等待 RPC 完成多长时间DEADLINE_EXCEEDED。在服务器端,服务器可以查询特定的 RPC 是否已超时,或者还剩多少时间来完成 RPC。

指定期限或超时是特定于语言的:一些语言 API 根据超时工作,而一些语言 API 根据期限工作。

4.3 RPC 终止

在 gRPC 中,客户端和服务器都对调用是否成功做出独立的本地判断,并且它们的结论可能不匹配。这意味着,例如,可能有一个 RPC 在服务器端成功完成但在客户端失败。服务器也可以在客户端发送所有请求之前决定完成。

4.4 取消 RPC

客户端或服务器都可以随时取消 RPC。取消会立即终止 RPC,以便不再进行任何工作。

5 gRPC通信原理

众所周知,gRPC是基于HTTP2的,而HTTP2又是一个相对HTTP1.1比较新的概念,因此在探究gRPC原理之前有必要先了解下HTTP2是怎样的。

5.1 HTTP2

  • HTTP/2 的规范于 2015 年5 月发布,旨在解决其前身的一些可扩展性问题,在许多方面改进了 HTTP/1.1 的设计,最重要的是提供了连接上的语义映射。
    创建 HTTP 连接的开销很大。您必须建立 TCP 连接、使用 TLS 保护该连接、交换标头和设置等。HTTP/1.1 通过将连接视为长期存在的、可重用的对象来简化此过程。HTTP/1.1 连接保持空闲,以便可以通过现有的空闲连接发送到同一目的地的新请求。虽然连接重用缓解了这个问题,但一个连接一次只能处理一个请求——它们是 1:1 耦合的。如果要发送一条大消息,新请求必须要么等待它完成(导致 队列阻塞),要么更频繁地为启动另一个连接付出代价。
  • HTTP/2 通过在连接之上提供一个语义层:,从而进一步扩展了持久连接的概念。流可以被认为是一系列语义连接的消息,称为 。流可能是短暂的,例如请求用户状态的一元流(在 HTTP/1.1 中,这可能等同于 GET /users/1234/status)。随着频率的增加,它的寿命很长。接收者可能会建立一个长期存在的流,从而实时连续接收用户状态消息,而不是向 /users/1234/status 端点发出单独的请求。流的主要优点是连接并发,即在单个连接上交错消息的能力。
  • 流量控制
    然而,并发流包含一些微妙的陷阱。考虑以下情况:同一连接上的两个流 A 和 B。流 A 接收大量数据,远远超过它在短时间内可以处理的数据。最终,接收者的缓冲区被填满,TCP 接收窗口限制了发送者。这对于 TCP 来说都是相当标准的行为,但这种情况对于流来说是不利的,因为两个流都不会接收更多数据。理想情况下,流 B 应该不受流 A 的缓慢处理的影响。
    HTTP/2 通过提供 流控制 机制作为流规范的一部分来解决这个问题。流控制用于限制每个流(和每个连接)的未完成数据量。它作为一个信用系统运行,其中接收方分配一定的“预算”,发送方“花费”该预算。更具体地说,接收方分配一些缓冲区大小(“预算”),发送方通过发送数据填充(“花费”)缓冲区。接收方使用特殊用途的WINDOW_UPDATE帧向发送方通告可用的额外缓冲区 . 当接收方停止广播额外的缓冲区时,发送方必须在缓冲区(其“预算”)耗尽时停止发送消息。
    使用流控制,并发流可以保证独立的缓冲区分配。 再加上轮询请求发送,所有大小、处理速度和持续时间的流都可以在单个连接上进行多路复用,而无需关心跨流问题。
  • 更智能的代理
    HTTP/2 的并发属性允许代理具有更高的性能。例如,考虑一个接受和转发尖峰流量的 HTTP/1.1 负载平衡器:当出现尖峰时,代理会启动更多连接来处理负载或将请求排队。前者——新连接——通常是首选(在某种程度上);这些新连接的缺点不仅在于等待系统调用和套接字的时间,还在于在 发生TCP 慢启动时未充分利用连接所花费的时间。
    相比之下,考虑一个配置为每个连接多路复用 100 个流的 HTTP/2 代理。一些请求的峰值仍然会导致新的连接被启动,但与 HTTP/1.1 对应的连接数相比只有 1/100 个连接。更笼统地说:如果 n 个 HTTP/1.1 请求发送到一个代理,则 n 个 HTTP/1.1 请求必须出去;每个请求都是一个有意义的数据请求/有效负载,请求是 1:1 的连接。相反,使用 HTTP/2 发送到代理的 n请求需要n 个,但 不需要n 个 连接!

5.2 gRPC与HTTP2

gRPC 引入了三个新概念:通道、远程过程调用 (RPC) 和消息。三者之间的关系很简单:每个通道可能有很多 RPC,而每个 RPC 可能有很多消息。

网络异常,图片无法展示
|


通道是 gRPC 中的一个关键概念。HTTP/2 中的流支持在单个连接上进行多个并发会话通道通过在多个并发连接上启用多个流来扩展这个概念。 从表面上看,频道为用户发送消息提供了一个简单的界面;然而,在引擎盖下,大量的工程投入到保持这些连接的活力、健康和利用上。

通道代表到端点的虚拟连接,实际上可能由许多 HTTP/2 连接支持。RPC 与连接相关联(此关联将在后面进一步描述)。RPC 实际上是普通的 HTTP/2 流。消息与 RPC 相关联并作为 HTTP/2 数据帧发送。更具体地说,消息是在数据帧之上分层的。 一个数据帧可能有很多 gRPC 消息,或者如果一个 gRPC 消息非常大它可能跨越多个数据帧。

6 总结

好了,到这里关于gRPC的讲解就差不多了,归根结底,gRPC是一个网络协议,既然是网络协议就难逃网络I/O,因此也正是I/O多路复用成就了HTTP2,进而成就了gRPC,下一篇文章,让我们深入浅出网络I/O模型!

参考文章:

www.cncf.io/blog/2018/0…

grpc.io/blog/grpc-o…


相关文章
|
3月前
|
机器学习/深度学习 存储 缓存
129_量化技术:INT8与动态量化 - 推导压缩的精度损失公式
在2025年的大语言模型(LLM)时代,随着模型规模的指数级增长,部署这些庞然大物变得越来越具有挑战性。GPT-5和Claude 3等最新模型的参数量已经达到数千亿甚至上万亿,这给计算资源和内存带来了巨大压力。模型量化作为一种有效的压缩技术,正在成为解决这一挑战的关键方案。本文将深入探讨LLM量化技术,特别是INT8和动态量化方法,推导其精度损失公式,并提供2025年最新的优化策略和实现代码。
|
8月前
|
Web App开发 编解码 数据可视化
实时云渲染:数字孪生可视化最稳定省心的方案
数字孪生技术发展面临大内容与轻终端的矛盾,实时云渲染成为解决这一问题的关键。它支持大规模复杂数据处理、低延迟交互、跨终端访问、高精度可视化及弹性扩展,同时保障数据安全。平行云Lark XR作为企业级实时云渲染PaaS平台,相比Epic Games UE引擎的像素流送插件,提供更稳定、兼容性强、功能全面的解决方案,适用于工业数字孪生、云游戏、元宇宙活动等场景,助力企业专注于业务创新。
|
自然语言处理 调度 决策智能
Coconut:基于连续潜在空间推理,提升大语言模型推理能力的新方法
Coconut提出了一种新的大语言模型推理范式,通过在潜在空间中运算,利用隐藏层生成的连续思维状态取代传统文本推理。该方法采用广度优先搜索探索多条路径,避免单一路径局限,显著提升逻辑任务性能并减少token消耗。 Coconut结合“语言模式”和“潜在模式”动态切换,通过多阶段课程学习优化推理能力,在复杂规划任务中表现卓越,尤其在GSM8k和ProsQA等任务中优于传统模型。实验表明,Coconut能有效捕获中间变量,减少幻觉错误,具备更强的推理规划能力。
565 2
Coconut:基于连续潜在空间推理,提升大语言模型推理能力的新方法
|
消息中间件 Kafka API
Django中如何配置kafka消息队列
Django中如何配置kafka消息队列
385 0
|
SQL 监控 Oracle
|
机器学习/深度学习 数据采集 人工智能
循环神经网络RNN
7月更文挑战第2天
549 11
|
Rust 安全 C++
游戏引擎的未来:是Rust成为新王,还是C++仍占鳌头?
【8月更文挑战第31天】随着游戏行业的快速发展,对高性能、安全且易维护的游戏引擎需求日益增长。虽然C++长期占据主导地位,但Rust语言凭借其内存安全和高性能的特点,逐渐成为游戏引擎开发的新选择。Rust通过所有权机制和强大的类型系统,在保证内存安全的同时实现了与C++相当的性能,有助于提前发现潜在错误。尽管Rust在生态系统成熟度和学习曲线上仍面临挑战,其在游戏引擎领域的潜力正逐渐被认可。随着Rust社区的发展和工具链的完善,Rust有望成为游戏引擎开发的重要选项。
662 0
|
SQL 存储 API
实时计算 Flink版产品使用合集之多个任务合并一个宽表该怎么操作
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
311 0
|
JSON 缓存 Java
ProtoBuf-gRPC实践
gRPC 是一个高性能、开源、通用的 RPC 框架,基于 HTTP/2 设计,使用 Protocol Buffers(ProtoBuf)作为序列化协议。ProtoBuf 允许定义服务接口和消息类型,编译器会生成客户端和服务器端的代码,简化了跨平台的通信。 **gRPC 学习背景** 1. **为什么要学gRPC**:提高网络通信效率,支持多平台、多语言,提供高效序列化和反序列化,以及可靠的安全性和流控。 2. **RPC是什么**:远程过程调用,允许一个程序调用另一个不在同一设备上的程序。 3. **网络库收益分析**:gRPC 提供高效、安全、易用的网
976 0
|
算法
数学建模——曲线拟合
数学建模——曲线拟合
1490 1

热门文章

最新文章