服务
关于
CloudProse博客
Think FaaS播客

无服务器气味-Think FaaS播客

为无用的无服务器设计开发一种直觉't feel quite right.
福雷斯特Brazeal Trek10 191210 171202
阿甘(Forrest Brazeal) | 2019年6月17日

2019年六月17日星期一

在Google Play上订阅 订阅苹果播客

成绩单

嗨,这是Trek10的Forrest Brazeal,您正在听Think FaaS,在这里我们比运行Lambda函数花费的时间更少,了解了无服务器计算的世界。因此,花15分钟时间-是时候开始思考FaaS了。

有很多方法可以使用无服务器构建块来组装体系结构,就像您可以用一堆乐高积木制造几乎所有东西一样。问题是,如果您要建造坚固的房屋,可能不会用太多的这些砖块组合。我看到的无服务器的最大挑战之一是筛选所有可能的架构,以找到一个好的解决方案。

假设您要构建一个API,该API将响应同步返回给您的用户。但是,该API调用还需要启动一个异步进程,该进程会打入某些第三方服务,然后稍后通过回调通知您的用户。这是一种常见的模式,在过去的两个星期中,我在三种不同的情况下遇到了某种形式的错误。但是,您可以通过多种方式来执行此操作。您的API是REST还是GraphQL?您会使用某种队列来缓冲第三方呼叫吗?如果是这样,您将如何避免压倒您的下游系统?您将在队列消息上设置计时器吗?如何跟踪这些计时器应该持续多长时间?您是否需要在某个地方涉及DynamoDB?

可能有五种方法可以很好地构建此错误,而五十种方法则可以构建出某种错误。而且,直到相距较远时,您才可能知道选择的路径。

因此,今天,我们将讨论检测无服务器气味的问题。您可以寻找什么样的警告信号来形成对长期无法正常使用的体系结构或开发选择的直觉?像往常一样,我们将围绕AWS展开讨论,但希望这也可以推广到其他云。

我将尝试避免使用“ antipattern”一词,因为这个空间还不够广泛,无法整理出很多东西绝对不是个好主意,尤其是考虑到有那么多人正在经历无服务器之旅采用需要大量重构。因此,随着您的前进,我们在下面识别出的气味实际上可能是有效的停止点,但是我想指出为什么它们可能会出现问题以及我们应该朝哪个方向发展。

为了识别气味,我们首先需要了解一种好的无服务器架构的外观。您追求的设计目标是什么?

对我而言,激励性的冲动始终是建立“行之有效”的东西。回到乐高类比,我想看到积木相互点击。我不想用dremel重塑它们,然后用胶涂抹它们。这是我的意思的示例。假设我之前提到的API的要求之一是用户合同应在GraphQL模式中定义。我可以找到一个GraphQL库,并在Lambda函数中建立一堆样板逻辑,以将查询连接到解析器。或者,我可能可以通过使用AWS的托管GraphQL服务AppSync减少很多工作。到目前为止,如此明显。 AppSync是这里的乐高积木。现在,假设我的要求之一是对该服务的用户请求进行限制和速率限制。事实证明,AppSync今天并未本地提供该行为。 API网关确实具有与API密钥使用计划有关的许多功能的服务。但是,如果我使用API​​ Gateway,那么我将在后台实施我自己的GraphQL服务器。好像没有服务器的气味。

那我有什么选择呢?好吧,我可以将API网关代理放在AppSync端点的前面。这是一个好主意吗?也许!它将为我提供API网关的使用控制功能以及AppSync的强大功能,但也可能会给我的API带来一些额外的延迟。还有一个问题是如何处理API Gateway和AppSync之间的身份验证切换。如果我使用标准的HTTP代理,则必须维护和旋转AppSync API密钥,也许要使用按计划运行的单独Lambda函数。但是,我还可以在API Gateway中选择将AppSync后端视为AWS服务集成。这意味着我可以使用IAM授权AppSync调用,而无需旋转密钥。

您能看到我在这里描述的内容吗?我们已将两项具有非常强大功能的服务(AppSync和API网关)连接在一起,而无需任何中间Lambda功能。我们现在提供了诸如模式自省,数据库集成和API密钥限制等功能。我们通过API网关免费处理了无效请求。另一个优点是,尽管AppSync不支持自定义域和证书,​​但API Gateway可以。因此,只需添加一些Route53配置,就可以将主动-主动多区域服务与运行状况检查和故障转移结合在一起。这种体系结构的缺点-由于AppSync前面的API网关,可能会导致轻微的性能损失,每个请求几毫秒的时间,当然您要花两个托管服务的费用。但是,这就是您希望使用无服务器进行的权衡,以换取您无需构建自己的许多功能。

