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