【进程间通信IPC之RPC】技术演化:RPC-SOAP-REST-gRPC/Thrift/GraphQL

进程间通信技术演化

  • 传统的RPC
  • SOAP
  • REST
  • gRPC的起源
    • gRPC的优势
    • gRPC的劣势
  • Thrift
    • Thrift vs gRPC
  • GraphQL
    • GraphQL vs gRPC

传统的RPC

借助RPC(Remote Procedure Communication),客户端能够像调用本地方法那样远程调用某个方法的功能。早期一些很流行的RPC实现,比如通用对象请求代理体系结构(common object request broke architecture, CORBA)和Java远程方法调用(remote method invocation,RMI),他们都用来构建和连接服务或应用程序。


但是,大多数传统RPC的实现极其复杂,因为它们构建在TCP这样的通信协议之上,而这会妨碍互操作性,并且他们还有大量的规范限制,于是有了SOAP。

SOAP

简单对象访问协议(simple object access protocol, SOAP)是面向服务的架构(service-oriented architecture,SOA)的标准通信技术。用于在服务之间交换XML结构化数据,并且能够基于任意的底层通信协议进行通信,其中最常用的协议就是HTTP。


但是,消息格式复杂,规范复杂,妨碍分布式应用程序的敏捷性,于是有了REST架构风格。

REST

描述性状态迁移(representational state transfer,REST)架构风格起源于Roy Fielding的博士论文。Fielding是HTTP规范的主要作者之一,也是REST架构风格的创始人。REST是面向资源的架构(resource-oriented architecture,ROA)的基础,在这种架构中,需要将分布式应用程序建模为资源集合,访问这些资源的客户端可以变更这些资源的状态(创建、读取、更新或删除)。亦即:通过HTTP,将RESTful Web应用程序建模为能够通过唯一标识符访问的资源集合。应用于资源的状态变更 操作会采用HTTP动词(GET、POST、PUT、DELETE、PATCH等)的形式,资源的状态会以文本的格式来表述,如JSON、XML、HTML、YAML等。实际上,通过HTTP和JSON将应用程序构建为REST架构风格已成为构建微服务的标准方法。


但是,随着微服务的数量及其网络交互的激增,RESTful服务已经无法满足现代化的需求了。

  • 基于文本的低效消息协议
    RESTful服务建立在基于文本的传输协议(HTTP 1.x)上,并且会使用人类可读的格式,如JSON。但是服务与服务之间通信并不需要可读,这种格式很低效。其实可以用二进制内容来代替,采用JSON格式主要是他“人类可读”。这涉及工具选择问题,而不是二进制协议问题。

  • 应用程序之间缺乏强类型接口
    对于服务使用完全不同的语言来构建,缺乏明确定义和强类型的服务接口成了RESTful服务的主要障碍RESTful中现有的各种服务定义技术(如OpenAPI/Swagger等)都是事后的补救措施,并没有与底层的架构风格或消息协议紧密集成在一起。
    在构建这种分散的应用程序时,会遇到很多不兼容、运行时错误和互操作等问题。【REST风格结构不共享服务定义和类型定义,但在开发RESTful应用程序时就需要通过网络查看文本格式或者使用第三方API定义技术(如OpenAPI)】因此,现在非常重要的任务就是拥有现代化的强类型服务定义技术以及框架,从而为多语言技术生成核心的服务器端代码和客户端代码。

  • REST架构风格难以强制实施
    REST架构风格有很多“好的实践”,只有遵行这些实践才能构建出真正的RESTful服务。但是他们并没有作为实现协议(如HTTP)的一部分进行强制的要求。因此在实现阶段,这些实践很难实施。事实上大多数自称RESTful的服务并没有遵循基础的REST架构风格,也就是说, 这些所谓的RESTful服务不过是通过网络公开的HTTP服务 。开发团队必须花费大量时间来维护RESTful服务的一致性和纯度。

鉴于进程间通信技术在构建现代云原生应用程序时所存在的这些限制,人们开始寻求更好的消息协议。

gRPC的起源

长期以来,谷歌有一个名为Stubby的通用RPC框架,用来连接成千上万的微服务,这些微服务跨多个数据中心并且使用完全不同的技术来构建。Stubby的核心PRC层每秒能处理数百亿次的互联网请求。Stubby有许多很棒的特性,但无法标准化为业界通用的框架,因为它与谷歌内部的基础设施耦合得过于紧密。

2015年谷歌发布了开源PRC框架gRPC,这个RPC基础设施具有标准化、可通用和跨平台得特点,旨在提供类似Stubby的可扩展性、性能和功能,但它主要面向社区。

在此之后,gRPC的受欢迎程度陡增,很多大型公司大规模采用了gRPC,如Netflix、Square、Lyft、Docker、CoreOS和思科。解这gRPC加入了云原生计算基金会(Cloud Native Computing Foundation, CNCF),这是最受欢迎的开源软件基金会之一,他致力于让云原生计算具备通用性和可持续性。

