简介:本文讲述了我们在首款产品上市之前就差点破产、最后幸存下来并从中汲取教训的故事。
2020年3月,当COVID上市时,我们的初创公司Milkie Way也遭受了巨大的打击,几乎被关闭了。在几个小时内使用Firebase探索和内部测试Cloud Run时,我们烧掉了$ 72,000。
在有了想法之后,我于2019年11月开始开发Announce https://announce.today。目的是创建产品的功能性V1“ MVP”,因此,我们的代码基于简单的堆栈。我们使用JS,Python,并将我们的产品部署在Google App引擎上。
我们的团队非常小,我们的重点是编写代码,设计UI和准备产品。我花了最少的时间在云管理上,足以让我们投入使用,并拥有基本的开发流程(cicd)。
在V1 Web应用程序中,用户体验并不是最流畅的,但是我们只是想制作一些我们的用户可以试用的产品,同时我们构建了更好的Announce版本。随着Covid走向世界,我们认为这是做出改变的最佳时机,因为Announce可能会被各国政府用来在全球范围内发布公告。
即使用户不首先创建内容,在平台上拥有一些丰富的数据不是很酷吗?这种想法导致了另一个名为Announce-AI的项目。目的是为自动发布创建丰富的内容。丰富的数据==事件,地震等安全警告,以及可能的本地相关新闻。
0
一些技术细节课
为了开始开发Announce-AI,我们使用了Cloud Functions。由于我们的漫游器抓取网络的年龄还很小,因此我们认为轻量级的Cloud功能是必经之路。但是,当我们决定扩展规模时,我们遇到了麻烦,因为Cloud Functions的超时时间约为9分钟。
目前,我们了解了Cloud Run,它具有大量的免费使用层。在没有完全理解它的情况下,我要求我的团队在Cloud Run上部署“测试”宣布AI功能,并查看其性能。我们的目标是玩转Cloud Run,因此我们可以真正地学习和探索它。
Google Cloud Run
为简单起见,因为我们的实验是针对一个很小的站点,所以我们使用Firebase来存储数据库,因为Cloud Run没有任何存储,并且在SQL Server上进行部署,或者用于测试运行的任何其他数据库都已经过时了。杀。
我创建了一个新的GCP项目ANC-AI Dev,设置了7美元的Cloud Billing预算,并将Firebase Project保留在Free(Spark)计划中。如果我们步履蹒跚,我们想象的最糟糕的情况就是超出了每日免费Firestore限制。
在修改了一些代码之后,我们部署了代码,并在一天中的半天手动发出少量请求,检查日志,开帐单了几分钟来运行它,然后一切都变得一团糟。
1
噩梦开始
测试当天一切都很好,我们回到了开发公告的阶段。第二天下班后,我在下午晚些时候小睡了。醒来时,我读了几封来自Google Cloud的电子邮件,它们彼此之间在几分钟之内就发送完了。
第一封电子邮件:Firebase项目的自动升级
第二封电子邮件:超出预算
幸运的是,我的卡预设有100美元的支出限额。这导致收费下降,并且Google暂停了我们的所有帐户。
第三封电子邮件:卡被拒
我跳下床,登录Google Cloud Billing,看到一张约5,000美元的账单。超级压力,而且不确定发生了什么,我四处张望,试图找出正在发生的事情。我也开始考虑可能发生的事情,以及我们如何“可能”支付5K美元的账单。
问题是,账单每分钟都在上涨。
5分钟后,账单显示15,000美元,在20分钟内显示为25,000美元。我不确定它会在哪里停止。也许它不会停止?
两个小时后,它的价格略低于$ 72,000。
到了这个时候,我和我的团队正在通话中,我处于完全震惊的状态,对下一步该怎么做绝对一无所知。在此过程中,我们已经禁用了计费功能,并关闭了所有服务。
由于我们在所有GCP项目中都使用了相同的公司卡,因此我们所有的帐户和项目都已被Google暂停。
2
噩梦仍在继续
这发生在3月27日星期五晚上,即我们计划发布Announce V1的三天前。由于Google暂停了所有与同一张信用卡相关联的项目,因此我们的产品开发工作死了。我的士气低落了,我们公司的前途未卜。
我们所有的云项目都已暂停;发展停止
一旦我的想法与这个新现实融洽了,午夜时分,我坐下来实际调查发生了什么。我开始写一份详细介绍所有调查的文件……我称此文件为“第11章”。
我参加实验的团队中的两个成员也整夜不眠不休地调查并试图弄清发生了什么。
第二天,即3月28日,星期六,我打电话给十几家律师事务所并通过电子邮件发送电子邮件与他们进行预约/与一些律师聊天。他们所有人都离开了,但是我能够通过电子邮件从其中之一得到回复。因为即使对于工程师来说,事件的细节也是如此复杂,所以用通俗易懂的英语向律师解释这本身就是一个挑战。
作为一家自负盈亏的公司,我们无法拿出$ 72K。
到了这个时候,我对破产法的第7章和第11章已经很精通,并且对接下来可能发生的事情有充分的心理准备。
3
喘息之机:GCP漏洞
在向律师发送电子邮件之后的星期六,我开始阅读更多内容,并仔细阅读GCP文档中的每一页。我们确实犯了错误,但是Google之前甚至没有付款就让我们花了7.2万美元就没有意义了。
GCP和Firebase
1.将Firebase帐户自动升级到付费帐户
在注册Firebase时,我们从未想到过,也从未显示过。我们的GCP项目已连接结算以执行Cloud Run,但Firebase处于免费计划(Spark)下。GCP刚出了头就对其进行了升级,并向我们收取了所需的费用。
事实证明,这就是他们的过程,因为“ Firebase和GCP深度集成”。
2.计费“限额”不存在。预算至少要延迟一天。
实际上,GCP帐单至少延迟了一天。Google在大多数文档中建议使用预算和自动关闭云功能。好吧,猜猜是什么,到中断功能触发或通知云用户时,损坏可能已经完成了。
结算大约需要一天的时间,因此这就是我们第二天注意到收费的原因。
3. Google应该向我们收取$ 100,而不是$ 72K!
由于我们的帐户迄今尚未付款,因此GCP应该先根据帐单信息向您收取$ 100的费用,然后在未付款时停止该服务。但事实并非如此。后来我了解了原因,但这仍然不是用户的错!
我们帐户的第一笔帐单费用约为5,000美元。下一个售价为$ 72,000。
我们帐户的结算起付金额为$ 100
4. Firebase仪表板可能非常不可靠
不仅计费,而且Firebase Dashboard都花费了超过24个小时来更新。
根据Firebase控制台文档,Firebase控制台的仪表板编号可能与“账单”报告略有不同。
在我们的案例中,相差86,585,365.85%,即8600万个百分点。即使在收到账单通知之后,Firebase控制台的仪表板仍然表示该月有42,000次读写(低于每日限制)。
4
新的一天,新的挑战
成为Google员工已有6.5年左右的时间,并撰写了许多项目文档,验尸报告,后来写了一份文档,与Google分享,概述了这一事件,并在事后总结了Google方面的漏洞。Google小组将在2天后恢复工作。
编辑:一些读者建议我在Google使用我的内部联系人。事实是,我没有与任何人保持联系,并且我使用了任何普通开发人员/公司都会采用的方法。像其他任何小型开发人员一样,我在聊天,咨询,冗长的电子邮件和错误上花费了无数的时间。在我的下一篇有关如何处理事件的文章中,我想分享一下在此事件期间发送给Google的文档/验尸报告。
Google的最后一天
另一个任务是了解我们的错误,并制定我们的产品开发策略。并非团队中的每个人都知道发生了什么,但是很明显我们遇到了一些大麻烦。
作为Google员工,我有经验丰富的团队犯错,给Google造成了数百万美元的损失,但Google的文化挽救了员工(工程师必须写一份冗长的事故报告)。这次,没有Google。我们自己有限的资金和我们的辛勤工作完全处于危险之中。
5
我们实际上做了什么?
作为一个很小的团队,我们希望尽可能地保持无服务器状态。无服务器解决方案(如Cloud Functions和Cloud Run)的问题是超时。
在任何时候,一个实例将连续地在网页中抓取这些URL。但是9分钟后不久,它就会超时。
在讨论了这个问题并使用了咖啡因后,几分钟之内,我在白板上写了一些干燥的代码,现在我看到了很多设计问题,但那时候,我们更加专注于失败和快速学习以及尝试新事物。
在Cloud Run上宣布AI的``Hello World''版本
为了克服超时限制,我建议使用POST请求(以URL作为数据)将作业发送到一个实例,并并行使用多个实例,而不是串行使用一个实例。因为Cloud Run中的每个实例只会刮取一页,所以它永远不会超时,并行(缩放)处理所有页面,并且由于Cloud Run的使用精确到毫秒,因此也得到了高度优化。
刮板部署在Cloud Run上
如果仔细观察,该流程将丢失一些重要的部分。
- 没有中断的指数递归:实例没有中断时间,因为没有break语句。
- POST请求可以具有相同的URL。如果有指向上一页的反向链接,则Cloud Run服务将陷入无限递归中,但最糟糕的是,此递归呈指数增长(我们的最大实例数设置为1000!)。
可以想象,这导致1000个实例进行查询,并每隔几毫秒写入一次Firebase DB。查看数据发布事件,我们发现Firebase读取在某一点上大约为每分钟10亿个请求!
GCP帐单帐户的月末交易摘要
1160亿读取和3300万写入
在Cloud Run上运行此版本的Hello World部署,向Firestore读取了1,160亿次,写入了3,300万次。哎哟!
阅读Firebase上的运营成本:
(0.06 / 100,000)* 116,000,000,000 = 69,600
16,000小时的云运行计算时间
经过测试,我们假设该请求因日志记录停止而终止,但实际上它进入了后台进程。因为我们没有删除服务(这是我们第一次使用Cloud Run,那时我们还不太了解),所以多个服务继续缓慢运行。
在24小时内,这些服务版本每个扩展到1000个实例,消耗了16022小时。
6
我们所有的错误
在云上部署有缺陷的算法
上面已经讨论过了。我们确实发现了一种通过POST请求使用无服务器的新方法,这是我在Internet上任何地方都找不到的方法,但是在没有改进算法的情况下进行了部署。
使用默认选项部署云运行
在创建Cloud Run服务时,我们在服务中选择了默认值。max-instances预设为1000,并发设置为80。开始时,我们不知道这些值实际上对于测试程序而言是最坏的情况。
如果我们将max-instances选择为“ 2”,那么我们的成本将减少500倍。72,000美元的钞票原本是:144美元
如果我们选择并发请求为“ 1”,那么我们甚至可能不会注意到该账单。
在不完全了解Firebase的情况下使用Firebase
有些事情只有经过大量的经验才能学到。Firebase不是一种可以学习的语言,它是Google提供的容器化平台服务。它具有由他们定义的规则,而不是由自然法则或特定用户可能会认为的规则来定义。
另外,在Node.js中编写代码时,必须注意后台进程。如果代码进入后台进程,则开发人员没有简单的方法可以知道该服务正在运行,但是可能要花相当长的时间。正如我们稍后了解到的,这就是我们大多数云功能也都超时的原因。
快速失败,通过Cloud快速学习是一个坏主意
云的整体就像一把双刃剑。如果使用得当,它可能会很有用,但是如果使用不当,则可能会导致后果。
如果您算一下GCP文档中的页数,则可能比几本小说中的页数还多。了解定价和用法不仅耗时,而且需要深入了解云服务的工作方式。怪不得为此目的有全职工作!
Firebase和Cloud Run确实强大
在高峰期,Firebase能够处理每分钟约10亿次读取。这是异常强大的。我们已经在Firebase上玩了2-3个月,并且仍在学习它,但是直到现在我仍然完全不知道它有多强大。
Cloud Run也是如此!并发== 60,max_containers == 1000,每个请求占用400毫秒,Cloud Run的请求数每分钟可以处理900万个请求!
60 * 1000 * 2.5 * 60 = 9,000,000个请求/分钟
相比之下,Google搜索每分钟可获得380万次搜索。
使用 Cloud Monitoring
尽管Google Cloud Monitoring不会停止计费,但它会及时发送警报(大约3-4分钟的延迟)。了解Google Cloud的原型/命名结构有一个学习曲线,但是一旦您花了很多时间,仪表板,警报和指标就会使生活变得更轻松。
这些指标仅可使用90天,而我们从这次事件中丢失了指标(这些天Firebase和Cloud Run的使用情况发生了巨大的变化),否则,我很乐意在本文中分享它们。
7
我们还活着
但很悬,太悬了
在认真阅读了关于此次事件的报告之后,经过一系列咨询、讨论与内部研究,谷歌直接免除了我们的账单!
谢谢你,谷歌!
我们又恢复了活力,能够继续开发 Announce。而且这一次,我们拥有更好的视角、更强的架构与更安全的实现思路。
谷歌是我最欣赏的科技企业,这不只是因为它是一家值得为之工作的伟大公司,同时也因为它有着很强的同理心。谷歌提供的工具很合开发者的胃口,很重视说明文档质量(大多数情况下),而且一直在不断发展。(作者注:这只是我作为独立软件开发者的个人感受,绝非软文或者刻意吹捧。)
8
接下来是什么?
发生此事件后,我们花了几个月的时间来了解云和我们的架构。几周后,我的理解有了很大的提高,以至于我估计了使用带有改进算法的Cloud Run刮取“整个Web”的成本。
这次事件使我深入分析了产品的体系结构,并报废了产品的V1,以构建可扩展的基础架构来为产品提供动力。
在Announce V2中,我们不仅建立了MVP,还建立了MVP。我们建立了一个平台,在该平台上,我们可以迭代地快速开发新产品,并在安全的环境中对其进行全面测试。
这一过程花了我们一些时间……宣布于11月底发布,比我们为V1决定的发布晚了大约7个月,但它具有高度的可扩展性,获得了最佳的云服务并针对使用进行了高度优化。
我们还在所有平台上启动了,而不仅仅是在网络上启动了。
更重要的是,我们重用了整个平台来构建我们的第二个产品Point Address。这两种产品不仅具有可扩展性,具有出色的体系结构和高效性,而且还建立在一个平台上,该平台使我们能够快速构建想法并将其部署到可用产品中。
转自:Sudeep Chauhan