AWS SAM:构建无服务器应用框架

FreeGuideOnline 最新 2026-06-30

AWS SAM 无服务器应用——从零到部署完全指南

无服务器架构正从一种时髦概念变成标准的应用构建方式。AWS Serverless Application Model (SAM) 是一款开源框架,专门用于在 AWS 上构建无服务器应用。它将复杂的基础设施即代码 (IaC) 简化为几行 YAML,让你可以用更少的配置定义 API 网关、Lambda 函数和 DynamoDB 表,并实现本地调试和一键部署。

本教程面向零基础开发者,将带你用 AWS SAM 创建、测试、部署一套真实的 REST API 后端,逐步掌握无服务器应用的核心流程。


为什么选择 AWS SAM

AWS SAM 是 AWS 官方维护的无服务器框架,相比 Serverless Framework、SST 等工具,它拥有天然优势:

  • 原生集成:直接转化为 CloudFormation 模板,所有 AWS 资源均可声明。
  • 简单强大的 CLIsam initsam buildsam deploy 足够覆盖 90% 的场景。
  • 本地测试:支持在 Docker 容器中调用 Lambda 和 API Gateway。
  • 无额外费用:SAM 本身开源免费,只需支付所用 AWS 资源。

如果你想快速上手无服务器,并且希望与 AWS 生态无缝衔接,SAM 是最值得投入学习的工具。


前置准备

在开始之前,请确保你的开发环境中已经具备:

  • 一个拥有管理员权限的 AWS 账号(可新建 IAM 用户)
  • AWS CLI 已安装并完成 aws configure
  • AWS SAM CLI 已安装(macOS/Linux/Windows 均可)
  • Docker 已安装并正在运行(仅本地测试需要)

验证安装:

aws --version
sam --version
docker --version

第一步:初始化 SAM 项目

打开终端,运行引导命令:

sam init

你会看到交互式提示,推荐选择以下参数:

  • Template source1 - AWS Quick Start Templates
  • Package type2 - Zip (artifact is a zip uploaded to S3)
  • Runtime:选择 python3.11 或你熟悉的语言(Node.js、Java 等均支持)
  • Application template:选择 1 - Hello World Example (最基础但仍包含 API Gateway)

项目生成后会得到如下结构:

sam-app/
├── template.yaml          # SAM 模板,定义所有资源
├── hello_world/           # Lambda 函数代码目录
│   ├── app.py
│   └── requirements.txt
└── tests/

现在先不要修改代码,让我们仔细阅读 template.yaml 里的秘密。


第二步:理解 SAM 模板——无服务器的“蓝图”

打开 template.yaml,它是一个 CloudFormation 的超集,专门定义无服务器资源:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app
  Sample SAM Template  

Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.11
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

核心概念解析

  • TransformAWS::Serverless-2016-10-31 告诉 CloudFormation 使用 SAM 语法处理此模板。
  • Globals:为所有函数设置共用属性,避免重复。
  • AWS::Serverless::Function:SAM 的关键资源类型,它会自动创建 Lambda 函数、IAM 角色、CloudWatch 日志组等。
  • Events:定义触发函数的事件源。此处的 Api 类型会自动创建一个 API Gateway REST API 并将 GET /hello 路由到此函数。

无需手动编写复杂的 Lambda 权限或 API 网关,SAM 帮我们做了极简抽象。


第三步:本地开发和调试

真正的生产力来自本地运行和调试功能,这可以大大缩短反馈循环。

构建项目

在项目根目录执行:

sam build

此命令会:

  1. 根据运行时复制依赖(如通过 pip 安装 requirements.txt 中的库)。
  2. 将代码打包为可部署的构件。
  3. 为本地调用做准备。

本地调用 Lambda

要直接调用函数而不经过 API 网关,使用:

sam local invoke HelloWorldFunction

你会看到类似输出:

{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

本地运行 API 网关

启动本地 HTTP 服务器,完整模拟 API 网关行为:

sam local start-api

此时访问 http://127.0.0.1:3000/hello,即可获得 Lambda 返回的 JSON。当你修改代码后,无需重启,下次请求会自动重用新代码(热重载)。

提示:如果函数依赖外部服务(如 DynamoDB),可使用 sam local invoke --env-vars env.json 注入环境变量,或本地运行 DynamoDB Local。


第四步:编写一个实用 API——Todo 列表

现在将示例改造为一个简单的 Todo 应用,实现创建和查询任务。

修改 hello_world/app.py

import json
import os
import uuid
from datetime import datetime
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])


def lambda_handler(event, context):
    http_method = event['httpMethod']
    if http_method == 'GET':
        return get_todos()
    elif http_method == 'POST':
        body = json.loads(event['body'])
        return create_todo(body['title'])
    return {
        'statusCode': 400,
        'body': json.dumps({'error': 'Unsupported method'})
    }


def get_todos():
    response = table.scan()
    items = response.get('Items', [])
    return {
        'statusCode': 200,
        'body': json.dumps(items)
    }


def create_todo(title):
    item = {
        'id': str(uuid.uuid4()),
        'title': title,
        'completed': False,
        'createdAt': datetime.utcnow().isoformat()
    }
    table.put_item(Item=item)
    return {
        'statusCode': 201,
        'body': json.dumps(item)
    }