gRPC的优势

  • 提供高效的进程间通信
    gRPC没有使用JSON或XML这样的文本化格式,而是使用一个基于protocol buffers的二进制协议与gRPC服务和客户端通信。 同时gRPC在HTTP/2之上实现了protocol buffers,从而能够更快地处理进程间通信。这样一来,gRPC就变成了最高效的进程间通信技术之一。
  • 有简单且定义良好的服务接口和模式
    gRPC为应用程序开发提供了一种契约优先的方式。也就是说,首先必须定义服务接口,然后才能去处理实现细节。
  • 属于强类型
    使用protocol buffers来定义gRPC服务,所以gRPC服务契约清晰定义了应用程序间进行通信所使用的类型。这样一来,在构建跨多个团队和技术类型的云原生应用程序时,对于其所产生的大多数运行时错误和互操作错误,可以通过静态类型来克服,因此分布式应用程序的开发更加稳定。
  • 支持多语言
    gRPC支持多种编程语言,基于protocol buffers的服务定义是语言中立的。因此我们可以选择任意一种语言,它们都能与现有的gRPC服务或客户端进行互操作。
    【任意一种语言:只要你使用的框架最终可以注册到注册中心进而部署到云上,截至目前,最受欢迎的无非是Java的SpringCloud、Dubbo,Go的Kratos,Python的nameko(Django、Flask也可以,可参考链接),有些冷门的语言和框架支持就很差了可以看看这个支不支持。当然如果不需要上云当我没说,爱用啥框架用啥】
  • 支持双工流
    gRPC在客户端和服务端都提供了对流的原生支持,这些功能都被整合到了服务定义本身之中。因此,开发流服务或流客户端变得非常容易。与传统的RESTful服务消息风格相比,gRPC的关键优势就是能够同时构建传统的请求-响应风格的消息以及客户端流和服务端流
  • 具备内置的商业化特性
    gRPC提供了对商业化特性的内置支持,如认证、加密、弹性(截止时间和超时)、元数据交换、压缩、负载均衡、服务发现等。
  • 与云原生生态系统进行了集成
    gRPC是CNCF的一部分,大多数现代框架和技术对gRPC提供了原生支持。例如CNCF下的很多项目(如Envoy)支持使用gRPC作为通信协议。另外,对于横切性特性,比如度量指标和监控,gRPC也得到了大多数工具的支持,比如使用Prometheus来监控gRPC应用程序。
  • 业已成熟并被广泛采用
    通过在谷歌进行的大量实战测试,gRPC已发展成熟,前面提到的许多大型科技公司采用了gRPC。

gRPC的劣势

  • gRPC可能不太适合面向外部的服务
  • 大多数外部消费者对gRPC、REST或HTTP等协议很陌生, 因此如果希望将应用程序或服务通过互联网暴露给外部客户端,gRPC可能不是最适合的协议。gRPC服务具有契约驱动、强类型的特点,这可能会限制我们向外不暴露的服务的灵活性。同时消费者的控制权会削弱很多。
  • 巨大的服务定义变更时复杂的开发流程
    在现代的服务间通信场景,模式修改很常见。如果出现巨大的gRPC服务定义变更,通常需要重新生成客户端代码和服务端代码。这需要整合到现有的持续集成过程中,可能会让整个开发生命周期复杂化。【深有同感,仅仅是在proto文件里改变service或者message一点点,改个类型或者加个变量,后续需要改的内容就有不少,不过这也是契约驱动、强类型不可避免的┭┮﹏┭┮,所以最好在一开始就确定好服务定义】
  • gRPC生态相对较小
    当然是相对于REST或HTTP等协议而言,现在正常使用完全没问题。

Thrift

Apache Thrift是与gRPC类似的RPC框架,最初由Facebook开发,后来被捐赠给了Apache。他有自己的接口定义语言并提供了对多种编程语言的支持。Thrift可以在定义文件中定义数据类型和服务接口。Thrift编译器以服务定义作为输入,能够生成客户端代码和服务器端代码。Thrift的传输层为网络I/O提供了抽象,并将Thrift从系统的其他组成部分中解耦出来,这意味着Thrift可以在任意传输实现上运行,如TCP、HTTP等。

Thrift vs gRPC

  • 传输方面
    相对于Thrift,gRPC的倾向性更强,它为HTTP/2提供了一流的支持。gRPC基于HTTP/2的实现充分利用了该协议的功能,从而实现了高效率并且能够支持像流这样的消息模式。
  • 流方面
    gRPC服务定义原生支持双向流(客户端和服务器端),它本身便是服务定义的一部分。
  • 采用情况和社区资源方面
    采用情况上,gRPC石头似乎更好,社区资源也非常丰富。采用gRPC会更顺利一点。
  • 性能方面
    没有对比的官方结果,但一些在线资源对比了性能,Thrift的数据表现更好。但gRPC的绝大多数发布版本经过了大量的性能测试,所以性能不太成为选Thrift不选gRPC的决定性因素。【换句话说,gRPC小小地赢在了“营销”上。技术选型自行决定需量身定制(●’◡’●)】

GraphQL

GraphQL是另一项越来越流行的进程间通信技术,该项目由Facebook发起并通过开源进行了标准化。它是一门针对API的查询语言,并且是基于既有数据满足这些查询的运行时。GraphQL为传统的客户端-服务器端通信提供了一种完全不同的方法,该方法允许客户端定义希望获得的数据、获取方式、数据格式。

GraphQL更适合面向外部的服务或API,直接暴露给消费者。在这种情况下,消费者需要对来自服务器端的数据有更多的控制权。允许消费者使用GrapheQL查询语言来查询服务并获取想要的信息。

GraphQL vs gRPC

  • GrapheQL的消费者有更多的数据控制权
    可以自行决定获得的数据、方式、格式
    gRPC则是针对远程方法特定契约【有点面向契约编程的意思】
  • 使用场景
    GraphQL用于面向外部的服务或API;支撑API的内部适合使用gRPC,原因之一是GrapheQL的消费者有更多的数据控制权。

你可能感兴趣的:(笔记,rpc,graphql,网络协议)