经过长时间关于API设计的讨论。 当API 不基于RPC时,我想尝试一个明确的答案。
围绕这个Is That REST API Really RPC? Roy Fielding Seems to Think So
似乎有点混乱该特定链接是关于REST和RPC的。我的问题只是为了询问RPC与非RPC,而不是在HTTP的上下文中。
TLDR;定义何时API IS RPC "当它隐藏开发人员的网络时#34; 很公平。
但回到什么时候不是。
Twitter的讨论集中在HttpClient上,因为它不是RPC。
我的论点是HttpClient并没有真正模拟网络。 建模延迟中没有任何内容。 网络故障的表现也很弱。 HTTP中的大多数状态代码与网络无关,例如NotFound,需要付款等。
根据语言和SDK,HttpClient可能会采用字符串或URI。 如果它采用表示URI的字符串,也没有真正传达有涉及的网络,则需要知道字符串表示的内容以及URI是什么。
如果您之前从未见过HTTP,那么通过查看特定的API您会怎么知道? 有一个消耗字符串的API,并返回一个包含字符串或一些int响应代码的对象。
你怎么知道?
大多数开发人员当然知道HTTP是什么,但从严格定义的角度来看,你如何将API定义为不是RPC?
在Java" NetworkException"中是否会检查异常是否足以明确表示涉及网络? 如果您调用的函数具有描述性名称,例如" SayHelloOverNetwork"那会不足以使它不是RPC?
到底什么时候程序是一个远程程序? 所有网络通信都将导致某些代码在接收系统上运行。
如果我们选择一个从未接触过技术或协议的人,并教给这个人一种编程语言。 什么是"非RPC"的定义?这个人可以用来发现什么是RPC而不是?
我在这里很密集,可能很傻,但我试图找到"不是RPC"的精华,到底需要什么?
例如,它是否需要非阻塞才能以未知的延迟播放? 或者非RPC API可以阻止吗? IMO,如果它是阻塞的,它会隐藏所涉及的延迟,因此属于"延迟为零"谬误,意味着它隐藏了网络。
除了我之外,这对所有人来说似乎都是非常明显的,但是还没有人对未成为RPC的要求有一个简明的答案。
答案 0 :(得分:1)
对我而言,看起来你将所有鸡蛋放入一个篮子里。让我们从一开始就开始:
API 是application programming interface
它是一组明确定义的各种软件组件之间的通信方法
API的唯一最终属性是定义/记录的沟通方式。
如果一个应用程序/模块/组件A可以某种方式使用/调用另一个应用程序/模块/组件B - 这意味着B提供API而A使用此API。
通常,必须定义API的两个方面:
我没有触及"什么"部分原因很明显。
让我们专注于"如何":
的不同方式在所有这些情况下,您都在使用某些API =您以某种预定义的方式与其他组件进行通信。
计算机程序使程序(子程序)在另一个地址空间中执行
RPC的唯一权威属性是数据通过不同/远程地址空间传递,某些体系结构允许单个主机上的不同地址空间,例如x86。一旦不同的物理主机通常不共享地址空间,跨网络的任何呼叫都是RPC,但反之亦然。
注意:很少见,但可以在网络中连接的不同物理主机之间共享内存空间 - 那么严格来说这种通信不是RPC,让我们省略这种情况。
任何RPC调用都会自动表示您正在调用某些API。根据定义。所以我们可以说 RPC是API的一部分"" ,它是传输级别。一旦RPC本身没有定义实际机制,就会有很多不同的实现,例如共享内存,DMA,TCP / IP等。
我想现在您可以回答您的问题when an API is not RPC based
- 当API这样说时。由API开发人员决定是否应该通过RPC调用它,API可以定义多种调用方式。
作为RPC的反义词,您可以使用"进程中"。
因此,短语API IS RPC is "when it hides the network from the developer"
绝对没有意义。 API必须定义"如何"部分。
HTTP 是hyper text transfer protocol
客户端 - 服务器计算模型中的请求 - 响应协议
HTTP的唯一确定属性是它描述了请求(输入参数)和响应的协议/格式。
您可以在非RPC API中使用HTTP。例如,我更喜欢将HTTP视为文件格式。我们可以说 HTTP是API"" 的另一部分。它定义了API的序列化部分,但没有规定您的传输级别。
注意:某些RPC协议实际上定义了传输和序列化。
因此, HttpClient是允许您调用API并使用HTTP编码的请求/响应的工具,通常这样的库将RPC设为传输级别。这些术语都不要求网络或任何特定的传输协议。这就是为什么http客户端不应声明任何类型的网络异常/错误,但它可能会将HTTP错误作为异常抛出。
注意:可能会从TCP / IP RPC实现中抛出网络异常,例如,HTTP客户端库可以将它们代理给您。不幸的是,有些库错误地将HTTP与TCP / IP结合起来,并且跨越了不同职责之间的界限。
REST 是representational state transfer
分布式超媒体系统的架构风格
这是一个非常广泛的术语,它从不同方面和不同层面定义了很多东西,最重要的是:
客户端 - 服务器通常假定跨进程通信。即不同的地址空间,这就是为什么我们可以说 REST要求RPC 作为API + HTTP的调用机制作为序列化格式。
现在,我想你将能够理解这些答案:
你怎么知道?
当您向客户端提供REST API时,它会根据其他协议自动定义API的某些部分。即 - 要使用REST API,您必须首先阅读/了解HTTP协议。 API必须定义必须使用哪种RPC。
HttpClient并不真正为网络建模。
不应该这样做。它适用于HTTP语义。
你需要知道字符串代表什么,并且需要一个URI
实际上有两个URI:
如果您呼叫的功能具有描述性名称,例如" SayHelloOverNetwork"那会不足以使它不是RPC?
正如我之前写的那样 - 我们可以将网络视为RPC。
例如,它是否需要非阻塞才能以未知的延迟播放?
由API开发人员负责:
答案 1 :(得分:0)
RPC是一种网络API,顶部有足够的抽象层。什么足够的图层?这是一个主观的事情。
在我看来,API是否是RPC并不依赖于方法名称或您需要处理的异常/错误的名称。我们是成年人,我们知道通过网络进行通话。命名它" SayHello"而不是" SayHelloOverNetwork"并没有什么不同。
所有这些抽象层都有所不同 - 您需要做的资源管理和错误处理越少,代码就越多。
关于特定的HttpClient示例 - 我今天说,开展高级工作的开发人员认为HTTP是一种传输媒介;替换"普通旧插座"。
因此,当一个不知道HTTP是什么的人可能会看到"一个接受字符串并返回错误代码的函数"作为RPC,现代开发人员可能会将其视为"细节网络代码"。然后他会说 yuck ,并在顶部放置一些抽象层,以使其业务逻辑的方法调用更具有RPC-ish。这样,业务逻辑就必须只处理最极端的故障。
答案 2 :(得分:0)
A)如果文档告诉您如何通过调用API来执行所需操作,那么您将调用类似RPC的API,而不是REST API。
B)如果API本身告诉你如何调用它来完成你想要的东西,那么那个API就不像RPC那样,可能是一个REST API。
面向对象或程序样式的编程就像是案例(A) - 你知道在调用代码之前调用它以及如何调用它来完成你想要的东西。当[我假设Roy F.]说类似RPC的API隐藏了开发人员的网络时,他意味着开发人员可以继续以这种方式编程,无论他的电话是否是远程的 - 他没有关心网络。
但是,当您调用REST API时,您必须采用不同的编程方式,因为您必须让API告诉您可以执行的操作以及如何执行操作。这就是"超文本驱动"。
超文本驱动意味着当网络另一端的人根本不知道或不关心你的程序时,你的东西会继续工作,完全改变你可以做的事情以及你如何做必须这样做。请注意,您与所呼叫的系统之间缺少任何合同是RPC隐藏的网络的基本功能。