第二章:AWS Lambda 基础:函数、触发、执行环境
好,咱们进入正题。
构建日志巡检自动化,Lambda 是的核心。你想想看,我们平时要处理日志,要么写个脚本轮询,要么搭个服务一直跑着。但 Lambda 不一样——它只在需要的时候运行,没事件进来就安静待着,不花你一分钱。这一点对日志处理这种“间歇性”任务来说,简直是绝配。
我个人习惯把 Lambda 理解成“事件驱动的微函数”。说白了就是:你把代码扔上去,不用操心服务器,有事件触发它就跑,跑完就停。今天我们就来拆解它的三个最核心的部分:函数、触发、执行环境。
函数:你交付的核心载体
Lambda 函数本身就是一个独立的代码包,包含你的处理逻辑。创建函数时,你需要指定运行时、处理程序入口,以及 IAM 角色。这些东西,少一个都不行。
代码结构上,我建议你保持整洁。Lambda 的 handler 函数长这样:
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# 日志巡检的核心逻辑
logger.info("收到事件: %s", json.dumps(event))
for record in event.get('Records', []):
# 处理每条日志
process_log(record)
return {
'statusCode': 200,
'body': '日志处理完成'
}
你可能会问:“这个 lambda_handler 是固定的吗?” 嗯,其实你可以自定义,但我建议保持默认命名,至少团队里大家都懂。
logger 放在函数外部,这样冷启动时只初始化一次,避免每次调用都重设日志级别。
触发:让函数“活”起来
函数写好了,但没人调用它就跑不了。触发方式主要分两类:同步触发和异步触发。
我这里用一个表格给你对比清楚:
| 触发方式 | 典型服务 | 使用场景 | 重试行为 |
|---|---|---|---|
| 同步 | API Gateway、ALB | 实时响应,比如用户查日志状态 | 客户端负责重试 |
| 异步 | S3、SNS、CloudWatch | 日志上传后自动处理 | Lambda 自动重试 2 次 |
| 流式 | DynamoDB Streams、Kinesis | 持续消费日志流 | 根据批次失败策略 |
执行环境:函数“跑”在哪里
这才是 Lambda 最“黑盒”的地方。每次调用,AWS 会启动一个容器或者复用已有的容器。这就是我们常说的冷启动和热启动。
核心概念有这几个:
- 容器隔离:每个函数运行在独立的沙箱里,安全可靠。
- 生命周期:从 Init(初始化)到 Invoke(调用)再到 Shutdown(销毁),通常是分钟级。
- 超时限制:最大 900 秒(15 分钟)。对于日志巡检这个场景,通常几秒钟就搞定,但如果你要处理大文件,注意别超时。
- 内存与 CPU:你分配 128MB 内存,CPU 份额也跟着增加。我个人的经验是,日志解析这种 IO 密集型任务,512MB 基本够用,太大浪费钱。
我曾在项目里调试一个诡异的“偶发性超时”问题。后来发现,冷启动时如果加载了大的依赖包(比如 pandas),第一次调用很可能超时。解决办法?要么预热,要么优化依赖——说白了就是砍掉不用的库。
核心逻辑:一张图看懂
下面这张图展示了 Lambda 三要素之间的关系:事件源触发函数,函数在执行环境中运行,输出结果给下游或直接返回。
你看这个流程。事件源可能是 CloudWatch Logs 把日志推过来,或者 S3 触发了上传事件。Lambda 接过来,在隔离的执行环境里跑你的处理函数,最后输出结果。整个过程没有服务器,没有固定的进程,只有逻辑。
实际启用时的几个要点
- 权限最小化:给 Lambda 的 IAM 角色只授予必要的权限,比如只读 CloudWatch Logs、写入 S3。
- 环境变量:把日志路径、告警邮箱等配置存到环境变量里,别硬编码。
- 监控:打开 CloudWatch 指标,关注
Invocations、Errors、Duration。
我还记得刚上手 Lambda 那会儿,觉得“无服务器”就是什么都不用管。结果有一次线上函数因为执行环境内存不足被 OOM kill 了,日志里只留下一个 Task timed out。后来才发现,内存给得太少,处理大日志文件时直接挂掉。从此之后,我每次上线前都会压测一下。
好了,Lambda 三要素就先说到这儿。你掌握了函数怎么写、触发怎么配、执行环境怎么理解,后面构建巡检自动化就轻松多了。