关于java:漫谈gRPCGoogle自研的rpc框架到底有什么神秘之处

30次阅读

共计 5639 个字符,预计需要花费 15 分钟才能阅读完成。

​原文链接:https://mp.weixin.qq.com/s/ah…

 

本文概括性的介绍 gRPC,包含 gRPC 的起源,外围个性,生态体系,以及一些出名开源软件对 gRPC 的应用,最初总结 gRPC 与 netty、dubbo 等框架的区别,目标是让读者从整体上对 gRPC 有一个绝对全面的认知。

1 gRPC 起源

十多年来,Google 始终在应用一个名为 Stubby 的通用 RPC 基础架构来连贯在数据中心外部和逾越数据中心运行的大量微服务,其外部零碎长期以来始终承受微服务架构的遍及。

领有对立的跨平台 RPC 基础架构,能够在整个零碎范畴内推广效率,安全性,可靠性和行为剖析,这对于反对 Google 的惊人增长至关重要。咱们明天应用的每个 Google 服务背地的 RPC 骨干都是 Stubby。

Stubby 有许多很棒的性能 – 然而,它不是基于任何规范,而是与 Google 的外部基础设施严密耦合,并不适宜公开公布。

随着 SPDY,HTTP / 2 和 QUIC 的呈现,许多这些雷同的性能曾经呈现在公共规范中,以及 Stubby 未提供的其余性能。很显著,是时候重做 Stubby 以利用这种标准化,并将其适用范围扩大到分布式计算的最初一英里,反对挪动设施(如安卓)、物联网(IOT)、和浏览器连贯到后端服务。

2015 年 3 月,Google 决定在公开场合构建下一版 Stubby,以便与业界分享教训,并进行相干单干,为 Google 外部以及外界的微服务构建下一版本的 Stubby,也就是本文要介绍的配角 gRPC。

2 gRPC 介绍     

gRPC 是一个古代的开源高性能 RPC 框架,能够在任何环境中运行。它能够无效地连贯数据中心内和跨数据中心的服务,并提供可插拔的反对,以实现负载平衡 (load balancing),调用链追踪(tracing),健康检查(health checking) 和身份验证(authentication)。它还实用于分布式计算的最初一英里,用于将设施,挪动应用程序和浏览器连贯到后端服务。

gRPC 的四个外围个性,使得其对开发者有着极大的吸引力:

  • 简略的服务定义
  • 跨平台跨语言
  • 基于 http/ 2 双向流传输
  • 可插拔的插件机制

2.1 服务定义    

与许多 RPC 零碎相似,gRPC 也是基于以下理念:定义一个服务,指定其可能被近程调用的办法(蕴含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来解决客户端调用。在客户端领有一个存根(Stub),它提供与服务器雷同的办法。客户端利用能够像调用本地对象一样间接调用另一台不同的机器上服务端利用的办法,其背地会通过 RPC 通信给服务端发送申请,并取得响应。如下图:

要实现这样的性能,咱们首先要进行服务定义(Service Definition),一些框架中,将定义服务的语法称之为 IDL(Interface Definition Language,接口定义语言)。

gRPC 默认应用 Protocol Buffer 进行服务定义,这是 Google 开源的一套成熟的构造数据序列化机制(当然也能够应用其余数据格式如 JSON)。

目前 Protocol Buffer 曾经倒退到 proto3,绝对于 proto2,它领有轻量简化的语法、一些有用的新性能,并且反对更多新语言。通常倡议在 gRPC 里应用 proto3,因为这样你能够应用 gRPC 反对全副范畴的的语言,并且能防止 proto2 客户端与 proto3 服务端交互时呈现的兼容性问题,反之亦然。

应用 Protocol Buffer 进行服务定义十分简单明了,咱们能够创立一个.proto 文件,依照 Protocol Buffer 语法编写此文件,如:

        阐明如下:

  1. 定义一个示意申请的 HelloRequest,其蕴含一个 message 字段示意申请内容
  2. 定义一个示意响应的 HelloResponse,其蕴含一个 message 字段示意响应内容
  3. 定义服务 HelloService,其提供一个 hello 办法,以 HelloRequest 作为办法参数,并返回 HelloResponse

思考为什么要在一个文件中进行服务定义?

这次要是为了跨语言。gRPC 提供了工具,能够依据服务定义文件,来为不同的平台和语言生成 server 端和 client 端的代码,意味着你的服务端和客户端,能够应用不同的语言。例如,笔者最近开发的一个服务,服务端应用 go 编写,客户端须要反对 go、python、java。此时笔者就能够依据这个配置文件,别离生成不同语言的代码。

2.2 跨语言跨平台工作    

gRPC 提供了工具,能够为不同的平台、语言,生成对应的 client 和 server 代码,使得彼此之间能够通过 gRPC 进行通信。

通常一个规模较大的公司,技术栈往往不对立,可能会应用多种语言。通过 gRPC,服务端咱们能够应用一种语言编写,而客户端能够反对多种语言。

下图演示了服务端应用 C ++,客户端应用 Java 和 Ruby 的交互案例:

截止笔者撰写此文(2019 年 6 月 28 日),官网反对 10 种语言,以及 linux、mac、windows 三种平台,具体如下:

2.3 插件机制  

grpc 提供了可插拔的插件机制,或者说是拦截器机制,以对每一次 RPC 申请进行拦挡。基于此,咱们能够实现一些 RPC 通信过程中的高级性能。如:

身份验证:

gRPC 内置了两种验证机制,基于连贯层面的 SSL/TLS,以及基于 Google Token 的身份认证机制。如果不满足需要,你也很容易的进行扩大本人验证机制。

负载平衡:

在微服务架构中,为了实现容灾、高可用或者程度扩大等目标,通常一个服务都会部署多个节点。客户端在调用时,尽量的将申请扩散在不同的节点上,以实现负载平衡。通常负载平衡有两种模式:1)通过代理,即申请先发送给一个两头代理服务器,例如 nginx,由代理依照负载平衡策略抉择一个后端节点进行解决;2) 客户端路由:客户端依照负载平衡抉择某个后端服务节点,进行调用。gRPC 提供了一套欠缺的机制,反对客户端发现服务端有哪些节点,以及自定义负载平衡策略。

