从 EC2 迁移到 Lambda + Bedrock:一次 Serverless AI 架构实践的完整复盘

前言

在做技术选型的时候,"用不用 Serverless" 这个问题经常被讨论。这篇文章不谈理论,记录一次真实的迁移过程——把一个跑在 EC2 上的 AI 问答服务,迁移到 Lambda + Bedrock 的 Serverless 架构。重点分析迁移动机、技术实现、踩坑过程和最终效果。

迁移动机

原来的架构是经典的 EC2 + FastAPI:

  • EC2 t3.medium 跑 Python FastAPI
  • 接受用户问题,调用 Bedrock API 返回回答
  • 7×24 运行,主要工作时间(8:00-18:00)有请求

问题在于:这台服务器大部分时间是空闲的。实际计算表明,每天真正在处理请求的时间不超过 10 分钟。剩下的 23 小时 50 分钟都在空转。

按照亚马逊云科技 Lambda 的计费模型——只在代码运行时才收费——这个场景非常适合做 Serverless 改造。

新架构

客户端 → API Gateway (HTTP API) → Lambda → Bedrock (Claude 3.5 Sonnet) → 客户端

去掉了 EC2 和 FastAPI,Lambda 直接承接原来的 API 逻辑。

核心函数

import json
import boto3

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

def lambda_handler(event, context):
    body = json.loads(event.get('body', '{}'))
    question = body.get('question', '')
    
    if not question:
        return {'statusCode': 400, 'body': json.dumps({'error': '缺少问题参数'})}
    
    response = bedrock.invoke_model(
        modelId='anthropic.claude-3-5-sonnet-20241022-v2:0',
        contentType='application/json',
        accept='application/json',
        body=json.dumps({
            'anthropic_version': 'bedrock-2023-05-31',
            'max_tokens': 2048,
            'messages': [{'role': 'user', 'content': question}]
        })
    )
    
    result = json.loads(response['body'].read())
    return {
        'statusCode': 200,
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps({'answer': result['content'][0]['text']})
    }

比 FastAPI 版本少了一半代码。不需要 uvicorn、不需要 requirements.txt(boto3 是 Lambda 内置的)、不需要 Dockerfile。

迁移中的关键问题

问题一:IAM 权限配置

这个坑了不少人。Bedrock foundation model 的 ARN 有个特殊格式:

arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-*

中间 :: 是对的——账号 ID 字段为空。跟大多数亚马逊云科技服务的 ARN 格式不同。

问题二:超时配置

Lambda 默认超时 3 秒,而 Bedrock Claude 模型的响应时间在 5-15 秒之间。迁移后第一次测试 100% 超时。

需要调整到至少 30 秒,给模型足够的响应时间。

问题三:冷启动延迟

EC2 方案是常驻的,响应延迟稳定。Lambda 冷启动后,首次请求延迟会增加 2-5 秒。

对于低频场景可以接受。如果对延迟敏感,可以配置预置并发(Provisioned Concurrency),代价是固定费用——但仍然比 EC2 便宜。

问题四:Bedrock 区域限制

Lambda 部署在 ap-northeast-1(东京),但 Bedrock 的 Claude 模型当时只在 us-east-1 和 us-west-2 可用。需要跨区域调用,增加约 50-100ms 网络延迟。在 AI 应用场景下(本身就要等几秒),这个额外延迟可以忽略。

迁移前后对比

指标 EC2 方案 Lambda 方案
月成本(不含模型费) ~$30 ~$0.20
部署复杂度 Dockerfile + systemd + nginx 一个 Python 文件
运维工作 系统更新、监控、备份 基本为零
冷启动延迟 2-5 秒(可优化)
自动扩缩容 需要手动配置 ASG 内置
最大并发 受实例规格限制 默认 1000 并发

哪些场景不适合迁移

实事求是地说,不是所有场景都适合 Serverless:

  1. 高并发持久连接:WebSocket 聊天场景,Lambda 的执行时间限制(15 分钟)和连接管理不方便
  2. 自定义模型推理:需要加载几 GB 的模型权重,Lambda 的 /tmp 只有 512MB-10GB
  3. 稳定高负载:如果 QPS 持续很高(每秒几百次),EC2 预留实例可能更划算

总结

这次迁移的核心收益是成本降了 99%,从每月 $30 降到 $0.20。代价是冷启动延迟和一些架构限制。

对于低频、事件驱动的 AI 应用场景,Lambda + Bedrock 的组合非常高效。不需要管理服务器,不需要操心扩缩容,按调用付费。

以上所有代码和配置基于亚马逊云科技 Lambda Python 3.12 运行时和 Bedrock Claude 3.5 Sonnet 模型验证通过。

posted @ 2026-03-17 08:03  亚马逊云开发者  阅读(0)  评论(0)    收藏  举报