Serverless的4种错误打开方式
自2014年AWS发布Lambda以来 , Serverless技术的采用率逐年上升 。 这是因为Serverless提供了云服务开发人员无法抗拒的产品 , 其主要优势如下:
将服务器管理的工作抽象给了供应商随用随付模式 , 您只需要为你使用的量来付费可自动扩展并且高可用这些好处是通过这种技术具备的一些特性来实现的 。 Serverless的应用程序是无状态的分布式系统 , 可以根据需求进行扩展 , 提供的是基于事件的异步开发模式 。 正是因为这些特性 , 这种技术才为云环境提供了理想的解决方案 。
不过 , 它是否真的像期望的那样理想吗?
经过进一步的调查可以发现 , 毫无疑问 , 在Serverless的应用过程中 , 很多开发者也陷入了该模式的一种反模式里面 , 特别是那些高度利用Serverless的场景 。 随着越来越多的行业从中获得好处 , 我们必须要清醒地认识到哪些东西是有效的 , 哪些是无效的 。 毫无疑问 , Serverless是有效的 , 不过错误的使用方式也会让它引发很多问题 , 使行业远离此项技术 。
因此 , 本文的主要目的是揭示那些困扰Serverless体系架构的反模式以及如何规避他们 , 从而推动Serverless应用的成功 , 提升其采用率 。
异步特性中的瑕疵在异步的场景中 , Serverless应用程序往往最合适 。 埃里克·约翰逊(EricJohnson)在伊斯坦布尔ServerlessDays演讲中提出了一个概念 , 即“Serverless的异步思考方式” 。 之后 , 他去了ServerlessDaysNashville上发表了更长的演讲版本 。
不过 , 受到追捧的异步特性也是其最大的反模式 。 在理解这句话之前 , 你需要记住 , Serverless是即付即用的模式 。 因此当一个function(译者注:Serverless中 , 每个函数被称为function , 下同 。 )或者一个服务在等待另一个异步调用的function或者服务返回响应结果时 , 第一个function是处在空闲状态的 。 只需要等待第二个function的响应即可 。
这是从单体架构转换到无服务架构过程中 , 不关注细节导致的结果 。 例如 , 在一个单体的系统中 , 一个方法可能需要执行读写DynamoDB的操作 。 然而 , 为了避免等待此项操作而阻塞整个控制流 , 可以使用异步的方式进行调用 。 允许该方法继续调用另一个方法执行其他任务 , 只是在方法的最后等待DynamoDB的响应结果 。 第二个方法可能是按照自己的方式开始操作S3 。
当上面的逻辑迁移到Serverless上面时 , 不能用相同的方式处理 。 因为每个方法会映射到每个单独的Serverless的function上面 , 但是你需要记住的是 , 每个function都有可能会超时 , 又或者只完成了他们剩余的任务 , 之后变成空闲状态等待回调 。
结果就是这个处在空闲状态的function也会被收费 , 因为在技术层面上它是活跃状态的 。 尽管function只是在等待 , 仍有一个worker节点使用所有必需的基础架构为该function提供服务 。
当很多function连接在一起的时候 , 这个问题会更加严重 。 在流程中 , 一个function对另一个function进行异步调用 , 等待响应 , 而第二个function对另一个function进行调用 , 又或者在对存储服务进行读写操作 。
解决方案并不是放弃异步的模式 , 因为问题的关键点不在于异步调用 , 而是在于合并此类调用的方式 。 例如 , 在分解单体系统时 , 通常存在控制器的function , 这只会增加不必要的开销 , 而且还会增大超时带来的function不可靠的概率 。
共享不是收养使用Serverless进行构建的目标是 , 用独立的且高度分离的function , 来拆解业务逻辑 。 不过说起来容易做起来难 。 而且开发人员经常会遇到必须在function之间共享某些库或者业务逻辑 , 又或者只是一些基础代码的场景 。 从而导致了某种程度的依赖和耦合关系 , 违背了Serverless架构的初衷 。
不同的function之间依赖于一些共享的代码和逻辑 , 会带来一系列的问题 。 最突出的问题就是影响到了伸缩性 。 随着系统规模和功能之间不断地相互依赖 , 错误、停机和延迟的风险成倍增加 。 微服务诞生的出发点就是要避免这些问题的 。 此外 , Serverless的一大卖点也是它的可扩展性 。 通过共享逻辑和代码库将功能耦合在一起的系统不仅不利于微服务 , 而且不利于Serverless可伸缩性的核心价值 。
下图描述了这个场景 , 因为functionA中数据逻辑的变更 , 导致functionB中 , 数据通信和处理方式也要发生必要的改变 。 根据实际的使用情况 , functionC也可能会受到影响 。
在大多数情况下 , 共享代码库和逻辑需求不仅是一种反模式 , 而且也同样是Serverlessfunction的一种技术限制 。 例如 , AWS的Lambdafunction在/tmp目录下存储上的限制是512MB 。 这意味着 , 开发人员在构建他们AWSLambdafunction代码的时候 , 必须要意识到这件事情并且合理运用 。 毕竟 , /tmp目录主要用于临时存储 , 因此 , 一旦serverless节点被移除 , /tmp目录下的内容也会不复存在 。
AWS最近通过发布备受期待的AmazonEFS和AWSLambda集成解决了这个问题 。 这种新的集成方式允许function通过集成AmazonEFS实例的方式 , 访问共享的类库或者数据 。 然而 , 这不能成为function之间相互依赖合理性的一种依据 。 目前可以实现某些事情并不意味着它是上述反模式陷阱的最佳解决方案 。
Serverless的主要目标是将复杂的基础架构抽象化 , 从而让人们把更多的关注重点放在业务逻辑上面 。 但是很明显的是 , 随着业务逻辑被拆分成各个function , 慢慢达到了平衡点 , 额外开销也开始逐渐超过了拆分带来的收益 。 因此这种情况可以被列为一种反模式 。
解决方案
云供应商已充分认识到使用无服务器function的开销 。 例如 , AWS发布了serverlesseventbus服务——AWSEventBridge 。 该服务减轻了与function之间传递事件有关的问题 , 甚至允许第三方工具将事件发送到AWS架构 。 但是 , 这不能完全解决问题 。
想要找到解决方案 , 需要先知道什么场景会出现这种问题 。 使用serverless的function来提高开发便捷性这件事已经是众所皆知了 。 构建function相对来说非常容易 , 因此开发人员更倾向于不断创建新的function , 导致了过度设计 。
【Serverless的4种错误打开方式】因此解决方案应该从开发过程开始的时候 , 就开始对架构设计进行思考 , 并且深入理解业务逻辑 。 这可以先分析客户预期如何使用应用程序 , 根据其使用的场景来考虑性能问题以及用例 , 从而实现需求 。
主要的目标还是了解用户期望采用的流程 , 以及在哪个区域的应用程序期望承受更高的负载 。 因此 , 对这些要求更为清晰的了解将有助于确定实际所需要的function以及它们的作用域 。 当务之急是与产品经理或其他人一起 , 制定出业务的目标和流程 。
递归可不是朋友递归是计算机科学中不可或缺的一个概念 , 它会降低计算机计算时的复杂性 , 相关的文献中广泛使用的“大O表示法”就是递归的典型应用 。 不过在serverless中 , 递归可能产生无法预期的影响 。 特别是它的伸缩性会极大地加剧这种影响 , 应该抵制使用递归 , 尤其是在递归算法导致无限递归的场景 。
在对容器或其他以CPU为中心的实例进行编程时 , 核心问题在于 , 由于递归会增加处理能力 , 从而使CPU利用率达到最大化 。 一个个function会不断地自我触发 , 这可能导致在各个线程中触发的function数量呈指数增长 。
在Serverless的场景下 , 实例的CPU利用率达到最大并不是问题 , 因为它可以自动伸缩 。 从理论上讲 , 可以增加无限数量的工作节点 , 甚至可以满足最严格的递归算法的需求 。 但是 , 从成本的角度出发 , 递归会导致DoW(DenialonWallet)的攻击 。
时刻需要记住 , 在Serverless的场景下 , 计费里面不止包含计算能力 , 还包括调用和运行时间 。 结果就是递归导致你云供应商收费激增 。 选择Serverless模式是为了节约成本 , 而这种使用方式却抵消了这种优势 , 你以为费用下降了 , 但实际却恰恰相反 。
解决方案
显而易见的解决方案是在构建无服务器应用程序时注意代码库中的递归算法 。 但是 , 可能有些应用程序仍需要递归操作 。 例如 , 在机器学习的应用中 , 重复训练模型直到在训练数据或验证数据上达到一定有意义的精度 。 但是 , 问题是可以提供多少次递归?
就像前面说的 , 递归函数最大的威胁点是无限递归的可能性 。 不过在大多数情况下 , 这是一种意料之外的结果 , 程序理论上不需要特殊处理无限递归 。 因此如果需要使用到递归 , 请确保进行严格的测试 , 尽可能完全避免这种问题 。
此外 , 您也可以在自己的function之间传递数据 , 以保持一个递归计数 , 并设置一个失效保护的开关 , 以便当递归计数达到一定的数量时停止正在运行的function 。 这将使系统知道递归发生的次数 , 并允许可配置的限制随着时间的推移而变化 , 同时考虑到无服务器应用程序的成本和其他因素 。 这样你的系统就知道递归实际发生的次数 , 并允许配置一个限制 , 可以随着时间的变化而变化 , 同时牢记成本和无服务器应用程序的其他因素 。
结论无服务器无疑正在彻底改变应用程序在云服务上面的构建方式 。 但是 , 随着这种新模型和体系结构的出现 , 它具有了自己独特的反模式 。
如果不小心谨慎的话 , 这些反模式很容易浮现 , 抹去选择无服务器架构获得的所有好处 。 实际上 , 根据问题的严重性 , 无服务器架构可能对业务应用程序有害无益 。
但是 , 该技术的优势极大地促进了其应用 。 因此多年来 , 云社区已经看到了很高的采用率 。 我们有必要积极了解如何在无服务器场景下构建软件 , 同时注意避免反模式 。 俗话说 , 强大的力量伴随着巨大的责任!
原文链接
关注我并转发此篇文章 , 私信我“领取资料” , 即可免费获得InfoQ价值4999元迷你书!
推荐阅读
- 养老金|2021年上半年办理退休,养老金核算的这些知识要把握
- 量化|量化大师麦教授:美好的不确定性
- 浪胃仙|泡泡龙的离世给所有吃播提了醒,浪胃仙顺势决定“转行”,新职业认真的吗?
- 脑梗死|脑梗死和喝酒有没有关系呢?爱喝酒的朋友,应该看看
- 米歇尔·戴斯玛克特|海奥华预言的真相,地球人被带到九级文明,揭开神话背后的秘密
- 减肥也能吃的小零食,营养美味,低脂低热量,多吃也不怕!
- 1碗面粉,不加水,锅里蒸一蒸,做香甜可口的发糕,比蛋糕还香
- 扇贝最好吃的做法,适合冬日里吃,做法简单好吃不腻,家人超爱吃
- 七种颜色的布丁吃过没有?软糯爽口,Q弹软糯
- 爱吃南瓜饼的收藏,外酥里嫩,香甜软糯,饭桌上必备,做法超简单
