与 API 网关一起部署在 Docker 容器中的 Lambda 函数一直面临着极其缓慢的冷启动。
技术堆栈:
为了进行部署,我一直使用 AWS SAM 和以下模板文件:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
demo
Resources:
AppFunction:
Type: AWS::Serverless::Function
Properties:
Timeout: 118
MemorySize: 3008
CodeUri: app/
PackageType: Image
Events:
ApiEvent:
Properties:
RestApiId:
Ref: FastapiExampleGateway
Path: /{proxy+}
Method: ANY
Auth:
ApiKeyRequired: true
Type: Api
Metadata:
Dockerfile: Dockerfile
DockerContext: .
FastapiExampleGateway:
Type: AWS::Serverless::Api
Properties:
StageName: prod
OpenApiVersion: '3.0.0'
# Timeout: 30
Auth:
ApiKeyRequired: true
UsagePlan:
CreateUsagePlan: PER_API
UsagePlanName: GatewayAuthorization
Outputs:
Api:
Description: "API Gateway endpoint URL for Prod stage for App function"
Value: !Sub "https://${FastapiExampleGateway}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
lambda相对较轻,安装时需要满足以下要求:
jsonschema==4.16.0
numpy==1.23.3
pandas==1.5.0
pandas-gbq==0.17.8
fastapi==0.87.0
uvicorn==0.19.0
PyYAML==6.0
SQLAlchemy==1.4.41
pymongo==4.3.2
google-api-core==2.10.1
google-auth==2.11.0
google-auth-oauthlib==0.5.3
google-cloud-bigquery==3.3.2
google-cloud-bigquery-storage==2.16.0
google-cloud-core==2.3.2
google-crc32c==1.5.0
google-resumable-media==2.3.3
googleapis-common-protos==1.56.4
mangum==0.11.0
我用于部署的 Dockerfile 是:
FROM public.ecr.aws/lambda/python:3.9
WORKDIR /code
RUN pip install pip --upgrade
COPY ./api/requirements.txt /code/api/requirements.txt
RUN pip install --no-cache-dir -r /code/api/requirements.txt
COPY ./api /code/api
EXPOSE 7777
CMD ["api.main.handler"]
ENV PYTHONPATH "${PYTHONPATH}:/code/"
导致 250mb 的图像。
在第一次 Lambda 拉取时,我看到了
看起来在实际的 lambda 执行之前有一个很长的开始。由于最长响应时间为 30 秒,API 网关已经超时!
sam local start-api
进行本地测试效果很好。不确定这是否是 Mangum(FastAPI 的包装)的问题?
我对容器支持的 Lambda 的体验与您相同。对于 1GB 容器,我的初始化时间可能是 5-20 秒。每个库导入的时间大约是我个人机器上的 10 倍,即使分配了最大内存(以及 CPU)。
这里有一篇来自 AWS Lambda 工程师的博客文章 https://brooker.co.za/blog/2023/05/23/snapshot-loading.html 解释了 AWS 从 S3 延迟加载整个容器文件系统。这意味着实际的冷启动时间比综合测试中出现的时间要糟糕得多(例如 mikhail.io/serverless/coldstarts/aws 上的博客文章),因为它们可能“使用”5GB 容器,但我强烈怀疑它们不要碰其中的任何文件。
Lambda 对图像使用的多级缓存也使得测试这些内容变得困难。因为虽然日志会告诉您是否进行了冷启动(“init”时间),但它并没有告诉您它是从哪个 Lambda 缓存中提取的(可能是三者的混合)。当某个功能在 6 小时内没有使用时,我可能会得到 2-5 秒的冷启动时间。但当一周没有使用时,我会得到 10-20 秒的冷启动时间。
这一切都非常令人失望。结果是,您本质上必须对面向客户端的任何事情使用预配置并发。