当您开始独自黑客入侵时,就会产生气味。我们尝试避免在此处放置“服务器功能”,而是将整个应用程序从VM提升并转移到Lambda。我知道有时候将它作为中间步骤或使用现有代码库是有意义的。但这不是最佳选择,因为它使函数的构建和运行速度变慢,您失去了对权限的精细控制,并且可能会发布不再需要编写的代码,例如GraphQL服务器。

这里的相关气味是将Lambda用作编排服务器,我认为这有点阴险,而且没有得到太多讨论。您必须开始将云服务视为应该外部化应用程序控制流的地方。这意味着扩展并发Lambda调用,而不是编写一堆线程代码。这意味着使用Step Functions和Amazon States Language而不是一堆if语句。这意味着通过死信队列处理错误。因此,您可以使业务逻辑保持较小,简单,离散的状态,并将其余部分表示为服务图。我知道程序员很难接受,这里有很多不同的意见。我是根据我的经验告诉您的意见:充满业务流程逻辑的黑匣子Lambda可能更难以推理,更难以调试,并且使您承担更多责任。在无服务器的世界中,这是一种气味。

我认为,另一种气味是不是事件驱动的代码。 Lambda函数现在最多可以运行十五分钟,并不意味着您应该长时间轮询直到超时。我已经看到这些批处理的Lambda函数运行了14分50秒,然后使用Step Functions在一个循环中重新调用了它们,消耗了数小时的计算,直到完成某些工作为止。如果人们对Lambda编程模型感到满意,我就会明白为什么这样做,但是在我看来,这种情况下外部编排无法提供清晰的信息。这些是长期运行的工作。使用批处理或Fargate。使用Lambda响应事件或处理可预测大小的小工作块。

我认为值得在这里花点时间来分解一下目前在无服务器社区中似乎非常热门的讨论,这是关于应该尝试将多少代码填充到VTL模板中而不是Lambda函数中的讨论。如果您不知道什么是VTL,那么某种程度上它是API网关和AppSync一起提供的一种模板语言。它的真正目的是让您调整传递给后端服务的事件的请求或响应正文。不过,它是一种图灵完备的语言,因此您会看到人们使用它来执行一些相当复杂的逻辑,有时甚至完全代替了Lambda函数。问题是它很难编写和调试,比Python或Javascript或在Lambda上运行的任何版本都要糟糕。 (尽管我会指出,以相反的方式,编写VTL会强制执行我认为更好的卫生条件,以测试无服务器应用程序,该应用程序运行端到端测试而不是单元测试。这是一个单独的讨论,我最近在一个 博客文章 问题是,在什么时候模板代码的简洁性超过了不必打包和交付Lambda函数的价值?这个问题的答案将取决于团队。我个人的经验法则是,当其他人不再清楚VTL在做什么时,您应该停止编写VTL。我知道有些人试图避免放入任何控制语句或任何其他内容,但是我认为那些在正确的上下文中是有道理的。但是这些深层嵌套的循环很难阅读。

我今天要谈的最终气味是更高层次的,并且易于重构。无服务器空间的变化很快,因此最佳实践也是如此。需要我插入API网关的AppSync缺少的两三个功能?我不知道AppSync团队的路线图,但是很可能这些差距将以某种方式填补。关于我们所设想的设计,很酷的事情是,一旦有了更好的选择,对我来说拔出API网关并将DNS记录直接插入到真棒的新AppSync自定义域功能中应该就很容易了。如果我构建了自己的自定义代理解决方案,那可能就不正确了。

看,事实是您不会正确地做出所有这些架构决策。我肯定不会跟踪的内容太多了,我们都在使用不完整的思维模型来研究特定时刻云的功能。但是您可以做的是优化以便于纠正。不要将您的功能和服务相互融合到创建分布式整体的地方。在运行时查找您的服务依赖关系,而不是进行硬编码的假设,可能使用AWS发布的用于服务发现的新Cloud Map Service之类的东西。不要强迫您的客户对与之交谈的后端类型做出假设。无论您建造什么建筑,都会遇到很多问题。让他们成为您可以解决的问题,而不必拆掉所有东西。

因此,总结一下这些气味,这是设计无服务器应用程序时我倾向于寻找的第一件事:我是否过度使用了功能?我的设计中是否有不必要的Lambda?因为我很懒惰并且以最佳的方式享有权利,我如何才能利用服务集成来免费为自己提供功能?这使您回到了乐高积木理想。关于乐高积木,最酷的事情是:除非您做错了什么,否则它们根本不会闻到任何东西。

今天就要做。如果您想在以后的节目中解决问题或话题,可以随时在Twitter @ Trek10inc上访问Trek10,或通过@forrestbrazeal与我联系,我们将在下一期Think中与您见面FaaS。

作者
福雷斯特Brazeal Trek10 191210 171202
阿甘(Forrest Brazeal)