ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AWS Serverless 生产级实战指南:基于 AAS Core 技能库的 Lambda、API Gateway 与事件驱动模式详解

AWS Serverless 生产级实战指南:基于 AAS Core 技能库的 Lambda、API Gateway 与事件驱动模式详解
  • AI 技能
  • AI 插件
  • 人工智能

【免费下载链接】agentic-awesome-skills

AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.

项目地址:https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills
点击查看免费下载

导读

本文是 AAS(agentic-awesome-skills)技能库中aws-serverless技能的核心参考文档(detailed-guide.md)的完整展开。该技能被 AAS Core 编目为cloud类目、critical风险等级的专项技能(见 skills_index.json),目标是指导 Agent 构建生产就绪的 AWS Serverless 应用。读完本文,你将掌握 Lambda 处理器规范、API Gateway 集成、SQS/DynamoDB 事件驱动模式、SAM/CDK 双轨部署、冷启动优化,以及 7 类生产环境高频陷阱的规避方案,同时了解技能本身的安全约束与校验门禁。


一、技能定位与使用边界

aws-serverless技能的入口文件是 SKILL.md,其 frontmatter 声明了:

  • 名称:aws-serverless
  • 范围:Lambda 函数、API Gateway、DynamoDB、SQS/SNS 事件驱动模式、SAM/CDK 部署、冷启动优化
  • 风险等级:critical,意味着执行前必须完整读取本文档,并遵守其中的安全与校验要求
  • 来源:vibeship-spawner-skills(Apache 2.0)

AAS Core 的目录索引将其归类到cloud大类(skills_index.json),并声明插件目标同时支持codex与claude两种 Agent 运行时,且无需额外安装配置(setup.type: none)。

技能自身明确了三项使用限制(见 SKILL.md):

  1. 仅在任务与上述能力范围明确匹配时使用;
  2. 输出不能替代真实环境下的验证、测试与专家评审;
  3. 当缺少必要输入、权限、安全边界或成功标准时,应停下来向用户澄清。

这些约束提示我们:本文是"施工图纸",而非"验收报告"——每段代码落地前仍需结合目标环境的 AWS 账号策略做适配。


二、设计原则:先度量,再优化

本文档开篇给出了 8 条贯穿全文的设计原则(见 detailed-guide.md):

原则说明
内存与超时按需配置先度量再优化,不要盲目加大 MemorySize
最小化冷启动对延迟敏感的工作负载优先处理冷启动路径
Java/.NET 使用 SnapStart通过快照恢复绕开 JVM/CLR 初始化成本
简单场景优先 HTTP API优先于 REST API,成本与延迟都更优
面向失败设计DLQ + 重试机制缺一不可
保持部署包精简减小包体是冷启动优化的第一优先级
用环境变量做配置表名、桶名等不硬编码进代码
结构化日志 + 关联 ID用 requestId 串联调用链,支撑 CloudWatch Insights

其中"内存 = CPU"是一个容易被忽略的事实:Lambda 的 CPU 算力随内存线性增长,128 MB 只能拿到约 1/8 vCPU,而 1024 MB 以上才能拿到完整 vCPU。这一机制会在后文的冷启动优化模式中反复体现。


三、核心模式一:Lambda Handler Pattern(函数骨架规范)

适用场景:任何 Lambda 函数实现——API 处理器、事件处理器、定时任务。

3.1 Node.js 处理器骨架

要点是把初始化移出 handler(见 detailed-guide.md):

// handler.js // Initialize outside handler (reused across invocations) const { DynamoDBClient } = require('@aws-sdk/client-dynamodb'); const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb'); const client = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(client); // Handler function exports.handler = async (event, context) => { // Optional: Don't wait for event loop to clear (Node.js) context.callbackWaitsForEmptyEventLoop = false; try { // Parse input based on event source const body = typeof event.body === 'string' ? JSON.parse(event.body) : event.body; // Business logic const result = await processRequest(body); // Return API Gateway compatible response return { statusCode: 200, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, body: JSON.stringify(result) }; } catch (error) { console.error('Error:', JSON.stringify({ error: error.message, stack: error.stack, requestId: context.awsRequestId })); return { statusCode: error.statusCode || 500, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: error.message || 'Internal server error' }) }; } }; async function processRequest(data) { // Your business logic here const result = await docClient.send(new GetCommand({ TableName: process.env.TABLE_NAME, Key: { id: data.id } })); return result.Item; }

