我们知道两个独立的应用程序需要一个中介来相互通信。因此,开发人员经常构建桥梁(应用程序编程接口)以允许一个系统访问另一个系统的信息或功能。为了快速、大规模地集成应用程序,API是使用协议或规范来实现的,这些协议或规范定义了通过网络传递的消息的语义和语法。这些规范构成了API架构。随着时间的推移,已经发布了不同的API架构风格。每个都有自己的标准化数据交换模式,丰富的选择引发了关于哪种架构风格最好的争论。今天,许多API消费者称REST为“安息”并为GraphQL欢呼,而十年前情况恰恰相反,REST是取代SOAP的赢家。这些观点的问题在于他们选择了一种技术本身,而不是考虑它的实际属性和特征如何适应当前情况。在本文中,我们将保持客观的态度,讨论四大API风格的出现顺序,比较它们的优缺点,并强调它们最适合的场景。RemoteProcedureCall(RPC):在另一个系统上调用函数RemoteProcedureCall是一种允许在不同上下文中远程执行函数的规范。RPC扩展了本地过程调用的概念,但将其置于HTTPAPI的上下文中。最初的XML-RPC存在问题,因为很难确保XML负载的数据类型。因此,后来RPCAPI开始使用更具体的JSON-RPC规范,这被认为是SOAP的更简单替代方案。gRPC是谷歌在2015年开发的最新RPC版本,gRPC支持可插拔的负载均衡、跟踪、健康检查和身份验证,非常适合连接微服务。RPC的工作原理客户端调用远程过程,将参数和附加信息序列化为消息,然后将消息发送到服务器。服务器收到消息后,反序列化其内容,执行请求的操作,并将结果发送回客户端。服务器和客户端存根负责参数的序列化和反序列化。RPC的优点交互简单直接。RPC使用GET获取信息,使用POST获取其他信息。服务器和客户端之间的交互机制归结为调用端点并获得响应。易于添加功能。如果我们对API有新的需求,我们可以很容易地添加另一个端点来满足这个需求:在编写一个新函数并将其放入一个端点之后,现在客户端可以访问这个端点并获取设置的所需信息。高性能。轻量级负载很容易在提供高性能的网络上实现,这对于在工作站网络上执行的共享服务器和并行计算很重要。RPC可以优化网络层,每天在不同服务之间发送大量消息,效率很高。RPC的缺点与底层系统紧密耦合。API的抽象级别有助于其可重用性。它越接近底层系统,它对其他系统的可重用性就越差。RPC与底层系统的紧耦合不允许在系统中的函数和外部API之间存在抽象层,这会引发安全问题,因为很容易将底层系统的实现细节泄露到API中。RPC的紧耦合使得可伸缩性要求和松耦合的团队难以实现,因此客户端要么担心调用特定端点可能产生的任何副作用,要么试图弄清楚要调用哪个端点,因为它不了解服务器如何命名其功能。可发现性低。在RPC中,无法自省API或发送请求,也无法根据请求了解调用什么函数。功能爆炸。创建新功能很容易。因此,我们不是编辑现有功能,而是创建新功能,最终得到一堆难以理解的重叠功能。RPC用例RPC模式从80年代就出现了,但这并不会自动使它过时。Google、Facebook(ApacheThrift)和Twitch(Twirp)等大公司在内部使用RPC的高性能变体来执行高性能、低开销的消息传递。他们庞大的微服务系统要求在安排短消息时内部通信清晰。命令API。RPC是向远程系统发送命令的正确选择。比如Slack的API是非常命令化的,加入频道,离开频道,发消息。因此,SlackAPI的设计者将其建模为类似RPC的样式,使其小巧、紧凑且易于使用。用于内部微服务的特定于客户端的API。通过单个提供者和消费者之间的直接集成,我们不想像RESTAPI那样花费大量时间通过网络传输大量元数据。gRPC和Twirp具有高消息速率和消息性能,是微服务的有力案例。在HTTP2的支持下,gRPC可以优化网络层,每天在不同的服务之间发送大量的消息,非常高效。但是,如果您的目标不是高网络性能,而是发布高度独特的微服务的团队之间稳定的API连接,REST将确保这一点。简单对象访问协议(SOAP):使数据作为服务可用SOAP是一种XML格式的高度标准化的网络通信协议。SOAP在Microsoft发布XML-RPC一年后发布,它从中继承了很多东西。当REST紧随其后时,它们首先被并行使用,但很快REST赢得了人气竞赛。SOAP是如何工作的XML数据格式背后有很多形式化的东西,庞大的消息结构使SOAP成为最冗长的API风格。SOAP消息包括:包含请求或响应的文字标头(如果消息必须标识任何特定或附加要求),以及在整个请求处理过程中可能发生的任何错误的失败通知。SOAPAPI逻辑是用Web服务描述语言(WSDL)编写的。这种API描述语言定义了端点并描述了所有可执行的过程,使得不同的编程语言和IDE能够快速建立通信。SOAP支持有状态和无状态消息传递。在有状态的情况下,服务器存储接收到的信息可能非常繁重。但这对于涉及多方和复杂交易的操作来说是合理的。SOAP的优点是独立于语言和平台。用于创建基于Web的服务的内置功能允许SOAP处理通信并做出独立于语言和平台的响应。绑定到各种传输协议。SOAP在传输协议方面很灵活,可以适应很多情况。内置错误处理。SOAPAPI规范允许返回带有错误代码和解释的重试XML消息。许多安全扩展。SOAP与WS-Security协议集成后,可以满足企业级的事务质量。它在交易中提供隐私和完整性,同时允许在消息级别进行加密。SOAP缺点出于多种原因,如今许多开发人员对必须集成SOAPAPI的想法感到不安。仅限XML。SOAP消息包含大量元数据,仅支持请求和响应的详细XML结构。重量级。由于XML文件的大小,SOAP服务需要大量带宽。狭窄的专业知识。构建SOAPAPI服务器需要深入了解所有涉及的协议及其高度限制性规则。无聊的新闻更新。添加或删除消息属性需要额外的努力,而且严格的SOAP架构会减慢采用速度。SOAP用例如今,SOAP框架最常用于企业内部或与其信任的合作伙伴集成。高度安全的数据传输。SOAP严格的结构、安全性和授权能力使其成为执行API和客户端之间正式软件合同的最合适选择,同时遵守API提供者和API消费者之间的合法合同。这就是金融机构和其他商业用户选择SOAP的原因。REST:使数据作为资源可用REST是一种不言自明的API架构风格,由一组架构约束定义,旨在被许多API使用者广泛采用。当今最常见的API风格最初是由RoyFielding在2000年的博士论文中描述的。REST使服务器端数据能够以简单的格式表示,通常是JSON和XML。REST的工作原理REST的定义不像SOAP那样严格,RESTful架构应遵守六个架构约束。统一接口:允许以统一的方式与给定的服务器进行交互,而不管设备或应用程序类型如何。无状态:处理请求的必要状态,包含在请求本身,服务器不需要存储任何与会话相关的内容。缓存客户端-服务器架构:一个分层系统,允许任何一方独立发展应用程序它们的核心是RPC风格,将较大的服务分解为资源并有效地使用HTTP基础设施。但关键部分是使用超媒体akaHATEOAS,超文本作为应用程序状态引擎的缩写。基本上,这意味着对于每个响应,RESTAPI都会提供元数据链接到有关如何使用API的所有相关信息。这就是实现客户端和服务器的解耦。因此,API提供者和API消费者都可以独立发展,而不会阻碍他们的交流。“HATEOAS是REST的一个关键特性。这就是REST真正是REST的原因。因为大多数人没有使用HATEOAS,他们实际上使用的是HTTPRPC。”以下是在Reddit上表达的一些激进观点。事实上,HATEOAS是REST最成熟的版本。然而,实现这一目标需要比当今通常使用和构建的API客户端先进得多的智能API,这使得它变得困难。所以,现在即使是非常好的RESTAPI也不一定能做到这一点。这就是为什么HATEOAS主要用作RESTfulAPI设计的长期发展愿景。当一个服务实现了REST的一些特性和RPC的一些特性时,REST和RPC之间确实可能存在灰色地带。REST基于资源或名词,而不是动作或动词。在REST中,使用GET、POST、PUT、DELETE、OPTIONS和PATCH等HTTP方法来完成任务。REST的优势是将客户端和服务器解耦。尽可能的解耦client和server,REST可以实现比RPC更好的抽象。具有抽象级别的系统,封装其细节以更好地识别和维护其属性。这使得RESTAPI足够灵活,可以随着时间的推移而发展,同时保持一个稳定的系统。可发现性。客户端和服务器之间的通信描述了一切,因此不需要外部文档来了解如何与RESTAPI交互。缓存友好。许多HTTP工具被重用,REST是唯一允许在HTTP级别缓存数据的样式。相反,在任何其他API上实现缓存需要配置额外的缓存模块。支持多种格式。支持多种格式来存储和交换数据的能力是REST目前成为构建公共API的主流选择的原因之一。REST的缺点没有单独的REST结构。构建RESTAPI没有完全正确的方法。如何对资产建模,以及对哪些资源建模,将取决于每个场景。这使得REST在理论上很容易,但在实践中却很难。大负载。REST返回大量丰富的元数据,以便客户端可以仅从其响应中了解有关应用程序状态的所有必要信息。对于具有大量带宽容量的大型网络管道,这种丰富的元数据并不是什么大问题。但情况并非总是如此,它是Facebook在2012年引入GraphQL风格描述的关键驱动因素。过度获取和获取不足的问题。REST响应包含太多数据或数据不足,通常需要另一个请求。REST用例管理API。最常见的API类型是一种专注于管理系统中的对象并面向许多消费者的API。REST使此类API具有强大的可发现性和良好的文档记录,并且非常适合这种对象模型。简单的资源驱动应用程序。REST是连接不需要灵活查询的资源驱动应用程序的宝贵方式。GraphQL:发明GraphQL是为了改变游戏规则,因为只有需要的数据需要多次调用,才能将需要的信息返回给RESTAPI。GraphQL是一种描述如何进行精确数据请求的语法。对于具有大量相互引用的复杂实体的应用程序数据模型,实施GraphQL是值得的。如今,GraphQL生态系统正在扩展库和强大的工具,如Apollo、GraphiQL和GraphQLExplorer。GraphQL是如何工作的GraphQL从构建一个模式开始,它描述了您可能在GraphQLAPI中进行的所有查询以及它们返回的所有类型。构建模式很困难,因为它需要模式定义语言(SDL)中的强类型。在查询之前使用架构,客户端可以根据架构验证他们的查询以确保服务器将响应它。当到达后端应用程序时,GraphQL操作将针对整个模式进行解释,并使用来自前端应用程序的数据进行解析。API向服务器发送一个大型查询,返回一个JSON响应,其中包含我们请求的数据的确切形状。除了RESTfulCRUD操作之外,GraphQL还有一个订阅功能,可以从服务器获取实时通知。GraphQL受益于类型化模式。GraphQL预先宣布它可以做什么,这提高了它的可发现性。通过将客户端指向GraphQLAPI,我们可以发现进行了哪些查询。适用于类似图形的数据。数据关系很深,但不适合平面数据。没有版本控制。版本控制的最佳实践是根本不对API进行版本控制。REST提供多个API版本,而GraphQL使用单一的、不断发展的版本,它提供对新功能的持续访问,并有助于更清洁、更可维护的服务器代码。详细的错误信息。与SOAP类似,GraphQL提供了出错的详细信息。它的错误消息包括所有解析器并提及出错的查询的特定部分。灵活的权限。GraphQL允许在保留私有信息的同时有选择地公开某些功能。同时,REST架构不展示部分数据。全有或全无。GraphQL性能问题的劣势。GraphQL用复杂性换取了它的强大功能。一个请求中有太多嵌套字段会使系统超载。所以,对于复杂的查询,REST仍然是更好的选择。缓存很复杂。由于GraphQL不重用HTTP缓存语义,因此需要自定义缓存工作。大量的前期发展教育。由于没有足够的时间了解GraphQL和SDL的小众操作,许多项目决定采用众所周知的REST方法。GraphQL用例移动设备API。在这种情况下,网络性能和单个消息的有效载荷优化很重要。因此,GraphQL为移动设备提供了更高效的数据加载。复杂系统和微服务。GraphQL将集成多个系统的复杂性隐藏在其API背后。它聚合来自多个地方的数据,然后将它们合并到一个全局模式中。这对于遗留基础架构或随时间扩展的第三方API尤其重要。哪种API模式最适合您的用例?每个API项目都有不同的要求和需要。通常,体系结构的选择取决于:所使用的编程语言、您正在开发的环境以及您拥有的资源,包括人力和财力。了解每种设计风格的所有权衡后,API设计人员可以选择最适合项目的风格。凭借其紧密耦合,RPC非常适合内部微服务,但对于健壮的外部API或API服务来说并不是一个好的选择。SOAP虽然笨重,但其丰富的安全功能对于计费业务、预订系统、支付等仍然是不可替代的。REST具有API的最高抽象和最佳建模。但这往往会增加在线和聊天的负担——如果您使用的是移动设备,这将是一个不利因素。GraphQL在数据抓取方面向前迈进了一大步,但并不是每个人都有时间和精力去掌握它。归根结底,尝试一些具有特定风格的小用例以查看它是否适合您的用例并解决您的问题是有意义的。如果是,请尝试扩展它以查看它是否适合更多用例。
