Cloudflare官方
25-10-24 18:05 微博认证:Cloudflare官方微博

Cap'n Web:用于浏览器和 Web 服务器的新 RPC 系统

通过本篇文章,让我们向您介绍 Cap’n Web,这是一个基于纯 TypeScript 实现的 RPC 协议和实现。

Cap'n Web 与 Cap'n Proto 堪称精神同源,后者是在 10 年前创建的 RPC 协议,但其设计初衷是为了在 Web 栈中良好运行。这意味着:

·与 Cap'n Proto 类似,它(Cap'n Web)是一种对象能力协议。(“Cap'n”是“capabilities and”的缩写。)我们将在下文详细介绍,它的功能非常强大。
·与 Cap'n Proto 不同,Cap'n Web 没有模式。事实上,它几乎没有任何模板代码。这意味着它的工作方式更像是 Cloudflare Workers 中的 JavaScript 原生 RPC 系统。
·尽管如此,它与 TypeScript 集成得很好。
·与 Cap'n Proto 不同,Cap'n Web 的底层序列化是人类可读的。实际上,它只是经过少量预处理/后处理的 JSON。
·它原生支持 HTTP、WebSocket 和 postMessage(),并且可以轻松扩展到其他传输协议。
·它可以在所有主流浏览器、Cloudflare Workers、Node.js 和其他现代 JavaScript 运行时中运行。
·整个内容压缩 (minify+gzip) 至 10 kB 以下,且无任何依赖关系。
·它是基于 MIT 许可的开源软件。

Cap'n Web 比几乎所有其他 RPC 系统都更具表现力,因为它实现了对象能力 RPC 模型。这意味着它:
·支持双向调用。客户端可以调用服务器,服务器也可以调用客户端。
·支持通过引用传递函数:当您通过 RPC 调用传递一个函数时,接收方会收到一个“存根”。·当其调用这个存根时,实际上会向您发起一次反向 RPC,从而在您最初定义该函数的地方执行它。这就是双向调用的实现原理:客户端向服务端传递一个回调函数,之后服务端可以在任意时刻调用它。
·类似地,支持通过引用传递对象:如果一个类扩展了特殊标记类型 RpcTarget,那么该类的实例将通过引用传递,方法调用将回调到创建对象的位置。
·支持 Promise 流水线。启动 RPC 时,会返回一个 Promise。无需等待,您可以立即在依赖的 RPC 中使用该 Promise,从而在一次网络往返中执行一系列调用。
·支持基于能力的安全性模式。

简而言之,Cap'n Web 允许您以设计常规 JavaScript API 的方式设计 RPC 接口,同时依然能正视网络延迟问题并加以优化。

最棒的是,Cap'n Web 的设置极其简单。

客户端看起来像这样:
图2
下面是一个实现了 RPC 服务器的完整 Cloudflare Worker:
图3

就是这样,应用就此完成。
·您可以向 MyApiServer 添加更多方法,并从客户端调用它们。
·您可以让客户端将回调函数传递给服务器,然后服务器可以直接调用它。
·您可以为您的 API 定义一个 TypeScript 接口,并轻松地将其应用到客户端和服务器。
它非常有效。

为什么使用 RPC 以及 RPC 到底是什么?
远程过程调用 (Remote Procedure Calls - RPC) 是一种通过网络在两个程序之间进行通信的方式。如果没有 RPC,您可能使用 HTTP 之类的协议进行通信。但是,如果使用 HTTP,您必须将通信格式化并解析为 HTTP 请求和响应,这或许可以采用 REST 风格设计。RPC 系统试图使通信看起来像常规的函数调用,就好像您是在调用库而不是远程服务一样。RPC 系统在客户端提供了一个“存根”对象,它代表真正的服务器端对象。当在存根上调用方法时,RPC 系统会确定如何序列化参数并将其传输到服务器,在服务器上调用该方法,然后将返回值传回。

RPC 的优点一直是争论的焦点。它常被指责犯下了诸多分布式计算谬误。

但这类说辞已经过时了。大约 40 年前 RPC 刚刚发明时,异步编程几乎不存在。我们还没有 Promise,更不用说 async 和 await 了。早期的 RPC 是同步的:每次调用都会阻塞调用线程,等待回复返回。在最好的情况下,延迟会使程序变慢。在最坏的情况下,网络故障会导致程序挂起或崩溃 - 这就不奇怪它会被认为是“不完善的”。

如今情况大不相同。我们有 Promise、async 和 await,并且可以在网络故障时抛出异常。我们甚至了解 RPC 是如何实现流水线化的,这样一连串调用只需要一次网络往返。您每天可能使用的许多大型分布式系统都是基于 RPC 构建的。它确实有效。

事实是,RPC 契合我们早已习惯的编程思维模式。每位程序员都被训练成以函数调用构成的 API 来思考问题,而非以字节流协议甚至 REST 的方式。使用 RPC 能让您摆脱在不同心智模型之间频繁切换的困扰,从而提升开发效率。

何时应该使用 Cap'n Web?
Cap'n Web 适用于任何两个 JavaScript 应用程序通过网络相互通信的情况,包括客户端到服务器以及微服务到微服务的场景。然而,它尤其适合具有实时协作功能的交互式 Web 应用程序,以及在复杂的安全边界上进行交互建模。

Cap’n Web 目前仍处于早期阶段,属于实验性项目,因此现阶段您可能也需要有拥抱前沿技术的勇气!

功能,功能,功能……
以下是使用 Cap’n Web 可能实现的更多功能。

HTTP 批处理模式
有时,WebSocket 连接显得有些过于重量级。如果您只是想快速发起一批一次性调用,而不需要维持一个持续连接,那该怎么办呢?

为此,Cap'n Web 支持 HTTP 批处理模式:
图4
(服务器与之前完全相同。)

请注意,一旦您在某个批次中 await 了一个 RPC 调用,该批次就结束了,通过该批次获得的所有远程引用都会失效。若要继续发起更多调用,您需要重新开始一个新的批次。不过,您可以在单个批次中发起多个调用。

图5
这就引出了另一个功能……
链式调用(Promise 流水线)

下面是见证奇迹的时刻。
在批处理模式和 WebSocket 模式下,您都可以进行依赖于另一个调用结果的调用,而无需等待第一个调用完成。在批处理模式下,这意味着您可以在单个批处理中调用一个方法,然后在另一个调用中使用其结果。整个批处理仍然只需要一次网络往返。

例如,假设您的 API 为:
图6
您可以这样写:
图7

请注意,对 getMyName() 的初始调用返回了一个 Promise,但我们直接使用该 Promise 本身作为 hello() 的输入,而没有先等待它。使用 Cap'n Web,这就可以正常工作:客户端向服务器发送一条消息,内容为:“请将第一次调用的结果插入到第二次调用的参数中。”
或者,第一次调用可能返回一个包含方法的对象。您可以立即调用这些方法,无需等待第一个 Promise,例如:
图8

之所以有效,是因为 Cap'n Web 调用返回的 Promise 并非常规的 Promise。相反,它是一个 JavaScript 代理对象。您对其调用的任何方法都会被解释为对最终结果的推测性方法调用。这些调用会立即发送到服务器,告诉服务器:“当你完成我之前发送的调用后,请对其返回的结果调用此方法。”

您发现其中的安全机制了吗?
最后一个例子展示了 Cap'n Web 的对象能力模型所支持的一个重要安全模式。

当我们调用 authenticate() 方法时,在验证了提供的 API 密钥后,它会返回一个经过身份验证的会话对象。客户端可以对该会话对象进行进一步的 RPC 调用,以执行需要以该用户身份授权的操作。服务器代码可能如下所示:
图9

其工作原理如下:客户端无法“伪造”会话对象。获取会话对象的唯一方法是调用 authenticate() 并使其成功返回。

在大多数 RPC 系统中,一次 RPC 调用不可能以这种方式返回指向新 RPC 对象的存根。相反,所有函数都是顶层函数,任何人都可以调用。在这种传统的 RPC 系统中,每次调用函数时都需要再次传递 API 密钥,并且每次都要在服务器上再次验证。或者,您需要完全在 RPC 系统之外进行授权。

这是 WebSocket 的一个常见痛点。由于 WebSocket 的 Web API 设计,通常无法使用标头或 Cookie 进行授权。相反,授权必须在带内进行,即通过 WebSocket 本身发送消息。但这对 RPC 协议来说可能很麻烦,因为这意味着身份验证消息是“特殊的”,会改变连接本身的状态,从而影响后续调用。这破坏了抽象性。

上面显示的 authenticate() 模式巧妙地使身份验证自然地融入了 RPC 抽象。它甚至是类型安全的:您不可能在调用需要身份验证的方法之前忘记进行身份验证,因为您没有可进行调用的对象。

说到类型安全……
TypeScript
如果您使用 TypeScript,Cap'n Web 可以很好地与之兼容。您可以将 RPC API 声明为 TypeScript 接口,在服务器上实现,然后在客户端调用它:
图11

现在,您将获得端到端的类型检查、自动补全的方法名等功能。
请注意,与 TypeScript 一样,运行时不会进行类型检查。RPC 系统本身并不能阻止恶意客户端使用错误类型的参数调用 RPC。当然,这并非 Cap'n Web 独有的问题——基于 JSON 的 API 一直存在这个问题。您可能希望使用像 Zod 这样的运行时类型检查系统来解决这个问题。(同时,我们希望在未来添加直接基于 TypeScript 类型的类型检查。)

Cloudflare 保护整个企业网络,帮助客户高效构建互联网规模的应用程序,加速任何网站或互联网应用程序,抵御 DDoS 攻击,防止黑客入侵,并能协助您实现 Zero Trust 的部署与实施。

从任何设备访问 1.1.1.1,使用我们的免费应用加速和保护您的互联网。

立即联系我们,获取更多相关信息http://t.cn/A6Tx4yTT

#Cloudflare##Cap'n Web#

发布于 北京