3.2 Python 处理器骨架

同样的"全局初始化 + 分层错误处理"思路(见 detailed-guide.md):

# handler.py import json import os import logging import boto3 from botocore.exceptions import ClientError # Initialize outside handler (reused across invocations) logger = logging.getLogger() logger.setLevel(logging.INFO) dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['TABLE_NAME']) def handler(event, context): try: # Parse input body = json.loads(event.get('body', '{}')) if isinstance(event.get('body'), str) else event.get('body', {}) # Business logic result = process_request(body) return { 'statusCode': 200, 'headers': { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }, 'body': json.dumps(result) } except ClientError as e: logger.error(f"DynamoDB error: {e.response['Error']['Message']}") return error_response(500, 'Database error') except json.JSONDecodeError: return error_response(400, 'Invalid JSON') except Exception as e: logger.error(f"Unexpected error: {str(e)}", exc_info=True) return error_response(500, 'Internal server error') def process_request(data): response = table.get_item(Key={'id': data['id']}) return response.get('Item') def error_response(status_code, message): return { 'statusCode': status_code, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps({'error': message}) }

3.3 最佳实践要点

  • 客户端在 handler 之外初始化,跨热调用复用连接;
  • 始终返回符合 API Gateway 代理集成格式的响应(statusCode/headers/body);
  • 结构化 JSON 日志,便于 CloudWatch Insights 查询;
  • 错误日志中携带requestId(context.awsRequestId),支撑跨服务追踪。

四、核心模式二:API Gateway Integration Pattern(SAM 定义 + 双 API 对比)

适用场景:构建由 Lambda 支撑的 REST API,或为函数提供 HTTP 端点。

4.1 SAM 模板:HTTP API + 两个函数 + DynamoDB

以下模板完整定义了资源拓扑(见 detailed-guide.md):

# template.yaml (SAM) AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Globals: Function: Runtime: nodejs20.x Timeout: 30 MemorySize: 256 Environment: Variables: TABLE_NAME: !Ref ItemsTable Resources: # HTTP API (recommended for simple use cases) HttpApi: Type: AWS::Serverless::HttpApi Properties: StageName: prod CorsConfiguration: AllowOrigins: - "*" AllowMethods: - GET - POST - DELETE AllowHeaders: - "*" # Lambda Functions GetItemFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/get.handler Events: GetItem: Type: HttpApi Properties: ApiId: !Ref HttpApi Path: /items/{id} Method: GET Policies: - DynamoDBReadPolicy: TableName: !Ref ItemsTable CreateItemFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/create.handler Events: CreateItem: Type: HttpApi Properties: ApiId: !Ref HttpApi Path: /items Method: POST Policies: - DynamoDBCrudPolicy: TableName: !Ref ItemsTable # DynamoDB Table ItemsTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH BillingMode: PAY_PER_REQUEST Outputs: ApiUrl: Value: !Sub "https://${HttpApi}.execute-api.${AWS::Region}.amazonaws.com/prod"

模板中有几个值得注意的设计决策:

  • Globals.Function统一函数运行时、超时、内存与环境变量,避免重复声明;
  • DynamoDBReadPolicy/DynamoDBCrudPolicy是 SAM 内置的最小权限策略,比手写 IAM 更贴合最小权限原则;
  • BillingMode: PAY_PER_REQUEST按量计费,适合起步阶段,免去吞吐量规划。

4.2 对应的 Node.js handler

路径参数通过event.pathParameters获取,404 与 400 分支明确(见 detailed-guide.md):

// src/handlers/get.js const { getItem } = require('../lib/dynamodb'); exports.handler = async (event) => { const id = event.pathParameters?.id; if (!id) { return { statusCode: 400, body: JSON.stringify({ error: 'Missing id parameter' }) }; } const item = await getItem(id); if (!item) { return { statusCode: 404, body: JSON.stringify({ error: 'Item not found' }) }; } return { statusCode: 200, body: JSON.stringify(item) }; };

4.3 项目目录结构