健康检查:

健康检查用于探测服务端是否能够解决 RPC 申请。查看查看能够由客户端间接发动,或者通过其余零碎(如 consul)。服务端能够抉择回复”unhealthy” 来表明本人还没筹备好解决申请,或者服务端曾经宕机。客户端依据服务端回复的响应信息,或者指定工夫内是否收到响应,来判断服务端是否衰弱。

2.4 基于 HTTP/ 2 双向流传输    

gRPC 基于 HTTP/2 规范设计,带来诸如双向流、流控、头部压缩、单 TCP 连贯上的多复用申请等特。这些个性使得其在挪动设施上体现更好,更省电和节俭空间占用。

gRPC 利用 HTTP/ 2 进行音讯传输,然而其只是自身定义了 HTTP2 中的传输单元中帧 (Frame) 的格局。至于 HTTP/ 2 协定自身的解析,gRPC 尽量复用已有的组件。例如,在 Java 中,Netty 自身反对 HTTP/ 2 协定协定,因而 gRPC 默认是反对与 netty 进行整合的。又或者,如果你心愿挪动设施(如安卓),能够间接与服务端进行交互,那么在安卓客户端,你能够抉择将 gRPC 与 okHttp 进行整合。

3 gRPC 生态体系

        gRPC 有着丰盛的生态系统,这些组件是由不是官网提供。以下介绍局部组件:

  • grpc-opentracing
  • grpc-gateway
  • grpc-prometheus
  • 其余组件

3.1 grpc-opentracing

在 RPC 调用过程中,可能会呈现 A 调动 B,B 又调用 C 等状况,此时咱们心愿对残缺的调用链路进行追踪。

grpc 生态系统中有一个 grpc-opentracing 组件,咱们能够应用其对接 zipkin,进行调用链路展现,查看整个调用链路中每个环节的耗时,以发现零碎的瓶颈。下

图起源自 zipkin 官网,咱们能够看到链路追踪的最终展现成果:

3.2 grpc-promethus

grpc-prometheus 来对 gRPC 服务进行监控,并将监控数据存储到 prometheus 中。

目前有 2 种语言的实现:

  • java-grpc-prometheus
  • go-grpc-prometheus

监控指标服务端与客户端别离统计,统计的指标包含:发动了多少个申请,接管到了多少个响应,响应提早等。

3.3 grpc-gateway

gRPC 曾经反对了绝大部分支流语言,对于一些小众语言可能不反对,此时你能够应用 grpc-gateway 来进行反向代理。

grpc-gateway 实质是一个 protoc 插件,咱们在编写 gRPC 服务定义 proto 文件,通过指定一些自定义选项,在编译时,在生成 gRPC 代码时,额定指定生成 grpc-gateway 反向代理相干代码,其作用是将 RESTful JSON API 申请转换为 gRPC 申请。

之后,咱们对反向代理代码进行革新,对于不反对 gRPC 的语言,让其发送 HTTP RESTful JSON 申请,通过反向代理将其转换成 grpc 申请,下图演示了其工作原理:

3.4 其余反对

上述提到的几个组件 gRPC 生态体系中的组件,围绕着 gRPC 来开发的。一些其余的驰名开源软件,如 nginx、haproxy 等,也提供了对 gRPC 的反对。

3.4.1 nginx 对 gRPC 的反对

