分享

简介

无服务器范式代表着应用程序和 Web 开发人员与基础设施、语言运行时和补充服务交互方式的重大转变。它通过抽象化和承担传统上影响代码在生产环境中运行方式的许多环境因素的责任,让开发人员能够专注于他们最关心的领域。

虽然无服务器计算有很多优点,但它也存在一些挑战,在你成功之前必须承认或解决这些挑战。在本指南中,我们将讨论当前一代解决方案的一些主要痛点,并讨论它们的含义以及如何绕过它们。你应该能够更好地了解你可能需要满足的要求以及可能遇到的障碍。

冷启动问题

在使用无服务器时,最常讨论的挑战之一被称为冷启动问题。虽然无服务器的目标是允许函数按需立即执行,但有一些场景可能会导致可预测的延迟。

什么是冷启动问题?

无服务器的一大卖点是能够在没有活动的时候缩放到零。如果一个函数没有在积极执行,函数的资源将被关闭,并将容量返还给平台,从而降低用户为保留这些组件而付出的成本。从成本的角度来看,这是理想的,因为它意味着用户只为他们的代码实际执行的时间和资源付费。

这样做的缺点是,当资源完全关闭时,下次需要执行时,就会有一个可预测的延迟。资源需要重新分配以运行函数,这需要时间。你最终会得到一组用于最近使用过的“热”函数的性能特征,以及另一组用于需要等待平台创建执行环境的“冷”函数的性能特征。

开发人员如何尝试解决冷启动问题?

开发人员和平台已经尝试了许多方法来解决这个问题。一些开发人员会安排“虚拟”请求来让与他们的函数相关的资源处于待命状态。许多平台为他们的服务添加了额外的层级,以允许开发人员自动将资源保持在待命状态。

这些解决方案开始模糊无服务器环境的界限。当开发人员被迫为他们代码没有积极执行时的待命资源付费时,就会引发一些关于无服务器范式的一些基本主张的问题。

最近,预先分配资源的替代方案是通过切换到更轻量级的运行时环境来避开这个问题。V8 这样的运行时环境具有与传统无服务器环境截然不同的执行策略,通过使用不同的隔离技术和更精简的环境,可以避免冷启动问题。它们以牺牲与依赖更强大环境的函数的兼容性为代价来避免冷启动问题。

应用程序设计约束

无服务器模型带来的另一个基本挑战是它强加的应用程序设计。无服务器平台只对可以在其约束条件下工作的应用程序有用。其中一些是云计算本身固有的,而其他要求则是由无服务器模型专门规定的。

设计云友好的架构

应用程序使用无服务器平台必须满足的第一个要求是云友好的设计。 在本次讨论的背景下,至少这意味着应用程序必须至少部分部署到其他组件能够与其通信的云服务。 虽然可以在设计中实现 单体功能,但无服务器模型最适合 微服务架构

其结果是,您的应用程序必须部分设计为由无服务器提供商执行的一系列函数。 您必须适应在您无法控制的基础设施上进行的处理。 此外,您必须能够将应用程序的功能分解为可以远程执行的离散函数。

处理无状态执行

无服务器函数本质上是无状态的。 这意味着,虽然如果函数使用相同的资源执行,一些信息可能被缓存,但您不能依赖任何状态在函数调用之间共享。

您必须设计您的函数,使其拥有执行所需的所有内部信息。 任何外部状态必须在调用开始时获取并在完成之前导出。 由于函数可以并行执行,这也限制了可以合理地对其进行操作的状态类型。 一般来说,函数管理的状态越少,执行速度越快,成本越低,需要管理的复杂性也越低。

函数的短暂性也存在其他副作用。 如果您的函数需要访问数据库系统,您很可能很快耗尽数据库的连接池。 由于您的函数的每次调用都可以在不同的上下文中执行,因此当数据库响应不同的调用或尝试将资源返回到池中时,数据库的连接池会很快耗尽。 像 Prisma Accelerate 这样的解决方案通过管理连接资源来缓解这些问题,这些资源用于连接到任何已有的连接池前面的无服务器实例。

供应商锁定问题

使用无服务器时难以克服的一个挑战是供应商锁定。 当您将应用程序设计为依赖运行在特定供应商平台上的外部函数时,以后可能难以迁移到其他平台。

可能出现哪些类型的锁定?