project/ ├── template.yaml # SAM template ├── src/ │ ├── handlers/ │ │ ├── get.js │ │ ├── create.js │ │ └── delete.js │ └── lib/ │ └── dynamodb.js └── events/ └── event.json # Test events

4.4 HTTP API vs REST API 选型

文档给出了明确的决策表(见 detailed-guide.md):

维度HTTP APIREST API
延迟更低(约 10ms 级)相对较高
成本便宜 50%~70%更高
功能精简缓存、请求校验、WAF、用量计划、API Key、请求/响应转换
适用绝大多数 REST API复杂 API、企业级功能需求

结论:简单用例默认选 HTTP API;只有在需要 WAF 接入、请求验证、API Key 管理或转换能力时才升级到 REST API。


五、核心模式三:Event-Driven SQS Pattern(可靠异步处理)

适用场景:解耦的异步处理、需要重试与 DLQ、批量消费消息。

5.1 SAM 模板:队列 + 处理器 + DLQ

关键配置在VisibilityTimeout与RedrivePolicy上(见 detailed-guide.md):

# template.yaml Resources: ProcessorFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/processor.handler Events: SQSEvent: Type: SQS Properties: Queue: !GetAtt ProcessingQueue.Arn BatchSize: 10 FunctionResponseTypes: - ReportBatchItemFailures # Partial batch failure handling ProcessingQueue: Type: AWS::SQS::Queue Properties: VisibilityTimeout: 180 # 6x Lambda timeout RedrivePolicy: deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn maxReceiveCount: 3 DeadLetterQueue: Type: AWS::SQS::Queue Properties: MessageRetentionPeriod: 1209600 # 14 days

配置逻辑:

  • VisibilityTimeout = 6 × Lambda 超时(这里 Lambda 默认 30s,队列设为 180s),保证函数超时后消息重新可见;
  • maxReceiveCount = 3,消息被消费失败 3 次后进入 DLQ;
  • MessageRetentionPeriod = 1209600 秒(14 天),DLQ 消息最长保留两周等待人工/自动化处理。

5.2 Node.js:ReportBatchItemFailures 部分失败处理

// src/handlers/processor.js exports.handler = async (event) => { const batchItemFailures = []; for (const record of event.Records) { try { const body = JSON.parse(record.body); await processMessage(body); } catch (error) { console.error(`Failed to process message ${record.messageId}:`, error); // Report this item as failed (will be retried) batchItemFailures.push({ itemIdentifier: record.messageId }); } } // Return failed items for retry return { batchItemFailures }; }; async function processMessage(message) { // Your processing logic console.log('Processing:', message); // Simulate work await saveToDatabase(message); }

5.3 Python 等价实现

import json import logging logger = logging.getLogger() def handler(event, context): batch_item_failures = [] for record in event['Records']: try: body = json.loads(record['body']) process_message(body) except Exception as e: logger.error(f"Failed to process {record['messageId']}: {e}") batch_item_failures.append({ 'itemIdentifier': record['messageId'] }) return {'batchItemFailures': batch_item_failures}

5.4 最佳实践

  • VisibilityTimeout设为 Lambda 超时的 6 倍;
  • 使用ReportBatchItemFailures实现批内部分失败,避免整批重试拖慢吞吐;
  • 始终配置 DLQ 兜底毒消息;
  • 消费逻辑必须幂等(重试会导致同一消息被处理多次)。

六、核心模式四:DynamoDB Streams Pattern(数据变更驱动)

适用场景:对数据变更的实时响应、跨区域复制、审计日志、通知。

6.1 SAM 模板:开启流的表 + 流处理器 + 失败队列

# template.yaml Resources: ItemsTable: Type: AWS::DynamoDB::Table Properties: TableName: items AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH BillingMode: PAY_PER_REQUEST StreamSpecification: StreamViewType: NEW_AND_OLD_IMAGES StreamProcessorFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/stream.handler Events: Stream: Type: DynamoDB Properties: Stream: !GetAtt ItemsTable.StreamArn StartingPosition: TRIM_HORIZON BatchSize: 100 MaximumRetryAttempts: 3 DestinationConfig: OnFailure: Destination: !GetAtt StreamDLQ.Arn StreamDLQ: Type: AWS::SQS::Queue

