AWS 数据处理中心架构学习笔记
乔文飞 Lv8

架构总览

最近在学习一套基于 AWS 的服务端架构,整体分为四层:

层级 组件
边缘 & 网关层 Lambda@Edge、AWS AppSync
负载均衡层 Lambda 负载均衡(ALB)
业务服务层 Stat Task、Account / Order / Management / Assets / Image Handler Service
监控层 Amazon CloudWatch
Client Browser / App ① 边缘层 Lambda@Edge 4 个触发点 · JWT 鉴权 边缘执行 · 低延迟 AWS AppSync GraphQL 托管网关 Full Text Search 接口 ② 负载均衡 Lambda 负载均衡(ALB) Listener · Rule · Target Group 路径路由 /api/orders/* → Lambda ③ 业务服务层 Account REST API Provisioned ×2 Order REST API Provisioned ×3 Management REST API /management/* Assets REST API S3 存储对接 Image Handler REST API 图片处理转换 Full Text Search GraphQL · AppSync 背后接 OpenSearch Stat Task EventBridge cron 定时触发 · 无需预置 ④ 监控层 Amazon CloudWatch Logs · Metrics · Alarms · Dashboard Errors · Duration · Throttles · InitDuration

Lambda 是 Serverless

AWS Lambda 是 Serverless(无服务器)架构的典型实现,也就是 FaaS(Function as a Service)。

核心思想:你只写代码,不管服务器。

  • 被调用时自动启动容器运行代码,用完自动销毁
  • 流量突增时自动扩容,流量下去自动缩容到零
  • 按实际调用次数和运行时长收费,没有请求就是零费用

类比出租车:Lambda 就像出租车,用的时候叫,用完即走,不需要养一辆车停在车库里持续花费。


Lambda@Edge:边缘执行的 Lambda

Lambda@Edge 是把 Lambda 函数”搬”到 CloudFront 全球边缘节点上运行的能力。普通 Lambda 部署在某个 AWS Region,而 Lambda@Edge 自动复制到离用户最近的 PoP 节点执行,延迟可以从几百毫秒降到几十毫秒。

四个触发点

一个请求从用户到源站,经过 CloudFront 时有四个可以插入逻辑的位置:

用户 Tokyo PoP CloudFront PoP 边缘缓存(Cache) 命中则直接返回,不触发 Lambda 缓存未命中 ↓ 进入触发点 ① Viewer Request 到达 PoP 时最先触发 · JWT 鉴权 / A/B 分流 ② Origin Request 即将回源前 · 修改目标源站 / 注入鉴权头 源站 S3 / ALB ③ Origin Response 源站响应返回后 · 改响应头 / 自定义错误页 ④ Viewer Response · 注入安全头 / 打点日志
  1. Viewer Request:用户请求刚到 PoP,缓存检查之前。适合 JWT 鉴权、A/B 测试分流、请求路径标准化。
  2. Origin Request:缓存未命中、即将回源前。适合动态改变源站地址(灰度发布)、注入内部鉴权头。
  3. Origin Response:源站响应返回后,写入缓存之前。适合修改响应头、替换源站 4xx 为自定义错误页。
  4. Viewer Response:响应最终返回用户前。适合注入安全响应头(Strict-Transport-SecurityX-Frame-Options)、打点日志。

与普通 Lambda 的区别

Lambda@Edge 有更严格的限制:内存最大 128 MB(普通 Lambda 最高 10 GB),Viewer 触发点执行时间最多 5 秒,Origin 触发点最多 30 秒。代码必须部署在 us-east-1,AWS 自动向全球复制。不支持环境变量。


Lambda 冷启动

什么是冷启动

Lambda 函数平时”不存在”,第一次被调用时 AWS 需要临时”造”出运行环境,这个过程就是冷启动,分为四步:

  1. 从 S3 下载代码包
  2. 启动容器(分配 CPU / 内存)
  3. 初始化运行时(启动 Node.js / JVM 等)
  4. 执行 handler 外的初始化代码(DB 连接、SDK 初始化等)

前三步是 AWS 控制的 Init 阶段,用户无法干预。第四步是用户代码,可以优化。

冷启动(第一次调用) 下载代码包 从 S3 拉取 zip 启动容器 分配 CPU / 内存 初始化运行时 启动 Node / JVM 执行初始化代码 handler 外 · DB连接 SDK 初始化 Init 阶段典型耗时 100ms ~ 3s,之后才执行业务代码 执行 handler 业务代码 真正的响应逻辑 热启动(容器复用,跳过全部 Init) 容器复用 AWS 直接重用 直接执行 handler(DB 连接 / SDK 已就绪,直接复用) 无 Init 开销,典型耗时 ~5ms 响应耗时对比 冷启动 ~500ms (Node.js) 热启动 ~5ms

冷启动耗时

  • Node.js / Python:典型 100~500ms
  • Java / Kotlin:因 JVM 启动慢,常见 2~5 秒

热启动(容器复用)时跳过全部 Init 阶段,直接执行业务代码,典型耗时 5ms 左右。

优化方案

1. Provisioned Concurrency(预置并发) — 最彻底的方案

提前告诉 AWS 保持 N 个容器随时热着,这些实例永远不走冷启动流程。代价是按保留实例数量持续收费,适合核心链路。

2. Warming(定时预热)

用 EventBridge 每 5 分钟触发一次 Lambda,防止容器因闲置被销毁。成本极低,但只能保证单实例热着,突发并发时新实例仍然冷启动。

3. 缩小代码包体积

代码包越小,下载越快。Node.js 用 esbuild 做 tree-shaking,能把包从几十 MB 压到几 MB,冷启动时间可缩短 30~50%。

最重要的代码层面优化:初始化代码放 handler 外

1
2
3
4
5
6
// 正确:DB 连接在 handler 外,容器复用时直接用
const db = new Database(process.env.DB_URL);

exports.handler = async (event) => {
return db.query('SELECT ...');
};
1
2
3
4
5
// 错误:每次调用都重新建连接,热启动也慢
exports.handler = async (event) => {
const db = new Database(process.env.DB_URL); // 每次都执行
return db.query('SELECT ...');
};

handler 外的代码只在冷启动时执行一次,之后容器复用时直接跳过。


Provisioned Concurrency 配置方式

预置并发必须绑定在别名(Alias)或版本(Version)上,不能直接绑在 $LATEST

方式一:AWS CLI

1
2
3
4
5
6
7
8
9
10
11
12
13
# 发布版本
aws lambda publish-version --function-name order-service

# 在该版本上配置预置并发数为 3
aws lambda put-provisioned-concurrency-config \
--function-name order-service \
--qualifier 1 \
--provisioned-concurrent-executions 3

# 查看状态(STATUS 变为 READY 才生效)
aws lambda get-provisioned-concurrency-config \
--function-name order-service \
--qualifier 1

方式二:Application Auto Scaling(生产推荐)

按时段自动调整预置数量,白天多、深夜少,避免浪费。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 注册为可扩展目标
aws application-autoscaling register-scalable-target \
--service-namespace lambda \
--resource-id function:order-service:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--min-capacity 2 \
--max-capacity 20

# 目标追踪策略:利用率超 70% 自动扩,低于 70% 自动缩
aws application-autoscaling put-scaling-policy \
--service-namespace lambda \
--resource-id function:order-service:prod \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--policy-name order-service-scaling \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 0.7,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "LambdaProvisionedConcurrencyUtilization"
}
}'

ALB 负载均衡

ALB(Application Load Balancer)把 HTTP 请求按路径规则分发到对应的 Lambda 函数。

三个核心概念:

  • Listener(监听器):监听某个端口(如 HTTPS 443)
  • Rule(规则):按路径匹配决定转发给谁
  • Target Group(目标组):承接请求的后端,每个 Lambda 函数对应一个 Target Group

Terraform 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
resource "aws_lb_target_group" "order_service" {
name = "order-service-tg"
target_type = "lambda"
}

resource "aws_lb_target_group_attachment" "order_service" {
target_group_arn = aws_lb_target_group.order_service.arn
target_id = aws_lambda_function.order_service.arn
}

resource "aws_lb_listener_rule" "order_service" {
listener_arn = aws_lb_listener.https.arn
priority = 20

condition {
path_pattern {
values = ["/api/orders/*"]
}
}

action {
type = "forward"
target_group_arn = aws_lb_target_group.order_service.arn
}
}

Lambda 接收的 event 结构

ALB 把 HTTP 请求转成 event 对象传给 Lambda:

1
2
3
4
5
6
7
8
9
10
11
12
exports.handler = async (event) => {
const method = event.httpMethod;
const path = event.path;
const headers = event.headers;
const body = JSON.parse(event.body);

return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ orderId: "123", status: "ok" })
};
};

Amazon CloudWatch 监控

Lambda 自动向 CloudWatch 上报日志和指标,无需额外配置。需要手动配置的是告警阈值和通知渠道。

五个核心监控指标

指标 含义 告警建议
Errors 函数报错次数 > 0 立即告警
Duration 执行时长 超过 Timeout 的 80% 时告警
Throttles 被限流次数 > 0 告警,说明并发超限
ConcurrentExecutions 并发执行数 评估预置并发是否够用
InitDuration 冷启动耗时 优化冷启动的核心依据

告警配置示例(CDK Python)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from aws_cdk import aws_cloudwatch as cw
from aws_cdk import aws_cloudwatch_actions as cw_actions
from aws_cdk import aws_sns as sns

topic = sns.Topic(self, "AlertTopic")
sns.Subscription(self, "EmailSub",
topic=topic,
protocol=sns.SubscriptionProtocol.EMAIL,
endpoint="your-team@example.com"
)

error_alarm = cw.Alarm(self, "OrderServiceErrors",
metric=order_lambda.metric_errors(),
threshold=1,
evaluation_periods=1,
alarm_description="Order Service Lambda 报错",
treat_missing_data=cw.TreatMissingData.NOT_BREACHING
)
error_alarm.add_alarm_action(cw_actions.SnsAction(topic))

Logs Insights 查询示例

1
2
3
4
5
6
7
8
9
10
11
-- 查所有冷启动记录
fields @timestamp, @duration, @initDuration
| filter @type = "REPORT" and ispresent(@initDuration)
| sort @initDuration desc
| limit 20

-- 查错误日志
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 50

总结

这套 AWS 架构的核心设计思路是:用 Serverless 彻底免除服务器运维负担,用 Lambda@Edge 把计算推到离用户最近的地方,用 ALB 把请求按业务职责分散到独立的函数,用 CloudWatch 统一收口监控和告警。

各服务的预置并发策略建议:

  • Account ServiceOrder Service:配置 Provisioned Concurrency(建议从 2~3 个开始),用户直接感知延迟
  • Management ServiceAssets ServiceImage Handler:按需冷启动即可,延迟容忍度较高
  • Stat Task:定时任务,完全不需要预置并发
  • 本文标题:AWS 数据处理中心架构学习笔记
  • 本文作者:乔文飞
  • 创建时间:2026-05-27 00:00:00
  • 本文链接:http://www.feidom.com/2026/05/27/AWS数据处理中心架构学习笔记/
  • 版权声明:本博客所有文章为作者学习笔记,有转载其他前端大佬的文章。转载时请注明出处。