gRPC设计动机和原则

 

gRPC | Microsoft Docs https://docs.microsoft.com/zh-cn/dotnet/architecture/cloud-native/grpc

 

什么是 gRPC?

gRPC 是一种新式的高性能框架,它发展了由来已久的远程过程调用协议。 从应用程序层面来看,gRPC 简化了客户端和后端服务之间的消息传递。 gRPC 源自 Google,是云原生产品服务的云原生计算基础 (CNCF) 生态系统的一部分,并且是开放源代码的。 CNCF 将 gRPC 视为培育中的项目。 培育意味着最终用户会在生产应用程序中使用该技术,该项目有大量的贡献者。

典型的 gRPC 客户端应用将公开实现业务操作的本地进程内函数。 在此之下,该本地函数会在远程计算机上调用另一个函数。 看起来是本地调用,实际上变成了对远程服务的透明进程外调用。 RPC 管道对计算机之间点到点网络通信、序列化和执行进行抽象化。

在云原生应用程序中,开发人员在工作中通常会处理不同的编程语言、框架和技术。 这种互操作性使消息协定和跨平台通信所需的管道变得复杂。 gRPC 提供“统一水平层”来对此类问题进行抽象化。 开发人员在本机平台中编写专注于业务功能的代码,而 gRPC 会处理通信管道。