配置要点:

  • StartingPosition: TRIM_HORIZON表示从最早的未处理记录开始消费;
  • MaximumRetryAttempts: 3限制迭代器重试次数;
  • DestinationConfig.OnFailure把反复失败的批次投递到 DLQ,避免 shard 卡死。

6.2 Node.js 处理器:按事件类型分派

// src/handlers/stream.js exports.handler = async (event) => { for (const record of event.Records) { const eventName = record.eventName; // INSERT, MODIFY, REMOVE // Unmarshall DynamoDB format to plain JS objects const newImage = record.dynamodb.NewImage ? unmarshall(record.dynamodb.NewImage) : null; const oldImage = record.dynamodb.OldImage ? unmarshall(record.dynamodb.OldImage) : null; console.log(`${eventName}: `, { newImage, oldImage }); switch (eventName) { case 'INSERT': await handleInsert(newImage); break; case 'MODIFY': await handleModify(oldImage, newImage); break; case 'REMOVE': await handleRemove(oldImage); break; } } }; // Use AWS SDK v3 unmarshall const { unmarshall } = require('@aws-sdk/util-dynamodb');

6.3 StreamViewType 四档选择

取值内容
KEYS_ONLY仅键属性
NEW_IMAGE修改后的整条记录
OLD_IMAGE修改前的整条记录
NEW_AND_OLD_IMAGES前后都有

视图类型决定了流记录携带的数据量,直接影响流的写入开销,按业务需要最小化选择。


七、核心模式五:Cold Start Optimization Pattern(冷启动优化)

适用场景:延迟敏感应用、面向用户的 API、高流量函数。

文档给出了 5 个递进手段(见 detailed-guide.md)。

7.1 压缩部署包(收益最大)

// Use modular AWS SDK v3 imports // GOOD - only imports what you need const { DynamoDBClient } = require('@aws-sdk/client-dynamodb'); const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb'); // BAD - imports entire SDK const AWS = require('aws-sdk'); // Don't do this!

7.2 Java/.NET 启用 SnapStart

Resources: JavaFunction: Type: AWS::Serverless::Function Properties: Handler: com.example.Handler::handleRequest Runtime: java21 SnapStart: ApplyOn: PublishedVersions # Enable SnapStart AutoPublishAlias: live

7.3 上调内存换取 CPU

# More memory = more CPU = faster init Resources: FastFunction: Type: AWS::Serverless::Function Properties: MemorySize: 1024 # 1GB gets full vCPU Timeout: 30

7.4 必要时启用预置并发

Resources: CriticalFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/critical.handler AutoPublishAlias: live ProvisionedConcurrency: Type: AWS::Lambda::ProvisionedConcurrencyConfig Properties: FunctionName: !Ref CriticalFunction Qualifier: live ProvisionedConcurrentExecutions: 5

7.5 延迟初始化

# GOOD - Lazy initialization _table = None def get_table(): global _table if _table is None: dynamodb = boto3.resource('dynamodb') _table = dynamodb.Table(os.environ['TABLE_NAME']) return _table def handler(event, context): table = get_table() # Only initializes on first use # ...

7.6 优化优先级

  1. 减小部署包(影响最大)
  2. Java/.NET 启用 SnapStart
  3. 增大内存加速初始化
  4. 延迟重依赖导入
  5. 预置并发(最后手段,成本最高)

八、核心模式六:SAM Local Development Pattern(本地开发调试)

适用场景:本地开发与测试、调试 Lambda、本地验证 API Gateway。

8.1 完整命令流

# Install SAM CLI pip install aws-sam-cli # Initialize new project sam init --runtime nodejs20.x --name my-api # Build the project sam build # Run locally sam local start-api # Invoke single function sam local invoke GetItemFunction --event events/get.json # Local debugging (Node.js with VS Code) sam local invoke --debug-port 5858 GetItemFunction # Deploy sam deploy --guided

8.2 测试事件样例

// events/get.json (test event) { "pathParameters": { "id": "123" }, "httpMethod": "GET", "path": "/items/123" }

8.3 VS Code 远程调试配置

// .vscode/launch.json (for debugging) { "version": "0.2.0", "configurations": [ { "name": "Attach to SAM CLI", "type": "node", "request": "attach", "address": "localhost", "port": 5858, "localRoot": "${workspaceRoot}/src", "remoteRoot": "/var/task/src", "protocol": "inspector" } ] }