对于针对特定无服务器平台构建的应用程序,许多因素都会干扰干净地迁移到另一个提供商。 这些因素可能是由无服务器实现本身造成的,也可能是由应用程序设计中可能集成的供应商相关服务的使用造成的。

在由实际无服务器实现造成的锁定方面,提供商之间最基本的区别之一可能是支持用于定义函数的语言。 如果您的应用程序函数是用其他候选提供商不支持的语言编写的,则必须用支持的语言重新实现逻辑,否则迁移将无法进行。 无服务器不兼容性的一个更微妙的例子是不同提供商对平台内函数触发机制的概念化和暴露方式的不同。 如果这些机制存在显着差异,您可能需要重新定义新平台上触发器的实现方式。

当无服务器应用程序使用其提供商生态系统中的其他服务来支持其应用程序时,可能会出现其他类型的锁定。 例如,由于无服务器函数不处理状态,因此通常使用提供商的对象存储产品来存储在调用期间产生的任何工件。 虽然对象存储通常使用标准接口实现,但它说明了无服务器架构的约束如何导致对其他可用服务的生态系统更大程度的采用和依赖。

开发人员如何尝试限制锁定

开发人员可以尝试一些方法来最小化其应用程序锁定可能性或影响。

用广泛支持的语言(如 JavaScript)编写函数是最简单的避免硬依赖的方式之一。 如果您选择的语言得到许多提供商的支持,那么您将可以选择其他可能运行您代码的平台。

开发人员还可以尝试将服务的使用限制在每个平台上几乎相同的商品产品。 例如,我们之前使用的对象存储示例实际上是一个理想的示例,说明了可以被另一个提供商的产品替换的服务。 您依赖的服务越专业,迁移出生态系统就越困难。 这是一个您必须逐案评估的权衡,因为您可能不得不放弃专业工具而使用更通用的工具。

关于缺乏控制和洞察力的调试担忧

开发人员评估无服务器以用于未来项目时,对其提出的常见抱怨之一是无服务器平台提供的控制和洞察力不足。 部分原因在于产品本身,因为对运行代码的基础设施的控制,必然会使该服务不再属于无服务器类别。 尽管如此,开发人员通常仍然对在限制可见性和控制的环境中进行部署感到担忧,尤其是在诊断可能影响正常运行时间和影响生产的问题时。

开发人员可以期待哪些类型的差异?

无服务器范式承诺将除了代码本身以外的所有责任转移到平台提供商。 这在运营开销方面可以带来很多优势,并简化开发人员的执行环境,但它也使开发人员通常依赖的许多技术和工具变得更加困难或无法使用。

例如,一些开发人员习惯于能够通过直接访问编程环境来进行调试,方法是连接到具有 SSH 的主机,或内省代码并使用进程公开的数据。 这些在无服务器环境中通常不可能或不容易,因为执行环境对用户来说是不透明的,并且只有函数日志等特定接口可用于调试。 这可能导致难以诊断问题,尤其是在无法在本地复制问题或多个函数在管道中调用时。

有哪些选项可以帮助?

开发人员可以采用许多不同的策略来帮助他们在这种更有限的调试环境中工作。

一些无服务器功能可以在本地运行或模拟,允许开发人员在自己的机器上调试无法在生产环境中调试的内容。 许多工具旨在模拟常见的无服务器平台,以便开发人员可以重新获得一些他们可能缺少的诊断功能。 它们允许您逐步执行函数,查看状态信息并设置断点。

对于在平台本身进行调试,您必须尝试利用提供商提供的全部工具。 这通常意味着在您的函数中进行大量日志记录,使用 API 测试工具自动用不同的输入触发函数,并使用平台提供的任何指标来尝试了解执行环境中可能发生的情况。

总结

无服务器环境在开发人员效率、降低运营复杂性和节省实际成本方面提供了很多价值。但是,务必了解范式的局限性以及在设计应用程序以在无服务器环境中运行时可能需要解决的一些特殊挑战。

通过熟悉可能遇到的各种障碍,您可以更明智地决定哪些应用程序可以从权衡中获益最多。您还将更好地准备以更好地理解如何减轻或避免这些问题,方法是使用其他工具或设计考虑因素。

关于作者
Justin Ellingwood

Justin Ellingwood

Justin 从 2013 年开始撰写有关数据库、Linux、基础架构和开发人员工具的文章。他目前与妻子和两只兔子住在柏林。他通常不必以第三人称写作,这对所有相关方来说都是一种解脱。