连接生产环境:远程绑定的架构
远程绑定是连接到您Cloudflare账户上已部署资源的绑定,而不是本地模拟资源——最近,我们宣布远程绑定现已全面可用。通过此发布,您现在可以在本地机器上运行Worker代码时连接到已部署的资源,如R2存储桶和D1数据库。这意味着您可以在真实数据和服务上测试本地代码更改,而无需每次迭代都进行部署。在这篇博客文章中,我们将深入探讨我们如何构建它,以创建无缝的本地开发体验的技术细节。
在Workers平台上开发
Cloudflare Workers平台的一个关键部分是能够本地开发代码,而无需每次想要测试时都进行部署——尽管我们支持这种方式多年来发生了巨大变化。我们从运行在远程模式的wrangler dev开始。这是通过部署并连接到在您每次更改代码时在Cloudflare网络上运行的Worker预览版本来实现的,允许您在开发过程中进行测试。然而,远程模式并不完美——它复杂且难以维护。开发人员体验也差强人意:迭代速度慢、调试连接不稳定、缺乏对多Worker场景的支持。这些问题及其他因素促使我们对Workers的完全本地开发环境进行了重大投资,该环境于2023年中期发布,并成为wrangler dev的默认体验。从那时起,我们在Wrangler、Cloudflare Vite插件(以及@cloudflare/vitest-pool-workers)和Miniflare的本地开发体验上投入了大量工作。
尽管如此,原始的远程模式仍然可以通过标志访问:wrangler dev --remote。当使用远程模式时,完全本地体验的所有DX优势以及我们在过去几年中所做的改进都被绕过了。那么为什么人们仍然使用它?它实现了一个关键独特功能:在本地开发时绑定到远程资源。当您使用本地模式在本地开发Worker时,所有绑定都使用本地(最初为空)数据在本地模拟。这对于使用测试数据迭代应用程序逻辑非常棒——但有时这还不够,无论您是想跨团队共享资源、复现与真实数据相关的错误,还是仅仅希望您的应用程序能在生产环境中与真实资源一起工作。
鉴于此,我们看到了一个机会:如果我们可以将远程模式的最佳部分(即访问远程资源)引入wrangler dev,那么将有一个单一的Workers开发流程,能够支持许多用例,同时不会将人们排除在我们对本地开发所做的进步之外。而这正是我们所做的!从Wrangler v4.37.0开始,您可以在每个绑定的基础上选择绑定应使用远程还是本地资源,只需指定remote选项。重要的是要重新强调这一点——您只需要添加remote: true!不涉及复杂的API密钥和凭据管理,一切都只是使用Wrangler现有的与Cloudflare API的Oauth连接来工作。
|
|
眼尖的您可能已经意识到,一些绑定已经像这样工作,从本地开发访问远程资源。最突出的是,AI绑定是通用远程绑定解决方案可能样子的先驱。从其引入开始,AI绑定始终连接到远程资源,因为一个真正的本地体验,支持您可以在Workers AI中使用的所有不同模型,是不切实际的,并且需要大量预先下载AI模型。当我们意识到Workers内的不同产品(例如Images和Hyperdrive)需要类似于远程绑定的东西时,我们最终得到了一些不同解决方案的拼凑。我们现在已经统一在一个适用于所有绑定类型的单一远程绑定解决方案下。
我们如何构建它
我们希望让开发人员能够非常容易地访问远程资源,而无需更改其生产Workers代码,因此我们确定了一个解决方案,要求我们在Worker中使用点时从远程资源获取数据。
|
|
上面的代码片段显示了访问env.KV KV命名空间中的“some-key”值,该值在本地不可用,需要通过网络获取。所以,如果那是我们的要求,我们如何实现?例如,我们如何从用户在Worker中调用env.KV.put("key", "value")到实际将其存储在远程KV存储中?显而易见的解决方案可能是使用Cloudflare API。我们本可以在本地用存根对象替换整个env,这些存根对象进行API调用,将env.KV.put()转换为PUT http:///accounts/{account_id}/storage/kv/namespaces/{namespace_id}/values/{key_name}。
这对于KV、R2、D1和其他具有成熟HTTP API的绑定来说可能工作得很好,但这将是一个相当复杂且难以维护的解决方案。我们将不得不复制整个绑定API表面,并将绑定上的每个可能操作转换为等效的API调用。此外,一些绑定操作没有等效的API调用,并且使用此策略将无法支持。相反,我们意识到我们已经有一个现成的API在等待我们——我们在生产环境中使用的那个!
生产环境中绑定的工作原理
Workers平台上的大多数绑定本质上归结为服务绑定。服务绑定是两个Worker之间的链接,允许它们通过HTTP或JSRPC(我们稍后会回到JSRPC)进行通信。例如,KV绑定被实现为您创作的Worker与平台Worker之间的服务绑定,使用HTTP进行通信。KV绑定的JS API在Workers运行时中实现,并将像env.KV.get()这样的调用转换为对实现KV服务的Worker的HTTP调用。
您可能会注意到这里有一个自然的异步网络边界——在运行时转换env.KV.get()调用与实现KV服务的Worker之间。我们意识到我们可以利用那个自然的网络边界来实现远程绑定。不是生产运行时将env.KV.get()转换为HTTP调用,我们可以让本地运行时(workerd)将env.KV.get()转换为HTTP调用,然后直接发送到KV服务,绕过生产运行时。而这正是我们所做的!
上面的图示显示了一个本地运行的Worker,带有一个远程KV绑定。它不是由本地KV模拟处理,而是现在由远程代理客户端处理。然后,该Worker与连接到真实远程KV资源的远程代理服务器通信,最终允许本地Worker与远程KV数据无缝通信。每个绑定可以独立地由远程代理客户端处理(全部连接到同一个远程代理服务器)或由本地模拟处理,允许非常动态的工作流程,其中一些绑定在本地模拟,而其他绑定连接到真实的远程资源,如下例所示:
上面的图示和配置显示了一个Worker(在您的计算机上运行)绑定到3个不同的资源——两个本地(KV和R2),一个远程(KV_2)。
JSRPC如何融入
上述部分处理由HTTP连接支持的绑定(如KV和R2),但现代绑定使用JSRPC。这意味着我们需要一种方法让本地运行的workerd与生产运行时实例进行JSRPC通信。幸运的是,一个并行项目正在进行以使这成为可能,如Cap’n Web博客中详细所述。我们通过让本地workerd实例与远程运行时实例之间的连接使用Cap’n Web通过websockets进行通信来集成它,从而使由JSRPC支持的绑定能够工作。这包括较新的绑定,如Images,以及到您自己的Worker的JSRPC服务绑定。
与Vite、Vitest和JavaScript生态系统的远程绑定
我们不想将这个激动人心的新功能仅限于wrangler dev。我们希望在我们的Cloudflare Vite插件和vitest-pool-workers包中支持它,并允许任何其他潜在工具和来自JavaScript生态系统的用例也能从中受益。为了实现这一点,wrangler包现在导出实用程序,如startRemoteProxySession,允许不利用wrangler dev的工具也支持远程绑定。您可以在官方远程绑定文档中找到更多详细信息。
如何尝试?
只需使用wrangler dev!从Wrangler v4.37.0(@cloudflare/vite-plugin v1.13.0,@cloudflare/vitest-pool-workers v0.9.0)开始,远程绑定在所有项目中可用,并且可以通过在Wrangler配置文件的绑定定义中添加remote: true来在每个绑定的基础上开启。