为什么本地开发是无服务器架构的一种反模式
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
在无服务器社区,个人和团队花费大量时间和精力试图构建一个与云端环境完全相同的开发环境。为什么?因为我们一直以来都是这么做的。当你开始从事 Web 应用开发工作时,你会被告知需要在自己的机器上搭建一个本地开发环境,并在将代码推送到代码仓库之前,先在这个环境中完成开发工作。
但我认为,在无服务器架构中,这种在构建应用程序时必须立即启动并运行的绝对要求不仅没有必要,而且实际上是有害的。
让我们先来思考一下原因。我们为什么要创建本地开发环境?它们究竟有什么用途?
回顾我们过去构建 Web 应用的历程,我们曾经身处一个代码和脚本极其精简的世界,工作基本上都是直接在为 Web 应用提供服务的服务器上完成的。为什么呢?因为这些服务器通常都是非常专业的机器,复制起来成本极高,而且在那个阶段,100% 的正常运行时间并非首要目标,所以何乐而不为呢?直接在远程服务器上编辑文件非常方便。
几年后,我们现在面临着这样的情况:需要每天多次修改一个应用程序,而这个应用程序必须尽可能避免宕机。直接在生产环境中进行修改令人担忧,因为我们希望尽可能先对应用程序进行测试。
幸运的是,在现阶段,网络的很多基础设施已经商品化;我们可以使用普通的消费级计算机,并在其上安装相同(或类似)的应用程序来模拟远程环境,并在将其推送到生产服务器之前测试我们的应用程序。
然而,情况不可能一直如此。流量激增,单台机器很快就无法应对互联网增长带来的负载。为了提高请求吞吐量和故障恢复能力,因为停机成本越来越高,需要架构相对复杂的机器集群。开发人员机器上的复制开发环境不再是高度精确的副本。
很多测试环境或开发环境都是由此而来。其思路是,让开发人员像往常一样在本地机器上进行开发,因为他们已经习惯了这种方式;而我们会尽可能搭建一个与生产环境高度相似的副本,以便进行测试,确保不会出现任何问题,即使这会给公司带来损失,因为这总比停机要好。
云计算在这方面也确实发挥了很大作用;如果你可以按需创建暂存环境,并且只在需要时才启动它们,那么它的成本就比在服务器机架中并行维护一个开发集群要低得多。
然而,问题在于我们的本地机器充其量只能偶尔与生产集群保持一致,而且通常需要开发人员不断地将代码推送到共享的测试服务器进行测试,因为架构过于复杂,根本无法在本地完全复现,任何形式的本地测试都显得多余。更不用说,在团队协作中,这会导致很多互相掣肘的情况,以及轮流测试自己修改的麻烦!
真正需要的是为团队中的每个开发人员提供一个生产环境的副本。但由于生产集群运行着多个虚拟机、负载均衡器、关系数据库、缓存等等,这样做成本太高。
然后,集装箱终于来了!现在我们可以把复杂的生产系统打包成互不干扰的简洁小模块,然后在我们自己的开发机器上运行它们,从而更接近生产环境。
然而,它们之间确实会相互干扰,并给开发人员增加了大量的复杂性,让他们不得不处理和操心这些事情。高薪工程师本应专注于开发功能和创造收入,而不是管理他们的开发环境,而且即便如此,它仍然无法准确地反映生产环境的真实情况!
我曾经在一家电商公司当工程师,他们安排了一位开发人员花了两个月时间,专门负责将生产环境复制成一系列 Docker 容器,以便我们可以直接安装在自己的机器上。最终的成果是,光是安装就花了 30 分钟,而且整个开发团队的硬件都需要升级到至少 16GB 内存。在一台机器上运行 Nginx、Elasticsearch、Redis 和 MySQL 居然会占用大量内存,真是令人难以置信。即便如此,当我们以为代码已经准备好在测试环境中运行时,仍然会遇到各种问题,但实际上并非如此。
这只是我要分享的众多例子中的一个。
以上内容的总结是什么?我们之前使用本地测试,是因为直接在生产环境中测试风险太大,我们尝试在本地复现生产环境,结果惨败,以至于今天我们实际上仍然在生产环境中进行测试。
如今,在无服务器开发领域,我们又一次面临着这样的困境:试图让一些原本不应该在本地运行的东西在本地运行。而且,这并非是我们可以勉强在本地运行的虚拟机或 Docker 容器集合。这些都是云服务,它们大多没有官方的本地运行方式,而且可能永远也不会有。像 Localstack 这样的工具所使用的现有模拟技术固然令人印象深刻,但它们并非云端的精确复制品;它们只是目前为止人们为了让我们能够在本地测试这些服务,尽可能接近云端版本而做出的最佳尝试。更不用说云(以及分布式应用架构)中那些可能造成诸多问题的方方面面了。如何复制服务内部的延迟、身份和访问管理 (IAM)、服务限制以及其他许多与特定服务无关的云特性呢?
我们甚至根本不需要这样做!有了像 Serverless Framework 这样的工具(我知道还有其他工具,但我对它们的熟悉程度不如 Serverless Framework),你就可以在任何其他环境中部署与生产环境完全相同的资源配置。想要一个供团队开发人员测试的共享环境?只需运行部署命令!想要一个自己的“本地”测试环境?只需运行部署命令!
终于!我们现在可以 100% 复制生产环境中的基础设施,而且由于无服务器应用程序倾向于按使用量计费,因此部署它们无需任何成本,进行测试也只需几分钱!
那么,我们为什么还要如此努力地维护本地环境呢?或许是因为担心生产力下降。为了解答这个问题,我想推荐一篇由我在 Serverless, Inc. 的同事最近发表的文章,他从极简的角度阐述了如何看待无服务器的“本地”开发,以及实现这一目标所需的极少工具。点击此处查看。管理本地开发环境、更新环境、确保其持续运行所花费的时间本身就成本高昂。但还有另一个充分的理由让我们放弃这种做法!
实际上这对你的申请有负面影响!
假设有一群开发者使用类似 Localhost 的模拟工具。它能很好地帮助团队成员在本地构建和测试无服务器应用程序。然而,团队中的一位成员发现了一项非常有用的云服务,可以用来构建针对他们正在尝试解决的问题的最佳方案。这项服务可以提高应用程序的整体可靠性,降低成本并缩短上线时间。但是,本地模拟工具目前尚未提供这项服务。
他们现在有三种选择。第一种是无论如何都要使用这项服务,这意味着在云端进行测试现在是绝对必要的,但应用程序也会因此变得更好。然而,这使得本地测试环境完全失去了意义。第二种是不使用这项服务,但这样一来,由于本地测试环境神圣不可侵犯,应用程序的效能实际上会大打折扣。第三种是花费数天甚至数周的时间,试图找到一种在本地复制这项服务的方法,这会延迟该功能的部署,而且——假设你一开始就找到了可行的解决方案——你仍然只能使用一个质量低劣的云服务副本进行测试。
那么像 serverless-offline 这样的工具怎么样?它简单易用,可以让你轻松地测试 HTTP 端点,对吧?
嗯,除了这再次证明它并不能准确反映云计算的实际情况,完全忽略了 API 网关、IAM 等服务的特殊性之外,它也仅适用于 HTTP 事件。我们看到越来越多的无服务器应用程序的功能远不止是功能强大的 REST API。你无法测试所有可能触发 Lambda 函数的其他事件。
乍看之下,本地开发似乎高效便捷。在传统的 Web 开发领域,本地开发是一种必要的妥协,因为传统的架构成本过高且难以完全复制给团队中的每个开发人员。但无服务器架构部署成本为零,测试成本也极低(甚至免费),而且部署到云端后可以与生产环境完全一致。
仅仅因为某种方法很熟悉,并不意味着它就是个好主意。像 Serverless Framework 这样的工具,以及其他一些工具,能够让你在短短几秒内部署代码,直接从本地调用远程 Lambda 函数,甚至可以在终端中查看日志,即时获取错误反馈。有了这些工具,你无需降低生产力,就能大幅降低生产环境的复杂性和准确性。
如果大家有任何问题,请在评论区留言,或者也可以在推特上联系我。我的私信是开放的,我非常乐意讨论无服务器相关的话题!
文章来源:https://dev.to/garethmcc/why-local-development-for-serverless-is-an-anti-pattern-1d9b