nginx 从 1.13.10 开始提供对 grpc 的反对,client 端和 server 端都能够应用 gRPC 实现,通过 nginx 进行代理,如下图:

nginx 应用 grpc_pass 指令代理流量。上面的 nginx 代理配置,演示了在端口 80 上侦听未加密的 gRPC 流量并将申请转发到端口 50051 上的服务器。

更残缺的介绍和配置,点击这里:

https://www.nginx.com/blog/ng…

3.4.2 HAProxy 对 gRPC 的反对

HAProxy 从 1.9.2 增加了对 gRPC 的反对。残缺介绍,点击以下链接:

https://www.haproxy.com/blog/…

4 gRPC 应用案例

很多出名公司或者机构目前都应用了 gRPC,这些公司对 gRPC 的应用,自身就证实了其弱小稳固与牢靠。官网列出有以下这些:

这些公司别离在各自的产品中应用了 gRPC,上面介绍 etcd 和 tidb。

4.1 etcd 案例

etcd 是一个牢靠的分布式 k / v 存储,利用 Raft 一致性算法,用于存储分布式系统的最要害数据,应用 Go 语言编写,k8s 应用了 etcd 来存储数据。

etcd v3 应用 gRPC 作为它的音讯协定。etcd 我的项目包含基于 gRPC 的 Go client 和 命令行工具 etcdctl,通过 gRPC 和 etcd 集群通信。另外,对于 gRPC 不反对的语言,etcd v3 通过 grpc-gateway(回顾前文)予以反对。

4.2 tidb 案例

TiDB 是 PingCAP 公司设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,联合了传统的 RDBMS 和 NoSQL 的最佳个性。TiDB 兼容 MySQL,反对有限的程度扩大,具备强一致性和高可用性。

TiDB 集群次要包含三个外围组件:TiDB ServerPD Server 和 TiKV Server。此外,还有用于解决用户简单 OLAP 需要的 TiSpark 组件。这些组件之间也应用 gRPC 来交互,如下图:

图片起源自网络

对于 tidb 与 gRPC 的渊源,参考这里(故事比拟波折):

https://blog.csdn.net/weixin_…

5 gRPC 性能

之所以有这么多厂商应用 gRPC,除了其自身的设计,丰盛的生态体系,与其高性能也有着极大的关系。

gRPC 专为分布式应用的高性能和高生产率设计而设计。继续性能基准测试是 gRPC 开发工作流程的要害局部。目前 gRPC 会针对 master 分支每小时运行一次多语言性能测试,并将这些数字报告给仪表板以进行可视化。

测试场景

  • 无争用提早 – 只有 1 个客户端应用 StreamingCall 一次发送一条音讯时看到的中位数和尾部响应提早
  • QPS – 当有 2 个客户端和总共 64 个通道时的音讯 / 秒速率,每个通道应用 StreamingCall 一次发送 100 个未实现的音讯
  • 可伸缩性(实用于所选语言)– 每个服务器外围的音讯数 / 秒

下图演示了第二个测试场景下的测试 qps:

能够看到,应用 go 和 java 时,qps 靠近 240w/ s 这个惊人的数字。当然,千万不能齐全置信这个数字,qps 受到网络、音讯大小、机器配置等多种因素的综合影响。理论应用还是须要自行测试。

6 总结

本文概括性的介绍 gRPC,包含 gRPC 的起源,外围个性,生态体系,以及一些出名开源软件对 gRPC 的应用,目标是让读者从整体上对 gRPC 有一个绝对全面的认知。

补充:gRPC 与 netty、dubbo 等框架的区别

netty 实质上是一个高性能的网路通信框架,且局限于 Java 语言。gRPC 则不同,则是面向微服务设计的,netty 能够作为 gRPC 的底层通信框架,gRPC 自身还反对很多微服务中的概念,如后面提到的服务发现注册,链路追踪等。

与其余微服务框架如 dubbo、spring cloud 等,gRPC 不局限于某一种语言,而是简直所有支流语言。

另外一个很大的不同是,gRPC 不是采纳公有协定,而是基于规范的 HTTP/ 2 实现,这意味着可能会有更多的厂商应用或者反对 gRPC,如果后面提到的 nginx、etcd 等。这体现了遵循规范的重要性,试想,如果想要 nginx 反对 dubbo,或者 etcd 来应用 dubbo,简直是不可能的事件。

设计者的思路,间接决定了一门技术到底可能有多宽泛的应用场景


微信公众号【程序员黄小斜】作者是前蚂蚁金服 Java 工程师,专一分享 Java 技术干货和求职成长心得,不限于 BAT 面试,算法、计算机根底、数据库、分布式、spring 全家桶、微服务、高并发、JVM、Docker 容器,ELK、大数据等。关注后回复【book】支付精选 20 本 Java 面试必备精品电子书。

正文完
 0