Serverless 应用的运维:监控、日志与问题排查
经过前面的学习和实践,代码跑起来了,API 也能访问了,是不是感觉可以高枕无忧了?
等等!一个常见的误解是 Serverless 等于 "NoOps" (无运维)。实际上,这并非完全正确。虽然你摆脱了繁琐的服务器管理(打补丁、扩容、监控 CPU/内存使用率等),但应用的健康运行、性能优化、问题排查等运维职责依然存在。我们通常称之为 "LessOps" (更少运维) 或者 "DifferentOps" (不同的运维)。
在 Serverless 世界里,运维的重心从管理服务器转向了管理应用本身及其配置、成本、安全以及最重要的——可观测性 (Observability)。没有良好的可观测性,你的 Serverless 应用就是一个黑盒子,一旦出现问题,你将束手无策。
那么,如何给你的 Serverless 应用装上“透视眼”和“听诊器”呢?主要依靠三大支柱:指标 (Metrics)、日志 (Logging) 和追踪 (Tracing)。
云原生的监控体系:三大支柱
AWS、Azure、Google Cloud 等主流云平台都提供了强大的原生监控服务,与它们的 FaaS 和 BaaS 服务深度集成。以 AWS 为例,我们主要会用到 Amazon CloudWatch (用于指标和日志) 和 AWS X-Ray (用于追踪)。
1. 指标 (Metrics):应用的“仪表盘”
指标是衡量应用运行状况的数值型数据。对于 FaaS 函数(如 AWS Lambda),一些关键指标可以告诉你很多信息:
- 调用次数 (Invocations): 函数被触发了多少次?可以反映业务负载。突然的飙升或下降都可能意味着问题或变更。
- 执行持续时间 (Duration): 函数每次执行花了多长时间?通常关注平均值 (Avg) 和百分位值 (如 P95, P99)。持续时间过长可能影响用户体验或增加成本。P99 指标升高通常能暴露长尾延迟问题。
- 错误次数 (Errors): 函数执行失败了多少次?这是最直接的问题指标。需要关注错误率(错误次数 / 调用次数)。
- 并发执行数 (ConcurrentExecutions): 同一时刻有多少个函数实例在运行?可以帮你了解应用的并发处理能力和是否接近并发上限。
- 限制/节流次数 (Throttles): 由于达到并发上限或其他限制(如 API Gateway 速率限制),导致多少次调用被拒绝?这是系统瓶颈的重要信号。
在哪看? 在 AWS Lambda 控制台,选择你的函数,切换到 “监控” (Monitor) 标签页,就能看到 CloudWatch 自动收集的这些关键指标图表。
2. 日志 (Logging):问题的“记录本”
当指标告诉你“出错了”,日志则能帮你找到“错在哪”以及“为什么错”。
- 为什么重要? FaaS 函数的执行环境是短暂的,你无法登录上去查看。日志是了解函数内部执行细节的唯一途径。
- 记什么?
- 关键业务逻辑的执行点和结果。
- 收到的输入事件 (
event
对象) 的关键部分(注意脱敏)。 - 调用外部服务(如数据库、其他 API)的请求和响应(关键部分)。
- 错误信息和堆栈跟踪 (Stack Trace)! 这是排查 Bug 的关键。
- 怎么记?
- 使用你所用语言的标准日志库或
console.log
/print
等。 - 强烈推荐结构化日志 (Structured Logging): 将日志输出为 JSON 格式,包含时间戳、日志级别、请求 ID、消息内容等字段。这极大地便于后续的自动化分析和查询。
// Node.js 示例: 输出 JSON 格式日志
console.log(JSON.stringify({
level: "INFO",
requestId: event.requestContext?.requestId, // 获取请求 ID (如果可用)
message: "Processing user registration",
userId: user.id
}));
- 在哪看/查?
- 默认情况下,AWS Lambda 函数的
console.log
输出会发送到 Amazon CloudWatch Logs。 - 在 Lambda 控制台的“监控”标签页点击“查看 CloudWatch 中的日志”。
- 使用 CloudWatch Logs Insights,你可以用类似 SQL 的查询语句在海量日志中快速搜索、过滤和分析。例如,查找某个请求 ID 的所有日志,或者统计某个时间段内 ERROR 级别的日志数量。
3. 追踪 (Tracing):请求的“导航图”
现代应用通常由多个微服务或 Serverless 函数组成,一个用户请求可能会依次经过 API Gateway、Lambda 函数 A、DynamoDB、Lambda 函数 B…… 如果其中一步变慢或出错,如何快速定位?分布式追踪就是答案。
- 它的作用是? 追踪记录一个请求在分布式系统中所经过的完整路径和耗时。
- 如何实现?
- 当请求进入系统时,生成一个唯一的追踪 ID (Trace ID)。
- 这个 ID 随着请求在各个服务间传递。
- 每个服务记录自己处理这段请求的开始时间、结束时间(生成一个 Span),并附上 Trace ID。
- 追踪系统(如 AWS X-Ray)收集这些 Span 信息,并将它们串联起来,形成一个完整的调用链(Trace Map 或 Service Map)。
- 有什么用?
- 可视化请求流程: 清晰地看到请求经过了哪些服务。
- 性能瓶颈定位: 快速发现哪个环节耗时最长。
- 错误定位: 快速定位是哪个服务或调用出错了。
- 如何启用 (AWS X-Ray 为例)?
- 在 Lambda 函数配置的 “监控和运维工具” (Monitoring and operations tools) 部分,启用 “主动追踪” (Active tracing)。
- 确保 Lambda 函数的执行角色拥有向 X-Ray 写入数据的权限。
- 对于 API Gateway 等其他支持的服务,也需要启用 X-Ray 追踪。
- (可选)在代码中使用 X-Ray SDK 添加更详细的自定义追踪信息(如对外部 HTTP 调用或 SQL 查询进行追踪)。
常见问题与排查思路
掌握了监控工具,我们来看看 Serverless 应用中一些常见的问题以及如何排查:
- 函数超时 (Timeout):
- 症状: 函数执行失败,日志中出现 "Task timed out after X seconds" 类似错误。
- 原因: 代码逻辑复杂耗时过长;等待外部 API 或数据库响应过慢;代码 Bug(如死循环);冷启动时间叠加执行时间超过了设置的超时阈值。
- 排查: 查看 Duration 指标和日志,分析耗时点。检查外部调用延迟。
- 解决: 优化代码逻辑;增加函数超时设置(Lambda 最长 15 分钟);优化外部调用;使用异步处理模式(如 SQS)将长任务解耦。
- 内存不足 (Out of Memory / OOM):
- 症状: 函数突然中断执行,日志中可能出现 OOM 或类似错误码。
- 原因: 函数配置的内存太小;代码加载了大型库或文件到内存;处理了非常大的数据量;内存泄漏。
- 排查: CloudWatch 会记录函数执行使用的内存量。观察该指标是否接近配置上限。分析代码中内存使用情况。
- 解决: 增加函数内存配置(Lambda 中增加内存也会相应提高 CPU 性能);优化代码,减少内存占用;分批处理大数据;使用流式处理。
- 冷启动延迟:
- 症状: P99 或 Max Duration 指标远高于 Avg Duration;用户偶尔反馈 API 响应慢。
- 排查: 使用 X-Ray 追踪可以清晰看到冷启动的
Initialization
阶段耗时。 - 解决: (参考第二篇) 优化代码包大小和依赖;选择更快启动的语言/运行时;启用预置并发 (Provisioned Concurrency) 让指定数量的实例保持“温热”状态(会产生额外费用)。
- 权限错误 (Permissions Error / Access Denied):
- 症状: 函数执行失败,日志中明确报出权限不足的错误,例如 "User: arn:aws:sts::...:assumed-role/.../myHelloFunction-... is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:..."。
- 原因: Lambda 函数的执行角色 (Execution Role) 没有被授予访问其他 AWS 服务(如 DynamoDB, S3, SQS)的必要权限 (IAM Policy)。
- **排查:**仔细阅读错误日志,明确缺少哪个服务的哪个操作权限。检查 Lambda 函数关联的 IAM Role 及其附加的 Policy。
- 解决: 编辑 IAM Role 的 Policy,添加缺失的权限。遵循最小权限原则 (Principle of Least Privilege),只授予必要的权限。Serverless Framework 或 SAM 可以方便地在配置文件中定义这些权限。
- 配置错误:
- 症状: 函数启动失败或运行不符合预期。
- 原因: 环境变量设置错误或缺失;依赖库版本冲突或打包问题;函数处理程序 (handler) 名称配置错误;API Gateway 路由或集成配置错误。
- 排查: 检查函数配置(环境变量、handler 字符串)。检查部署日志。在本地使用
invoke local
或模拟器测试。检查serverless.yml
或template.yaml
中的配置。
主动出击:设置告警 (Alerting)
仅仅被动地查看指标和日志是不够的。你需要让系统在出现问题时主动通知你。
- 为什么需要? 及时发现并响应生产环境的问题,避免影响扩大。
- 怎么做 (AWS CloudWatch Alarms 为例)?
- 可以基于指标设置告警:例如,当函数错误率 (Errors/Invocations) 连续 5 分钟超过 1% 时;当 P99 执行持续时间超过 1 秒时;当 Throttles 指标出现时。
- 可以基于日志模式设置告警:例如,当日志中出现特定错误关键字(如 "FATAL", "PaymentFailed")时。
- 配置告警触发时的动作 (Action):最常见的是发送通知到 SNS (Simple Notification Service) 主题,然后可以通过 SNS 将通知发送到 Email、短信、Slack、PagerDuty 等。
小结:运维焦点的转变
Serverless 并没有消除运维,而是将运维的焦点从底层基础设施管理转移到了应用层面的可观测性、配置管理、成本优化和安全保障上。熟练运用云平台提供的监控、日志、追踪和告警工具,是保障 Serverless 应用稳定、高效运行的关键。
理解了如何监控和排查问题,我们距离构建生产级的 Serverless 应用又近了一步。接下来,我们将探讨一些架构设计模式和最佳实践,帮助你构建更健壮、可扩展、安全的 Serverless 应用。
敬请期待下一篇:《架构设计模式:构建健壮、可扩展的 Serverless 应用》!