gRPC 在最常用的开发堆栈(包括 Java、JavaScript、C#、Go、Swift 和 NodeJS)中提供全面的支持。

gRPC 的优势

gRPC 使用 HTTP/2 作为传输协议。 虽然与 HTTP 1.1 也能兼容,但 HTTP/2 具有许多高级功能:

  • 用于数据传输的二进制组帧协议 - 与 HTTP 1.1 不同,HTTP 1.1 是基于文本的。
  • 对通过同一连接发送多个并行请求的多路复用支持 - HTTP 1.1 将处理限制为一次处理一个请求/响应消息。
  • 双向全双工通信,用于同时发送客户端请求和服务器响应。
  • 内置流式处理,支持对大型数据集进行异步流式处理的请求和响应。
  • 减少网络使用率的标头压缩。

gRPC 是轻量型且高性能的。 其处理速度可以比 JSON 序列化快 8 倍,消息小 60% 到 80%。 在 Microsoft Windows Communication Foundation (WCF) 中,gRPC 的性能超过经过高度优化的 NetTCP 绑定的速度和效率。 与偏向于 Microsoft 堆栈的 NetTCP 不同,gRPC 是跨平台的。

协议缓冲区

gRPC 采用名为协议缓冲区的开放源代码技术。 它们提供极为高效且不受平台影响的序列化格式,用于序列化服务相互发送的结构化消息。 开发人员使用跨平台接口定义语言 (IDL) 为每个微服务定义服务协定。 该协定作为基于文本的 .proto 文件实现,描述了每个服务的方法、输入和输出。 同一合同文件可用于基于不同开发平台构建的 gRPC 客户端和服务。

Protobuf 编译器 protoc 使用 proto 文件为目标平台生成客户端和服务代码。 该代码包括以下组成部分:

  • 由客户端和服务共享的强类型对象,表示消息的服务操作和数据元素。
  • 一个强类型基类,具有远程 gRPC 服务可以继承和扩展的所需网络管道。
  • 一个客户端存根,其中包含调用远程 gRPC 服务所需的管道。

运行时,每条消息都序列化为标准 Protobuf 表示形式,并在客户端和远程服务之间交换。 与 JSON 或 XML 不同,Protobuf 消息被序列化为经过编译的二进制字节。

Microsoft 体系结构站点提供的适用于 WCF 开发人员的 gRPC 一书深入介绍 gRPC 和协议缓冲区。

 

 

https://mp.weixin.qq.com/s/NMIIa0W722zo_AxCqASc0g

TiDB 与 gRPC 的那点事儿

黄东旭 PingCAP 2017-08-10
 

gRPC 背景介绍

其实做分布式系统那么久,几乎也是天天和 RPC 打交道,要说 各个模块是系统的筋肉,那 RPC 就是整个系统的血管,数据的流通,信令的传递,都离不开 RPC。

RPC 并不是一个固定的东西,可重可轻,重的如同 MS 的 DCOM,JAVA 的 EJB,轻的 HTTP 也可以说是 RPC,甚至自己写个 TCP 的文本通信协议也算。

大家也都知道 Google 内部其实没怎么用 gRPC,大量使用的是 Stubby,它作为 gRPC 的前身,也是一个 Protobuf RPC 的实现,因为大量依赖了 Google 的其他基础服务所以不太方便开放出来给社区使用。

随着 SPDY / QUIC,乃至 HTTP/2  的成熟,Google 决定用这些更加标准的组件来构建一个新的 RPC 框架,也就是 gRPC。不过这个项目过于庞大,而且 Google 内部 Stubby 已经用了超过 10 年,很难直接替换,毕竟程序员最烦的事情之一就是去改跑着好好的老代码。。。

不过 anyway,尽管 gRPC 没有在 Google 内部广泛使用,也是给社区带来了一个非常好的基础组件,现在为止包括 ETCD / Kubernetes / TiDB 在内的大量社区顶级开源分布式项目都在使用它。

为何选择 gRPC?

有人说,RPC 多简单啊,不就是一个长连接,Sender 和 Reciver 来回发包嘛,顶多再搞个服务发现做 Failover,搞得那么复杂为啥。另外要强大不是已经有 EJB 什么的嘛,gRPC 的意义何在?我想从官方的 gRPC 的设计动机和原则说起:

1、Google 应该是践行服务化的先驱之一,在业界没那么推崇微服务的时代,Google 就已经大规模的微服务化。

微服务的精髓之一就是服务之间传递的是可序列化消息,而不是对象和引用,这个思想是和 DCOM 及 EJB 完全相反的。只有数据,不包含逻辑;这个设计的好处不用我多说也很好理解,参考 CSP 。

2、Protobuf 作为一个良好的序列化方案,注意,只是 序列化(尽管 pb 也有定义 rpc service 的能力,Protobuf 默认生成的代码并不包含 RPC 的实现),它并不像 Thrift 天生就带一个 RPC Framework,相对的来说比较轻。

在 gRPC 的设计中,一个很重要的原则就是 Payload agnostic,RPC 框架不应该规定用的是什么 payload 格式,可以是 Protobuf,JSON,XML,这也让 gRPC 的设计和层次更加清晰。

3、比传统的 Request / Response 更丰富的 API Interface,这个是我们使用 gRPC 的重要理由,gRPC 不仅支持传统的一应一答的模式,更是支持三种 Streaming 的调用方式,现代的业务经常会需要传输大的数据流,Streaming API 的设计让这些业务写起来轻松很多。

4、有了 Streaming 就不可避免地需要引入 Flow-control ,这点 gRPC 的处理很聪明,直接依赖了 HTTP/2,在流控这边不怎么用操心,顺带还可以用 HTTP 反向代理做负载均衡。

但是另一方面也会带来更多的调优复杂度,毕竟和 Web 的使用场景不太一样,比如默认的 INITIAL_WINDOW_SIZE 在 gRPC 里是 64k,太小,吞吐上不去,需要人工改大。

5、另一方面由于直接使用了 HTTP/2,TLS 的支持就几乎是天然的,对于 TiDB 这样的商业数据库而言,传输层加密是一个很重要的功能,在 gRPC 中直接就可以支持。本着不重新造轮子的原则,直接用 gRPC 就好了。

 

https://mp.weixin.qq.com/s/nH4WG1lY56LvXATh_cvPVw

深度解析gRPC以及京东分布式服务框架跨语言实战

闫家宝 亿级流量网站架构 2017-02-22

gRPC设计动机和原则

最初由Louis Ryan在谷歌其他同事帮助下写成,如下文:

设计动机

十多年来,谷歌一直使用一个叫做Stubby的通用RPC基础框架,用它来连接在其数据中心内和跨数据中心运行的大量微服务。其内部系统早就接受了如今越来越流行的微服务架构。拥有一个统一的、跨平台的RPC的基础框架,使得服务的首次发行在效率、安全性、可靠性和行为分析上得到全面提升,这是支撑这一时期谷歌快速增长的关键。

 

Stubby有许多非常棒的特性,然而,它没有基于任何标准,而且与其内部的基础框架耦合得太紧密以至于被认为不适合公开发布。随着SPDY、HTTP/2和QUIC的到来,许多类似特性在公共标准中出现,并提供了Stubby不支持的其它功能。很明显,是时候利用这些标准来重写Stubby,并将其适用性扩展到移动、物联网和云场景。

 

设计原则

●  服务非对象、消息非引用 —— 促进微服务的系统间粗粒度消息交互设计理念,同时避免分布式对象的陷阱和分布式计算的谬误。

●  普遍并且简单 —— 该基础框架应该在任何流行的开发平台上适用,并且易于被个人在自己的平台上构建。它在CPU和内存有限的设备上也应该切实可行。

●  免费并且开源 —— 所有人可免费使用基本特性。以友好的许可协议开源方式发布所有交付件。

●  互通性 —— 该报文协议(Wire Protocol)必须遵循普通互联网基础框架。

●  通用并且高性能 —— 该框架应该适用于绝大多数用例场景,相比针对特定用例的框架,该框架只会牺牲一点性能。

●  分层的 —— 该框架的关键是必须能够独立演进。对报文格式(Wire Format)的修改不应该影响应用层。

●  负载无关的 —— 不同的服务需要使用不同的消息类型和编码,例如protocol buffers、JSON、XML和Thrift,协议上和实现上必须满足这样的诉求。类似地,对负载压缩的诉求也因应用场景和负载类型不同而不同,协议上应该支持可插拔的压缩机制。

●  流 —— 存储系统依赖于流和流控来传递大数据集。像语音转文本或股票代码等其它服务,依靠流表达时间相关的消息序列。

●  阻塞式和非阻塞式 —— 支持异步和同步处理在客户端和服务端间交互的消息序列。这是在某些平台上缩放和处理流的关键。

●  取消和超时 —— 有的操作可能会用时很长,客户端运行正常时,可以通过取消操作让服务端回收资源。当任务因果链被追踪时,取消可以级联。客户端可能会被告知调用超时,此时服务就可以根据客户端的需求来调整自己的行为。

● Lameducking —— 服务端必须支持优雅关闭,优雅关闭时拒绝新请求,但继续处理正在运行中的请求。

● 流控 —— 在客户端和服务端之间,计算能力和网络容量往往是不平衡的。流控可以更好的缓冲管理,以及保护系统免受来自异常活跃对端的拒绝服务(DOS)攻击。

● 可插拔的 —— 数据传输协议(Wire Protocol)只是功能完备API基础框架的一部分。大型分布式系统需要安全、健康检查、负载均衡和故障恢复、监控、跟踪、日志等。实   现上应该提供扩展点,以允许插入这些特性和默认实现。

● API扩展 —— 可能的话,在服务间协作的扩展应该最好使用接口扩展,而不是协议扩展。这种类型的扩展可以包括健康检查、服务内省、负载监测和负载均衡分配。

● 元数据交换 —— 常见的横切关注点,如认证或跟踪,依赖数据交换,但这不是服务公共接口中的一部分。部署依赖于他们将这些特性以不同速度演进到服务暴露的个别API的能力。

● 标准化状态码 —— 客户端通常以有限的方式响应API调用返回的错误。应该限制状态代码名字空间,使得这些错误处理决定更清晰。如果需要更丰富的特定域的状态,可以使用元数据交换机制来提供。

 

 

posted @ 2020-09-04 15:03  papering  阅读(464)  评论(0编辑  收藏  举报