SageMaker 推理在 Lambda 里卡了 4 秒:删掉两个配置后成本降了 80%
SageMaker 推理在 Lambda 里卡了 4 秒:删掉两个配置后成本降了 80%
项目上线前一周,组长丢来需求:每天凌晨从 S3 拉当日新数据,跑一遍风控模型,把预测结果写回 DynamoDB。听起来就是个简单的定时任务--我第一个想到的就是 Lambda + Amazon SageMaker 实时端点。
用 CodeWhisperer 写调用代码时确实很爽,注释里写一句"调用 SageMaker endpoint 做批量预测",它就把invoke_endpoint的样板给我补全了。但第一次部署到 CloudWatch 定时触发后,执行日志直接红了半边:每次 Lambda 启动时冷启动 4.3 秒,端点的响应延迟又吃掉 1.8 秒,总时长逼近 7 秒。更糟的是,Amazon SageMaker 实时端点只要开着就按小时计费,即使每天只用那 3 分钟,一个月账单额外多出 230 美元。我一开始根本没意识到,Serverless 不是"免运维",是"你要懂该用哪种 Serverless"--这个认知的转变,是从学了 AWS 基础知识之后才真正生根的。
当时的思路:CodeWhisperer 生成代码,我负责踩坑
接到需求时我信心很足:Lambda 的 Python 运行时配 Amazon SageMaker 的 Serverless Inference 端点,连实例都不用管。用 CodeWhisperer 写调用代码时,我只花了一个下午就把整个流程跑通了:
import boto3 import json import os runtime = boto3.client('sagemaker-runtime') ENDPOINT_NAME = os.environ['SAGE_ENDPOINT'] def lambda_handler(event, context): # CodeWhisperer 生成:从 event 中解析 S3 桶和键 bucket = event['Records'][0]['s3']['bucket']['name'] key = event['Records'][0]['s3']['object']['key'] # 从 S3 读取数据、预处理... payload = json.dumps({"instances": features}) response = runtime.invoke_endpoint( EndpointName=ENDPOINT_NAME, ContentType='application/json', Body=payload ) result = json.loads(response['Body'].read()) # 写入 DynamoDB这段代码在本地测试时完美通过,但我忽略了三件事:Lambda 冷启动要拉代码包、初始化 boto3 客户端;Amazon SageMaker Serverless 端点本身有冷启动;以及定时触发任务根本不适合用同步实时端点。当时我的机器学习基础几乎为零,只知道模型能预测,不知道"预测"还有实时、异步、批量三种模式。后来补机器学习基础课程时,讲师第一课就用一张表把这三种模式的区别讲透了--实时端点面向在线业务,需要毫秒级响应,异步推理适合大文件,批量转换才是我这种定时离线场景的正解。如果早一点学过,根本不会犯这种错。
第一波翻车:冷启动叠加成本失控
上线后第一个凌晨,CloudWatch 日志就报了三个问题:
- 首次调用冷启动:Lambda 初始化耗时 4.3 秒,其中 2.1 秒花在下载 zip 包和解压依赖。
- SageMaker 端点同样冷启动:Serverless 端点在无流量时会缩容到零,重新启动需要 1~3 秒。
- 成本:我开了预留并发想解决冷启动,结果 Lambda 的预留并发按时计费,加上 Amazon SageMaker 端点的实例时间,整月额外多付了将近 250 美元。
当时我试着用 CloudWatch 的日志告警去监控延迟,但告警治标不治本。又尝试把 Lambda 内存拉到 2GB,冷启动降到 2.8 秒,但成本反而更高。那个周末我翻文档翻到 Amazon SageMaker 的 Batch Transform 功能--一行 API 调用就能起一个批处理任务,不用长久开着端点,也不用关心并发。但问题是,我之前连 Batch Transform 的存在都不知道,这正是机器学习基础课程里反复强调的"模型部署阶段"的知识盲区。学机器学习基础时,第二章专门讲模型交付和部署选型,从实时端点、边缘推理到批量转换,每种模式的适用场景、成本结构和延迟特性都给得明明白白,学完后我立刻就能判断自己的业务最适合哪一种。
重构:从实时到批量,六行改动省掉的 80% 成本
搞清概念后,周末我把 Lambda 里的代码重写了。核心变动就六行--把invoke_endpoint替换成create_transform_job,让 Amazon SageMaker 自己去跑一个批处理作业:
sagemaker = boto3.client('sagemaker') TRANSFORM_JOB_NAME = f"daily-risk-{datetime.now():%Y%m%d}" MODEL_NAME = os.environ['SAGEMAKER_MODEL'] S3_OUTPUT = "s3://my-bucket/predictions/" def lambda_handler(event, context): # ...从 event 解析 S3 输入路径... response = sagemaker.create_transform_job( TransformJobName=TRANSFORM_JOB_NAME, ModelName=MODEL_NAME, BatchStrategy='MultiRecord', TransformInput={ 'DataSource': {'S3DataSource': {'S3DataType': 'S3Prefix', 'S3Uri': s3_input}}, 'ContentType': 'text/csv', 'SplitType': 'Line' }, TransformOutput={ 'S3OutputPath': S3_OUTPUT, 'AssembleWith': 'Line' }, TransformResources={'InstanceType': 'ml.m5.large', 'InstanceCount': 1} )这批改动的效果立竿见影:
- Lambda 冷启动降到 780ms--因为不再需要初始化 sagemaker-runtime 客户端去建长连接。
- 不再需要 Amazon SageMaker 端点常驻,凌晨那几分钟的批处理作业跑完即焚,整月成本从 230 美元降到 42 美元,降幅正好 82%。
- 任务从"每次数据变更触发"改成了"一次批量处理当日全量文件",DynamoDB 写入次数也降了 60%。
这次重构让我对机器学习管道有了更深刻的体感。之前我只关注模型训练和评估,从不觉得"部署"有什么技术含量。学完机器学习基础我才明白,特征工程、数据预处理、超参调优和部署监控是一整条链,部署选型错误会直接让前面所有优化打水漂。现在我再接到类似需求,第一时间想的不是写什么代码,而是先问自己:这是在线还是离线?同步还是异步?模型大小和 S3 数据量是多少?这些问题,机器学习基础课里都给了决策框架。
引入 CodeWhisperer 后我改掉的三个坏习惯
第二次重构时,我学乖了,不再让 CodeWhisperer 直接生成完整 Lambda 函数,而是先手写一个"意图草稿":
# 目标:触发 SageMaker 批处理任务 # 输入:S3 事件触发,获取输入文件路径 # 输出:创建 SageMaker Transform Job,不等待结果 # 约束:Lambda 超时 30 秒,任务名必须唯一然后才让 CodeWhisperer 在框架内补充细节。这个习惯是在学 CodeWhisperer 课程时养成的--讲师一再强调,AI 辅助编程不是"让它写",而是"告诉它边界",否则生成的代码会默认最通用的写法,容易忽略冷启动、超时和成本这些工程约束。CodeWhisperer 课程里有一节专门讲如何用注释约束生成范围,以及如何检查生成的 API 调用是否符合 Well-Architected 原则。学完后我写代码时注释量翻了倍,但返工率降了至少七成。
现在回头看,如果早点学过 CodeWhisperer 课程,第一次写 Lambda 代码时就不会一股脑接受它写的invoke_endpoint,而是会先评估这个 API 是否适合定时任务场景。AWS CodeWhisperer 本身是强大的助手,但需要使用者有足够的基础知识才能用好,而这些基础知识正是亚马逊云科技的一系列在线课程提供的--从 AWS 基础知识到机器学习入门,再到深度学习基础,每一门课都在填补"会用工具"和"用对工具"之间那条裂谷。
这次踩坑教会我的五件事
复盘整个项目,核心教训其实都是基础知识不牢导致的。以下五点现在成了我带新人时必讲的清单:
- 先判断任务类型再选服务:实时端点、异步推理、批量转换、边缘推理四种模式各有用武之地。机器学习基础课程用一整章讲这个决策树,建议任何要动手的人先去翻一遍。
- Lambda 冷启动不是靠堆内存解决的:包体积、初始化逻辑、客户端连接方式都影响启动时间。AWS 基础知识中关于 Lambda 性能优化的模块给了一套量化分析方法。
- S3 触发 + Batch Transform 是离线推理的最优解:不需要常驻端点,成本极低。深入了解 Amazon SageMaker 的 Batch 特性后,我才意识到很多应用根本不需要实时端点。
- AI 编程助手的输出必须被约束:CodeWhisperer 能加速开发,但如果不先学会如何给它设定边界,生成的代码往往是最安全但也最贵的方案。CodeWhisperer 课程教的"注释驱动开发"方法,值得花一个下午系统学一遍。
- 成本是设计出来的,不是优化出来的:第一次上线时多花的 250 美元完全是因为选型错误。补完机器学习入门和 AWS 基础知识后,我在做架构设计时就能预估每个方案的成本区间--这个能力在面试和实际项目中都是硬通货。
后来有同事问我,为什么花时间学那么多基础课而不是直接看文档。我说,文档教你怎么做,课程教你怎么判断要不要那么做。就像这次,如果不是在机器学习基础里看到了模型部署的四种模式对比,我可能到现在还在用实时端点硬扛每天凌晨那三分钟的任务。
如果你也正准备把模型部署上线,我建议先至少过一遍 Amazon SageMaker 的官方学习路径和 AWS 基础知识,然后在 CodeWhisperer 课程里挑一两节关于"约束生成"的内容。这三门课加起来大概两周能学完,但节约的成本和踩坑的时间,可能是你接下来一整年的额度。