扩展 template.yaml 资源

添加一个 DynamoDB 表并赋予 Lambda 读写权限:

Resources:
  # ... HelloWorldFunction 保持不变,但可将其重命名 TodoFunction
  
  TodoTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
      TableName: todos

  TodoFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.11
      Environment:
        Variables:
          TABLE_NAME: !Ref TodoTable
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref TodoTable
      Events:
        GetTodos:
          Type: Api
          Properties:
            Path: /todos
            Method: get
        CreateTodo:
          Type: Api
          Properties:
            Path: /todos
            Method: post

关键点:

  • AWS::Serverless::SimpleTable 一行代码创建一个 DynamoDB 表。
  • Policies 使用 SAM 策略模板,无需手动编写 IAM 策略。
  • 为同一个 Lambda 定义了 GET 和 POST 两个事件,URL 路径相同但方法不同。

本地测试新 API

构建后启动本地 API:

sam build
sam local start-api

使用 curl 测试:

# 创建 todo
curl -X POST http://127.0.0.1:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"Learn SAM"}'

# 获取列表
curl http://127.0.0.1:3000/todos

一切正常后,就可以部署到 AWS 云端了。


第五步:部署到 AWS

首次部署:引导式向导

sam deploy --guided

交互过程中需要提供:

  • Stack Name:例如 sam-todo-app
  • AWS Region:选择接近你用户的区域
  • Confirm changes before deploy:建议选 Y,会展示变更集
  • Allow SAM CLI IAM role creationY
  • Save arguments to samconfig.tomlY,下次部署直接 sam deploy 即可

部署完成后,终端会输出 API Gateway 的端点 URL(如 https://abc123.execute-api.us-east-1.amazonaws.com/Prod/todos)。

后续部署

代码修改后,只需:

sam build && sam deploy

SAM 会智能检测变化并仅更新变更部分,速度非常快。


第六步:监控和调试线上应用

部署后如何查看日志?

使用 SAM 快速查看日志

sam logs -n TodoFunction --stack-name sam-todo-app --tail

这会显示 Lambda 函数的最新 CloudWatch 日志,类似 tail -f

也可指定时间范围:

sam logs -n TodoFunction --stack-name sam-todo-app -s '10min ago'

使用 AWS 控制台

进入 Lambda 控制台 → 选择函数 → 点击 Monitor 标签,可以看到调用次数、错误率、持续时间等指标。


最佳实践与进阶技巧

1. 合理设置超时与内存

Lambda 计费与内存和时间成正比。不要盲目设置最大内存。对于 IO 密集型任务(如访问 DynamoDB),256–512 MB 通常足够。

2. 使用 samconfig.toml 管理多环境

可以创建 samconfig.toml

[dev.deploy.parameters]
stack_name = "sam-todo-dev"
s3_bucket = "my-deploy-bucket-dev"
region = "us-east-1"
capabilities = "CAPABILITY_IAM"

[prod.deploy.parameters]
stack_name = "sam-todo-prod"
s3_bucket = "my-deploy-bucket-prod"
region = "us-east-1"
capabilities = "CAPABILITY_IAM"

部署时指定配置文件:sam deploy --config-env prod

3. 为 Lambda 添加层(Layers)

当多个函数共享代码或库时,用层可以减少包体积。

MyLayer:
  Type: AWS::Serverless::LayerVersion
  Properties:
    ContentUri: my-layer/
    CompatibleRuntimes:
      - python3.11

MyFunction:
  Type: AWS::Serverless::Function
  Properties:
    Layers:
      - !Ref MyLayer
    ...

4. 使用嵌套栈拆分应用

大型应用可将资源拆分为多个模板,通过 AWS::Serverless::Application 引用。

5. 利用 SAM 管道实现 CI/CD

可使用 sam pipeline init --bootstrap 自动创建 CI/CD 管道(如 GitHub Actions),实现代码推送即部署。


常见问题排查

问题 可能原因 解决方法
sam build 失败 缺少对应运行时的包管理器 检查 Python/Node 版本并使用正确构建方式
sam local start-api 超时 Docker 资源不足 增加 Docker 内存或调整函数超时
部署后 API 返回 502 Lambda 执行错误 查看 CloudWatch 日志,检查环境变量
本地请求路径不匹配 API 网关路径与本地不一致 确保 start-api 后路径与模板 Events 中一致
AccesDenied 错误 IAM 权限不足 检查 Policies 属性,必要时使用 sam validate

总结

通过本教程,你已经完整掌握:

  1. 使用 sam init 启动项目。
  2. 编写 SAM 模板定义 Lambda、API Gateway 和 DynamoDB。
  3. 在本地构建、调用和运行完整 API 模拟。
  4. sam deploy --guided 将应用部署到 AWS。
  5. 通过 sam logs 查看日志并调试线上问题。

AWS SAM 将无服务器应用的门槛降低到只需一个 YAML 文件。它背后的云资源抽象让你聚焦业务逻辑,而不是基础设施的配置细节。接下来你可以尝试集成更多 AWS 服务(Step Functions、S3 事件等),或者为多环境加入自动化 CI/CD 管道。祝你无服务器之旅一帆风顺!

进一步学习资源