当前位置: 首页 > 科技观察

哪些场景(不)适合使用Lambda

时间:2023-03-13 22:06:17 科技观察

作者|杨航Lambda是AWS推出的基于FaaS(Function-as-a-Service,简称FaaS)的Serverless服务。根据我的项目经验,我发现Lambda不适合或不能独立支持以下场景:用户期望稳定的低延迟请求,需要在多个函数之间跳转以期望大量调用。同时,Lambda与其他AWS服务的结合可以为以下场景提供很好的解决方案:作为监听者,异步响应Webhook(API网关+SQS+Lambda)处理需要延迟或执行的任务指定时间(StepFunctions+SQS+Lambda)Lambda只支持单请求模式,可以考虑使用AWS的AppRunner或者GCP的CloudRun。背景介绍笔者参与的项目大量使用Lambda进行开发。Lambda的作用包括:作为AppServer支持前端功能,监控第三方系统的Webhooks,作为后台程序执行批处理任务等等。在使用过程中,笔者觉得Lambda并不是万能的,有其设计和功能上的局限性。因此,我根据项目的使用和经验,整理了Lambda适合和不适合的场景,分享给大家,供大家在技术上选择。型号供参考。LambdaSingle请求模式的局限性是什么:一个实例一次只能处理一个请求。如果在处理完成之前有新的请求需要处理,Lambda需要创建一个新的实例来处理它。体积:一个函数的解压体积不能超过250MB,这是一个硬性限制;使用Lambda时一定要控制依赖,避免无用的依赖变大,从代码库中提取静态文件等。特别值得注意的是,Lambda运行时自带aws-sdk。除非您需要指定SDK的版本,否则请不要在部署包中包含SDK。并发数:默认一个账号的区域并发限制为1000,即可以同时处理1000个请求;申请AWS可以扩容到几万。如果达到上限,新请求将被限制。在大型项目中,请务必为不同的模块使用不同的账号,以隔离并发需求,避免单个模块的工作量波动影响整个系统的稳定性。ReservedConcurrency可以用来限制单个函数的并发数,但同时会降低没有设置ReservedConcurrency的函数的并发限制。超时时间:最大超时时间为900秒,不可更改;如果在HappyPath中无法判断执行时间小于900秒,则需要拆分Lambda或者使用其他方案。工具:Lambda有特定的部署方式,需要工具来支持,以保证完整的开发流程;可用的工具包括CDK、SAM、Serverless等。Lambda的特色生命周期作为一个Serverless计算服务,Lambda有一个重要的按需创建实例的特性,即在有请求时创建实例进行处理(冷启动)。当实例处理完请求后,会保留一段时间,可以响应后续的请求(热启动)。如果实例空闲超过一段时间,就会被Lambda回收(AWS没有明确提到回收的等待时间)。AWS并未正式给出州的标准名称。这里我们使用非标准术语来描述生命周期,如下图所示:同步vs异步Lambda函数有两种执行模式:同步和异步。在同步模式下,当我们执行一个函数时,Lambda会创建/重用一个实例,并等待实例完成后再返回结果;在异步模式下,Lambda会将请求排队并立即返回,然后在后台创建/重用实例Workwithexamples。使用异步模式时,可以设置重试次数,如果重试仍然失败,可以将失败的请求发送到其他地方,比如SNS的主题。许多AWS服务可以与Lambda集成。您需要查看文档以阐明如何调用Lambda。例如APIGateway以同步方式调用Lambda,CloudWatchEvent以异步方式调用Lambda。Lambda不适用的场景基于Lambda的生命周期,用户期望稳定和低延迟。当有请求需要处理时,如果此时没有可用的实例,Lambda会初始化一个新的实例并使用,即冷启动。结合Lambda单请求模式的特点,意味着必须有相当数量的冷启动,请求的响应时间会和实例初始化时间混在一起,导致延迟波动。根据项目经验,NodeJS实现的一个简单功能的启动时间在1-3秒之间波动;这个区间值来自于CloudWatch的日志输出,实际感知的时间可能会更长,这部分时间会直接暴露给调用者。所以当一个场景需要提供持续稳定的低延迟响应时,同步调用Lambda是不合适的。顺便说一句,实例的启动时间非常重要。例如,一些传统的Java应用程序需要几分钟才能启动。建议不要直接放Lambda。请求需要在多个实例间跳转如果一个请求需要同步在多个实例间跳转,最坏的情况下,请求的延迟会成倍增加,并发数也会增加一倍。以项目经验为例,有一个API网关->功能A->功能B->第三方系统的接入链接。在测试环境下(用的人少,流量波动大),从页面调用这个接口的时间基本在8秒以上,有时候10多秒,让客户怀疑是有问题系统的性能。采用网状结构设计的微服务模型应用需要服务间频繁同步通信,所以在放置Lambda时要谨慎。预计会有大量呼叫。如果一个接口有大量的调用,基于效率和成本的考虑,Lambda可能不是一个合适的选择。从一般原则来看,如果一个接口有大量调用,为每个调用分配一个独占实例显然不是一个明智的选择,这会显着增加单个实例的边际开销。在这种情况下,增加单个实例可以同时处理的调用数,可以有效提高系统吞吐量,提高系统的整体效率。在价格方面,Lambda采用了按调用次数计费的模式。当调用次数增加到一定阈值以上时,其成本效益肯定会低于按资源使用时长计费的模型。我们用一个虚拟的场景来对比一下Lambda和AppRunner:假设有一个接口,每天忙时3小时处理600个RPS调用,另外12小时非高峰时间处理60个RPS调用,其余的时候不打电话;每次通话持续500毫秒。两种服务的价格对比如下:Lambda:基于128M内存的配置,每天有600*60*60*3+60*60*60*12=9072000次调用,所以月费为$335.76.有兴趣的读者可以使用AWSPricingCalculator自行计算。AppRunner:基于1个vCPU和2G内存的配置,假设每个实例可以同时处理60个请求。当超过60个请求时,将创建一个新实例来处理它们。那么高峰时段每天的费用为2.30,非高峰时段为0.77,无通话时间为0.34,每月总计102。对成本细节感兴趣的读者请前往AppRunnerPricing页面上的Example3:Highvolumeproductionapp。Lambda适合的场景是作为监听器异步响应Webhooks。很多第三方系统都提供了用于通知的Webhooks,一般Webhooks都是异步设计的。该场景可以通过APIGateway、SQS和Lambda提供解决方案。下面我们根据AWS的5大支柱来分析一下为什么这是一个很好的解决方案:可靠性:APIGateway加上SQS可以保证足够的高可用性,提供稳定的低延迟,这对Webhooklisteners来说非常重要。在webhook设计中,如果监听器不能在短时间内提供响应,可能会被认为是不健康的,从而导致监听器被限制或阻塞。PerformanceEfficiency:以上服务提供了足够的可扩展性,确保监听器能够应对较大的流量变化。一般不需要提前预测流量来准备基础设施。成本优化:上述服务均为Serverless服务,可按实际使用量付费,无需支付基础设施费用。安全:API网关和SQS自动提供HTTPS协议,保证数据传输安全;SQS和Lambda可以通过IAM保证访问控制,APIGateway可以通过Authorizer或者APIKey实现访问控制。卓越运营:以上设计完全可以通过InfrastructureasCode部署,无需人工操作。处理需要延迟或在指定时间执行的任务。有时任务需要等待一段时间才能执行,或者在特定的时间执行。与使用Long-run服务定期扫描和处理相比,StepFunctions,SQSPlusLambda提供了更高效的解决方案。前面提到的优点不再赘述,这里补充一些对StepFunctions的解释。StepFunctions是AWS提供的无服务器状态机服务,其中包括等待状态,最长可达1年;AWS保证等待的可靠性。StepFunctions结合Lambda可以设置单个任务的处理时间,无需扫描和批量处理任务。StepFunctions根据状态变化收费。等待时状态不变,不收费,有效降低成本。写在最后,Serverless的特性决定了实例无法避免冷启动。Lambda支持同步和异步调用模式。根据项目经验,同步调用方式受冷启动影响较大,有时会通过SQS将调用封装成异步方式。Serverless工具中甚至还提供了ServerlessWarmUpPlugin,通过定时调用来避免冷启动。AWS还提供ProvisionedConcurrency功能来维护热实例并减少冷启动次数。Lambda的单一请求模式是一个很大的限制,它不仅限制了实例的性能(比如使用NIO),而且导致实例需要更频繁地初始化。能够更改单一请求模型以便一个实例接受更多请求将是一个很好的功能。Lambda有一个独立的生态系统,对代码和部署有特定的要求,这降低了代码的可移植性。有更好的选择吗?作者推荐读者参考GCP的CloudRun服务,它提供了一种容器即服务(CaaS)的解决方案,可以以Serverless的形式部署镜像。通过指定实例的请求并发数,可以显着减少新实例的初始化。频率。AWS也提供类似的服务AppRunner,但目前仅在美国、爱尔兰和日本地区可用。