编写第一个Lambda函数:Hello World
好,到了真正动手的时候了。这一章我们写第一个Lambda函数,说白了就是个"Hello World"。但别小看它——事件对象、上下文、日志输出这些核心概念,都会在这一小段代码里串起来。写完这个,你对Lambda的理解就不会只是"哦,一个云函数"了。
创建函数的两种姿势
我个人习惯在AWS控制台里先跑通,再用CLI或IaC去固化。初学者直接上控制台,路径是:
- 进入Lambda服务首页
- 点「创建函数」
- 选「从头开始创作」
- 函数名称:
HelloWorldDemo - 运行时:Python 3.12(或你环境里最新的3.x版本)
- 架构:x86_64就够,ARM便宜但第一次用没必要折腾
- 权限:保持默认「创建基础Lambda执行角色」
点完创建,你就能看到内置代码编辑器了。这时候别急着写代码——先看看默认模板长什么样。
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
嗯,这就是Lambda函数的骨架。重点在函数签名:event和context两个参数,缺一不可。
事件对象:Lambda的输入信号
event说白了就是触发你的那个"事"。它可以是API Gateway传过来的HTTP请求,可以是S3新文件的通知,可以是CloudWatch定时器。具体长啥样?触发源说了算。
你想想看,如果是一个定时巡检任务,那event里可能只带一个时间戳。但如果是来自API Gateway,那body、headers、queryStringParameters全都有。
我在项目中遇到过最奇葩的event——某个第三方服务把XML当JSON传过来了,解析直接炸了。所以第一条经验:永远不要假设event结构。打印出来看才最稳。
上下文对象:函数的运行环境快照
context里装的不是业务数据,而是"我是谁、还剩多少时间、日志组是哪个"这类运行时信息。我刚开始用Lambda时压根不看它,直到有一次函数超时了,才发现context里早就警告了剩余时间。
| 属性/方法 | 类型 | 说明 | 我的常用场景 |
|---|---|---|---|
function_name |
字符串 | 当前函数名 | 日志里标记来源 |
function_version |
字符串 | 函数版本($LATEST或具体数字) | 版本回滚时排查 |
invoked_function_arn |
字符串 | 完整ARN | 跨账号调用时校验身份 |
memory_limit_in_mb |
整数 | 分配的内存大小 | 性能分析时看是不是内存太小 |
aws_request_id |
字符串 | 该次调用的唯一ID | 关联日志和异常追踪 |
log_group_name |
字符串 | CloudWatch日志组名 | 直接跳转到对应日志组 |
log_stream_name |
字符串 | 日志流名 | 并发高时区分不同实例 |
get_remaining_time_in_millis() |
方法 | 返回剩余毫秒数 | 超时前做清理或回退 |
注意那个get_remaining_time_in_millis(),我在一个数据处理任务里用过它——如果剩余时间不足10秒,就保存当前进度并提前退出,避免数据写到一半被粗暴杀掉。这个技巧在定时巡检里很实用,因为巡检任务经常要扫大量资源,一下跑不完。
日志输出:CloudWatch是你唯一的朋友
在Lambda里不能用print大法慢慢看终端,因为根本没有终端。所有标准输出(stdout和stderr)会自动写入CloudWatch Logs。所以你写print(...)其实也能用,但官方推荐用logging模块。
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("函数开始执行")
logger.info(f"事件内容: {json.dumps(event)}")
logger.info(f"剩余时间(ms): {context.get_remaining_time_in_millis()}")
# 你的业务逻辑放这里
name = event.get('name', 'World')
message = f"Hello, {name}!"
logger.info(f"返回消息: {message}")
return {
'statusCode': 200,
'body': json.dumps({'message': message})
}
logging.setLevel(logging.DEBUG)忘了改成INFO,结果一个函数一天写了10GB日志,CloudWatch账单直接飙上去。建议生产环境至少用INFO级别,DEBUG只在开发测试时开。另外,《定时巡检》场景下日志量会随着巡检频率线性增长,一定要注意控制。
完整的Hello World(带参数版)
下面这个版本集成了一开始提到的三个核心点。你可以直接复制到编辑器中,然后创建一个测试事件:
{
"name": "行云"
}
点「测试」——控制台会立即返回结果,同时CloudWatch里会多一条日志流。去CloudWatch控制台找到对应的日志组(名字就是/aws/lambda/HelloWorldDemo),点开最新日志流,你就能看到我们写的INFO日志了。
本章核心知识图
下面的SVG把函数调用时的数据流画出来了,看一眼能帮你理清事件、上下文、日志之间的协作关系。
最佳实践清单
- 日志分级:线上用INFO,故障排查时临时开DEBUG,完事改回去
- 打印event:每次新对接触发源,第一件事就是
logger.info(event),看清结构再写解析代码 - 关注剩余时间:长任务里定期检查
context.get_remaining_time_in_millis(),别让Lambda死在半路 - 测试事件别删:至少保留一个测试case,后面重构时一键验证
- 别在代码里拼日志组名:直接用
context.log_group_name,万一运维改了命名规则呢?
写到这里你已经有一只脚踏进Lambda的大门了。接下来我们需要给它装上定时器——CloudWatch Events。那才是定时巡检自动化的真正起点。