8.4 命令速查

命令作用
sam build构建 Lambda 部署包
sam local start-api本地启动 API Gateway
sam local invoke调用单个函数
sam deploy部署到 AWS
sam logs追踪 CloudWatch 日志

九、核心模式七:CDK Serverless Pattern(基础设施即代码)

适用场景:超出单个 Lambda 的复杂基础设施、偏好编程语言而非 YAML、需要可复用构造。

9.1 TypeScript 栈定义

// lib/api-stack.ts import * as cdk from 'aws-cdk-lib'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as apigateway from 'aws-cdk-lib/aws-apigateway'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import { Construct } from 'constructs'; export class ApiStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // DynamoDB Table const table = new dynamodb.Table(this, 'ItemsTable', { partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING }, billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: cdk.RemovalPolicy.DESTROY, // For dev only }); // Lambda Function const getItemFn = new lambda.Function(this, 'GetItemFunction', { runtime: lambda.Runtime.NODEJS_20_X, handler: 'get.handler', code: lambda.Code.fromAsset('src/handlers'), environment: { TABLE_NAME: table.tableName, }, memorySize: 256, timeout: cdk.Duration.seconds(30), }); // Grant permissions table.grantReadData(getItemFn); // API Gateway const api = new apigateway.RestApi(this, 'ItemsApi', { restApiName: 'Items Service', defaultCorsPreflightOptions: { allowOrigins: apigateway.Cors.ALL_ORIGINS, allowMethods: apigateway.Cors.ALL_METHODS, }, }); const items = api.root.addResource('items'); const item = items.addResource('{id}'); item.addMethod('GET', new apigateway.LambdaIntegration(getItemFn)); // Output API URL new cdk.CfnOutput(this, 'ApiUrl', { value: api.url, }); } }

9.2 CDK 常用命令

npm install -g aws-cdk cdk init app --language typescript cdk synth # Generate CloudFormation cdk diff # Show changes cdk deploy # Deploy to AWS

CDK vs SAM 的选择:当基础设施复杂度超出 Lambda 本身(需要自定义资源、跨栈共享、复杂路由)时,CDK 的编程式抽象和可复用 Construct 更具优势;简单场景下 SAM 的声明式 YAML 上手更快。


十、Sharp Edges:生产环境 7 类高频陷阱

该章节是本文档最有实战价值的部分,按严重程度组织(见 detailed-guide.md)。

10.1 冷启动 INIT 阶段开始计费(2025 年 8 月起)

严重度:HIGH

现状:自 2025 年 8 月 1 日起,AWS 将 INIT 阶段按调用时长计费,冷启动直接推高账单(可能高出 10%~50%),受影响最大的是:重依赖加载、慢初始化代码、频繁冷启动(低流量或并发不足)的函数。

