https://www.cnblogs.com/charlieroro/p/14570214.html
最近一段时间关于GraphQL的讨论很多,一些项目中也相继用到了这种风格,但使用是否合理,是否存在杀鸡用牛刀这样的问题,还有待商榷。
译自:Comparing API Architectural Styles: SOAP vs REST vs GraphQL vs RPC
两个不同的应用需要一个中间程序才能互通,开发者通常会使用应用程序接口(API)进行搭桥,使一个系统能够访问另一个系统的信息或功能。
为了在扩容时快速集成应用,实际的API会使用协议或规范来定义消息传递的语义和语法。这些规范构成了API架构。
过去几年曾出现了几种不同的API架构风格,每种风格都有其特定的标准数据交互模式。而对API架构的选择引起了无休止的讨论。
现在,很多API用户放弃REST,并拥抱GraphQL。而在十年之前,对于REST来说则是相反的情况,在于SOAP的竞争中,REST大获全胜。这种观念的问题在于用于单方面去选择一个技术,而没有考虑实际价值以及以与特定场景的匹配度。
本文将会按照API风格出现的顺序对它们进行讨论,对比各自的优劣势,并给出各自适合的场景。
RPC是一个规范,它允许在一个不同的上下文中远程执行功能。RPC将本地程序调用扩展到了HTTP API的上下文中(RPC的最上层大部分都是HTTP)。
一开始的XML-RPC问题比较多,它很难保证XML载体的数据类型。后来出现了一个基于JSON-RPC的RPC API,由于JSON的规范更加具体,因此被认为是SOAP的替代品。 gRPC是一个谷歌在2015年开发的全新RPC版本,插件化支持负载均衡、跟踪、健康检查以及身份认证等,gRPC非常适用于微服务间的通信。
客户端唤醒远端程序,序列化参数,并在消息中添加额外的信息,然后将消息发送给服务端。在接收到客户端的消息后,服务端会反序列化消息中的内容,执行请求的操作,并将结果返回给客户端。服务端存根(stub)和客户端存根(stub)负责参数的序列化和反序列化。
与底层系统的强耦合:API的抽象程度与其可复用性相关。与底层系统的耦合越高,API的可复用性就越低。RPC与底层系统的强耦合使其无法在系统和外部API之间进行抽象,同时也增加了安全风险,很容易在API中泄露底层系统的实现细节。RPC的强耦合使其很难实现需求扩展和团队解耦,客户要么会担心调用特定后端可能带来的副作用(如安全问题),要么会因为无法理解服务端的功能命名规则而不知道调用哪个后端。
这里说的"与底层系统"的耦合,并不是说与内核等底层实现之间的耦合,而是与底层服务的耦合,如与日志服务,鉴权服务等耦合。
可发现性低:RPC无法对API进行自省或无法通过发送的RPC请求来理解其调用的功能。
应该是RPC并没有像REST API那样相对严格的调用规范,因此有些调用会比较难以理解
功能爆炸:由于很容易添加新的功能,因此相比编辑现有的功能,新增的功能可能会导致大量功能重叠,也很难去理解。
RPC模式始于80年代,但它一直没有过时。像Google,Facebook (Apache Thrift)和Twitch(Twirp) 这样的大型公司利用RPC的高性能特性来获得高性能、低开销的消息处理能力(规模庞大的微服务使用短消息进行通信,需要保证通信的畅通)。
SOAP是一种XML格式的,高度标准化的web通信协议。在XML-RPC面世一年之后,Microsoft发布了SOAP,SOAP继承了XML-RPC的很多特性。而后出现了REST,二者并驾齐驱,但很快REST就后来居上。
XML数据格式多种多样,加上大量消息结构,使得SOAP称为一种最冗长的API样式。
一个SOAP消息包含:
SOAP API的逻辑是用Web服务描述语言(WSDL)编写的,该API描述语言定义了后端并描述了可执行的流程。它允许使用不同的编程语言和IDEs快速配置通信。
SOAP同时支持有状态和无状态消息。在有状态场景中,服务端会保存接收到的信息,该过程可能比较繁重,但对于涉及多方和复杂交易的操作来说是合理的。
如今,由于多种原因,很多开发人员对必须集成SOAP API的想法感到不安。
目前,SOAP架构大部分用于内部集成企业或其他可信任的伙伴。
REST是一个自解释的、由一组架构约束定义的API架构风格,并被很多API使用者广泛采用。
作为当今最通用的API风格,它最初出现在2000年的Roy Fielding 的博士论文中。REST使用简单格式(通常是JSON和XML)来表达服务侧的数据。
REST没有像SOAP那样严格。RESTful架构应该遵循以下六个架构约束:
实际上,某些服务仅在一定程度上是RESTful的,而核心使用了RPC风格,将大型服务分割成多个资源,并有效地利用HTTP基础设施。但关键部分使用的是超媒体(又称HATEOAS,Hypertext As The Engine of Application State),意味着对于每个响应,REST API提供了如何使用API的所有元数据信息。REST使用这种方式来解耦客户端和服务端,这样,API提供者和消费者就可以独立演进,且不会妨碍它们的通信。
Richardson Maturity Model as a goalpost to achieving truly complete and useful APIs, Source: Kristopher Sandoval
"HATEOAS 是REST的关键特性,这也是REST之所以称为REST的原因。但由于很多人并不使用HATEOAS,导致他们实际上用的是HTTP RPC",这是Reddit上的一些激进意见。确实,HATEOAS是最成熟的REST版本,但很难实现比通常使用和构建的API客户端更加高级和智能的API客户端。因此,即使是如今非常好的REST API也不能保证面面俱到。这也是为什么HATEOAS主要作为RESTful API设计的长期开发愿景。
REST和RPC之间有一些灰色区域,特别是当一个服务具有一部分REST特性,一部分RPC特性时。REST基于资源,而不是基于动作或动词。
在REST中,会用到像GET, POST, PUT, DELETE, OPTIONS, PATCH这样的HTTP方法。
它需要多次调用REST API才能返回所需的内容。 因此,GraphQL被认为是一种改变API规则的风格。
GraphQL 的语法描述了如何发起精确的数据请求。GraphQL适合那些相互之间具有复杂实体引用关系的应用数据模型。
现在,GraphQL生态扩展了相关的库,并出现了很多强大的工具,如Apollo, GraphiQL, and GraphQL Explorer。
一开始,GraphQL会创建一个schema(模式),它描述了在一个GraphQL API中的所有请求以及这些请求返回的所有types。构建模式会比较困难,它需要使用模式定义语言(DSL)进行强类型输入。
由于在请求前已经构建好了模式,因此客户端可以对请求进行校验,确保服务器能够进行响应。在到达后端应用后,会有一个GraphQL操作,负责使用前端应用的数据来解析整个模式。在给服务端发送包含大量查询的请求之后,API会返回一个JSON响应,内容正对应请求的资源。
除RESTful CRUD操作外,GraphQL还有订阅功能,允许接收服务端的实时通知。
类型化的模式:GraphQL 会提前发布它可以做的事情,这种方式提升了可发现性。通过将客户端指向GraphQL API,我们可以知道哪些查询是可用的。
非常适合类似图形的数据:适合深度关联的数据,不适合扁平数据。
没有版本控制:最好的版本控制就是不对API进行版本控制。
REST提供了多种API版本,而GraphQL是一种单一的、演化的版本,可以持续访问新的特性,方便服务端代码的维护。
详细的错误消息:与SOAP类似,GraphQL提供了详细的错误信息,错误信息包括所有的解析器以及特定的查询错误。
灵活的权限:GraphQL允许在暴露特定的功能的同时保留隐私信息。而REST架构不能部分展示数据(要么全部显示,要么全部隐藏)。
每种API项目都有不同的要求,通常基于如下几点进行选择:
在了解到每种API设计风格之后,API设计者就可以根据项目的需要选择最合适的API模式。
由于强耦合特性,RPC通常用于内部微服务间的通信,不适用于外部API或API服务。
SOAP比较麻烦,但它本身丰富的安全特性仍然是交易操作、订单系统和支付等场景的不二之选。
REST具有高度抽象以及最佳的API模型。但往往会增加线路和聊天的负担--如果使用的是移动设备,这是不利的一面。
在获取数据方面,GraphQL迈出了一大步,但并不是所有人都有足够的时间和精力来处理这种模式。
归根结底,最好在一些小场景下尝试每种API风格,然后看是否满足需求,是否能够解决问题。如果可以,则可以尝试扩展到更多的场景。
本文来自博客园,作者:charlieroro,转载请注明原文链接:https://www.cnblogs.com/charlieroro/p/14570214.html