应对四步:

  1. 度量 INIT 时长——查看 CloudWatch Logs 中的INIT_REPORT:
    INIT_REPORT Init Duration: 423.45 ms
  2. 降低 INIT 耗时——精简部署包(npm prune --production、tree shaking)、延迟加载重依赖、使用 SDK v3 模块化导入。
  3. Java/.NET 启用 SnapStart:
    Resources: JavaFunction: Type: AWS::Serverless::Function Properties: Runtime: java21 SnapStart: ApplyOn: PublishedVersions
  4. 监控冷启动频率——用自定义指标跟踪:
    let isColdStart = true; exports.handler = async (event) => { if (isColdStart) { console.log('COLD_START'); // CloudWatch custom metric here isColdStart = false; } // ... };

10.2 Lambda 超时配置错误

严重度:HIGH

事实基线:默认超时仅 3 秒,最大 900 秒。超时会导致函数被强制终止、无优雅退出、静默失败。

常见诱因:默认超时太短、下游服务变慢、VPC 网络问题、死循环/阻塞操作、S3 下载超过预期。

应对:

  • 超时设为"预期时长 + 缓冲":
    Resources: MyFunction: Type: AWS::Serverless::Function Properties: Timeout: 30 # Seconds (max 900)
  • 用context.getRemainingTimeInMillis()感知剩余时间,接近超时先保存进度再优雅失败:
    exports.handler = async (event, context) => { const remainingTime = context.getRemainingTimeInMillis(); if (remainingTime < 5000) { console.warn('Running low on time, aborting'); throw new Error('Insufficient time remaining'); } // ... };
  • 所有 HTTP 调用必须显式设置超时:
    const response = await axios.get('https://api.example.com/data', { timeout: 5000 // 5 seconds });

10.3 内存溢出(OOM)崩溃

严重度:HIGH

事实基线:Lambda 超过内存上限会被 AWS 强制终止运行时,且不会抛出可捕获异常——表现为日志截断、Max Memory Used触顶、高负载下行为不一致。

应对:

  • 上调内存(128~10240 MB,且内存增大同时带来更多 CPU):
    Resources: MyFunction: Type: AWS::Serverless::Function Properties: MemorySize: 1024 # MB (128-10240)
  • 大文件改为流式处理,避免整文件载入内存:
    // BAD - loads entire file into memory const data = await s3.getObject(params).promise(); const content = data.Body.toString(); // GOOD - stream processing const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); const s3 = new S3Client({}); const response = await s3.send(new GetObjectCommand(params)); const stream = response.Body; // Process stream in chunks for await (const chunk of stream) { await processChunk(chunk); }
  • 使用 Lambda Power Tuning 工具定位最优内存档位。

10.4 VPC 内 Lambda 冷启动延迟

严重度:MEDIUM

事实基线:VPC 内函数依赖弹性网络接口(ENI),即使 Hyperplane 大幅改善了 ENI 复用,首次冷启动仍有额外开销;NAT 网关问题、安全组误配、DNS 慢解析都会加剧。

应对:

  • 校验 VPC 配置,安全组放行 443 出站,子网覆盖多个可用区:
    Resources: MyFunction: Type: AWS::Serverless::Function Properties: VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroup SubnetIds: - !Ref PrivateSubnet1 - !Ref PrivateSubnet2 # Multiple AZs
  • 对 AWS 服务调用使用 VPC Endpoint(Gateway 类型)而非 NAT Gateway:
    DynamoDBEndpoint: Type: AWS::EC2::VPCEndpoint Properties: ServiceName: !Sub com.amazonaws.${AWS::Region}.dynamodb VpcId: !Ref VPC RouteTableIds: - !Ref PrivateRouteTable VpcEndpointType: Gateway
  • 只在确有必要时挂 VPC:访问 RDS/ElastiCache、私有 EC2 或合规要求才需要;大多数 AWS 服务无需 VPC 即可访问。

10.5 Node.js 事件循环未清空

严重度:MEDIUM

事实基线:默认情况下 Lambda 等待 Node.js 事件循环清空才返回。残留的setTimeout/setInterval、悬空数据库连接、未决回调会让函数空转到超时,白白计费。

应对:

  • 设置context.callbackWaitsForEmptyEventLoop = false;
  • 数据库连接显式关闭或使用连接池:
    const connection = await mysql.createConnection({...}); try { const [rows] = await connection.query('SELECT * FROM users'); return { statusCode: 200, body: JSON.stringify(rows) }; } finally { await connection.end(); // Always close }

10.6 API Gateway 载荷大小限制

严重度:MEDIUM

事实基线:REST API 与 HTTP API 请求/响应上限均为 10 MB;Lambda 同步响应上限 6 MB、异步 256 KB。超出会出现413 Request Entity Too Large或Malformed Lambda proxy response。

应对:大文件上传用 S3 预签名 URL 直传;大响应写入 S3 后返回预签名下载链接:

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3'); const { getSignedUrl } = require('@aws-sdk/s3-request-presigner'); exports.handler = async (event) => { const s3 = new S3Client({}); const command = new PutObjectCommand({ Bucket: process.env.BUCKET_NAME, Key: `uploads/${Date.now()}.file` }); const uploadUrl = await getSignedUrl(s3, command, { expiresIn: 300 }); return { statusCode: 200, body: JSON.stringify({ uploadUrl }) }; };

10.7 无限循环或递归调用

严重度:HIGH

典型自触发链路:S3 触发器写回同一桶、DynamoDB 触发器更新同一张表、SNS 发布回触发自身的主题、Step Functions 错误处理不当。

四道防线:

  1. 使用不同的桶/前缀,并用前缀过滤触发:
    Events: S3Event: Type: S3 Properties: Bucket: !Ref InputBucket Events: s3:ObjectCreated:* Filter: S3Key: Rules: - Name: prefix Value: uploads/ # Only trigger on uploads/
  2. 幂等检查,跳过已处理文件:
    if (key.startsWith('processed/')) { console.log('Skipping already processed file:', key); continue; }
  3. 设置保留并发作为熔断器:
    Resources: RiskyFunction: Type: AWS::Serverless::Function Properties: ReservedConcurrentExecutions: 10 # Max 10 parallel
  4. CloudWatch 告警兜底:
    InvocationAlarm: Type: AWS::CloudWatch::Alarm Properties: MetricName: Invocations Namespace: AWS/Lambda Statistic: Sum Period: 60 EvaluationPeriods: 1 Threshold: 1000 # Alert if >1000 invocations/min ComparisonOperator: GreaterThanThreshold

十一、Validation Checks:落地前的自动校验清单

文档在交付前提供了一套分级校验规则(见 detailed-guide.md),可作为代码评审与 Agent 自检的量化标准:

检查项级别说明
硬编码 AWS 凭证ERROR必须改用 IAM 角色或环境变量
源码内出现 Secret KeyERROR改用 Secrets Manager 或环境变量
IAM 策略过度授权WARNING避免通配权限,遵循最小权限
Handler 无错误处理WARNING必须加 try/catch 优雅降级
缺少callbackWaitsForEmptyEventLoopINFONode.js 建议显式置 false
默认 128MB 内存INFO许多负载建议上调
超时仅 1~3 秒WARNING涉及外部调用必须提高
未配置 DLQWARNING异步调用必须有死信队列
整包导入 AWS SDK v2WARNING改用 SDK v3 模块化导入
硬编码 DynamoDB 表名WARNING必须走环境变量

这套清单与技能risk: critical的定位一致——它把"面向失败设计""最小权限""配置外置"这些原则落成了可机械执行的检查项。


十二、协作边界:何时转交其他技能

当请求超出aws-serverless的范围时,文档定义了明确的委托路径(见 detailed-guide.md):

用户需求转交技能
GCP Serverlessgcp-cloud-run(容器) / Cloud Functions(事件)
Azure Serverlessazure-functions
数据库设计postgres-wizard(RDS 设计)或使用 DynamoDB 模式
认证授权auth-specialist(Cognito、API Gateway authorizers)
复杂工作流workflow-automation(Step Functions、EventBridge)
AI 集成llm-architect(Lambda 调用 Bedrock 或外部 LLM)

这条映射表是 AAS 技能生态"职责边界"的典型示例:aws-serverless只负责计算编排与事件管道本身,数据库、认证、工作流、AI 能力交由更专精的技能承接,避免职责重叠与上下文污染。


十三、总结

本文完整展开了aws-serverless技能的参考文档(detailed-guide.md,同时在仓库的 skills/aws-serverless/references/detailed-guide.md 存在同源副本),覆盖了从设计原则、七种核心模式到七类生产陷阱、十项校验规则与跨技能协作边界的完整闭环。实践时的核心心法可以概括为三句话:

  1. 先度量再优化——INIT 时长、内存水位、冷启动频率都要以 CloudWatch 数据为准,不要凭感觉配置;
  2. 面向失败设计——DLQ、重试、幂等、熔断(保留并发)四件套缺一不可;
  3. 配置外置、权限最小化——环境变量承载配置,IAM 策略精确到表/桶,这是校验清单里两条 ERROR 规则的直接要求。

最后提醒:技能自身明确要求"输出不能替代环境特定验证"(见 SKILL.md),任何模板落地到具体账号前,请结合组织现有的 IAM 基线、网络拓扑与合规要求做最终适配。

  • AI 技能
  • AI 插件
  • 人工智能

【免费下载链接】agentic-awesome-skills

AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.

项目地址:https://gitcode.com/GitHub_Trending/an/agentic-awesome-skills
点击查看免费下载
上一篇:Claude for Office 清单生成完全指南:用 build-manifest.mjs 定制企业级 Office 加载项清单
下一篇:electron-vue 内置 Vue 插件全解析:axios、vue-electron、vue-router、vuex 与 vuex-electron 实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进