如何增加 AWS lambda 部署包的最大大小(RequestEntityTooLargeException)?

How to increase the maximum size of the AWS lambda deployment package (RequestEntityTooLargeException)?

我从 AWS codebuild 上传了我的 lambda 函数源。我的 Python 脚本使用 NLTK,因此它需要大量数据。我的 .zip 包太大,出现 RequestEntityTooLargeException。我想知道如何增加通过 UpdateFunctionCode 命令发送的部署包的大小。

我使用 AWS CodeBuild 将源代码从 GitHub 存储库转换为 AWS Lambda。这是相关的构建规范文件:

version: 0.2
phases:
 install:
   commands:
     - echo "install step"
     - apt-get update
     - apt-get install zip -y
     - apt-get install python3-pip -y
     - pip install --upgrade pip
     - pip install --upgrade awscli
     # Define directories
     - export HOME_DIR=`pwd`
     - export NLTK_DATA=$HOME_DIR/nltk_data
 pre_build:
   commands:
     - echo "pre_build step"
     - cd $HOME_DIR
     - virtualenv venv
     - . venv/bin/activate
     # Install modules
     - pip install -U requests
     # NLTK download
     - pip install -U nltk
     - python -m nltk.downloader -d $NLTK_DATA wordnet stopwords punkt
     - pip freeze > requirements.txt
 build:
   commands:
     - echo 'build step'
     - cd $HOME_DIR
     - mv $VIRTUAL_ENV/lib/python3.6/site-packages/* .
     - sudo zip -r9 algo.zip .
     - aws s3 cp --recursive --acl public-read ./ s3://hilightalgo/
     - aws lambda update-function-code --function-name arn:aws:lambda:eu-west-3:671560023774:function:LaunchHilight --zip-file fileb://algo.zip
     - aws lambda update-function-configuration --function-name arn:aws:lambda:eu-west-3:671560023774:function:LaunchHilight --environment 'Variables={NLTK_DATA=/var/task/nltk_data}'
 post_build:
   commands:
     - echo "post_build step"

当我启动管道时,我有 RequestEntityTooLargeException 因为我的 .zip 包中的数据太多。请参阅下面的构建日志:

[Container] 2019/02/11 10:48:35 Running command aws lambda update-function-code --function-name arn:aws:lambda:eu-west-3:671560023774:function:LaunchHilight --zip-file fileb://algo.zip
 An error occurred (RequestEntityTooLargeException) when calling the UpdateFunctionCode operation: Request must be smaller than 69905067 bytes for the UpdateFunctionCode operation
 [Container] 2019/02/11 10:48:37 Command did not exit successfully aws lambda update-function-code --function-name arn:aws:lambda:eu-west-3:671560023774:function:LaunchHilight --zip-file fileb://algo.zip exit status 255
[Container] 2019/02/11 10:48:37 Phase complete: BUILD Success: false
[Container] 2019/02/11 10:48:37 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: aws lambda update-function-code --function-name arn:aws:lambda:eu-west-3:671560023774:function:LaunchHilight --zip-file fileb://algo.zip. Reason: exit status 255

当我减少要下载的 NLTK 数据时,一切正常(我尝试只使用包 stopwordswordnet

有没有人有解决这个问题的想法"size limit problem"?

您不能增加 Lambda 的部署包大小。 AWS Lambda devopler guide. More information on how those limits work can be seen here 中描述了 AWS Lambda 限制。本质上,您的解压缩包大小必须小于 250MB(262144000 字节)。

PS:使用层并不能解决大小调整问题,但有助于管理并且可能加快冷启动速度。包大小包括图层 - Lambda layers.

A function can use up to 5 layers at a time. The total unzipped size of the function and all layers can't exceed the unzipped deployment package size limit of 250 MB.

PPS:根据 AWS blog, as pointed by user jonnocraig ,如果您在 Lambda 上为您的应用程序构建容器并 运行 它,则可以克服这些限制。

您不能增加包的大小,但您可以使用 AWS Lambda 层来存储一些应用程序依赖项。

https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path

在此层之前,解决此限制的常用模式是从 S3 下载大量依赖项。

我自己没试过,但是 Zappa describe a trick that might help. Quoting from https://blog.zappa.io/posts/slim-handler 的人:

Zappa zips up the large application and sends the project zip file up to S3. Second, Zappa creates a very minimal slim handler that just contains Zappa and its dependencies and sends that to Lambda.

When the slim handler is called on a cold start, it downloads the large project zip from S3 and unzips it in Lambda’s shared /tmp space. All subsequent calls to that warm Lambda share the /tmp space and have access to the project files; so it is possible for the file to only download once if the Lambda stays warm.

这样你应该在 /tmp 中获得 500MB。

更新:

我在几个项目的lambdas中使用了下面的代码,它是基于zappa使用的方法,但可以直接使用。

# Based on the code in https://github.com/Miserlou/Zappa/blob/master/zappa/handler.py
# We need to load the layer from an s3 bucket into tmp, bypassing the normal
# AWS layer mechanism, since it is too large, AWS unzipped lambda function size
# including layers is 250MB.
def load_remote_project_archive(remote_bucket, remote_file, layer_name):
    
    # Puts the project files from S3 in /tmp and adds to path
    project_folder = '/tmp/{0!s}'.format(layer_name)
    if not os.path.isdir(project_folder):
        # The project folder doesn't exist in this cold lambda, get it from S3
        boto_session = boto3.Session()

        # Download zip file from S3
        s3 = boto_session.resource('s3')
        archive_on_s3 = s3.Object(remote_bucket, remote_file).get()

        # unzip from stream
        with io.BytesIO(archive_on_s3["Body"].read()) as zf:

            # rewind the file
            zf.seek(0)

            # Read the file as a zipfile and process the members
            with zipfile.ZipFile(zf, mode='r') as zipf:
                zipf.extractall(project_folder)

    # Add to project path
    sys.path.insert(0, project_folder)

    return True

然后可以按如下方式调用(我通过环境变量将带有图层的桶传递给 lambda 函数):

load_remote_project_archive(os.environ['MY_ADDITIONAL_LAYERS_BUCKET'], 'lambda_my_extra_layer.zip', 'lambda_my_extra_layer')

在我写这段代码的时候,tmp也被封顶了,我想是250MB,但是上面对zipf.extractall(project_folder)的调用可以用直接提取到内存来代替:unzipped_in_memory = {name: zipf.read(name) for name in zipf.namelist()} 这是我为一些机器学习模型所做的,我想 @rahul 的答案对此更通用。

实际上,您可以要求增加部署包大小的限制

1。登录 AWS 控制台后转到 AWS Support

https://docs.aws.amazon.com/awssupport/latest/user/getting-started.html

2。然后要求提高服务限额。

3。并填写所需的最大尺寸。

AWS 支持工程师会就限制增加批准给您回复

您可以尝试很棒的 serverless-python-requirements 插件中使用的解决方法。

如果能解决问题,理想的解决方案是使用 lambda 层。如果总依赖项大于 250MB,那么您可以在 运行 时间内利用 /tmp 目录中提供的 512 MB 从 S3 存储桶中侧载较少使用的依赖项。压缩的依赖项存储在 S3 中,lambda 可以在初始化期间从 S3 中获取文件。解压缩依赖包并将路径添加到 sys 路径。

请注意,python 依赖项需要在 Amazon Linux 上构建,这是 lambda 容器的操作系统。我使用 EC2 实例来创建 zip 包。

你检查serverless中使用的代码-python-requirements here

AWS Lambda 函数可以挂载 EFS。您可以使用 EFS 加载大于 AWS Lambda 的 250 MB 程序包部署大小限制的库或程序包。

这里有详细的设置步骤: https://aws.amazon.com/blogs/aws/new-a-shared-file-system-for-your-lambda-functions/

总的来说,变化包括:

  1. 创建和设置 EFS 文件系统
  2. 将 EFS 与 lambda 函数结合使用
  3. 在 EFS 访问点内安装 pip 依赖项
  4. 设置 PYTHONPATH 环境变量以告知在何处查找依赖项

以下是 Lambda 的硬限制(将来可能会更改):

  • 3 MB 用于控制台内编辑
  • 50 MB 压缩包上传
  • 解压后 250 MB,包括图层

解决此问题的明智方法是从您的 Lambda 安装 EFS。这不仅可以用于加载库,还可以用于其他存储。

浏览一下这些博客:

如果有人偶然发现此问题 post 2020 年 12 月,AWS 进行了重大更新以支持 Lambda 函数作为容器映像(最大 10GB!!)。更多信息 here

来自 AWS documentation:

If your deployment package is larger than 50 MB, we recommend uploading your function code and dependencies to an Amazon S3 bucket.

You can create a deployment package and upload the .zip file to your Amazon S3 bucket in the AWS Region where you want to create a Lambda function. When you create your Lambda function, specify the S3 bucket name and object key name on the Lambda console, or using the AWS Command Line Interface (AWS CLI).

您可以使用 AWS CLI 来部署包,而不是使用 --zip-file 参数来传递部署包,您可以在带有 --code 参数的 S3 存储桶。例如:

aws lambda create-function --function-name my_function --code S3Bucket=my_bucket,S3Key=my_file

在 AWS 中使用大型 lambda 项目的技巧是在 AWS ECR 服务中使用 docker 图像存储而不是 ZIP 文件。您最多可以使用一张 docker 图片 10GO。

AWS 文档提供了一个示例来帮助您: Create an image from an AWS base image for Lambda

聚会可能会迟到,但您可以使用 Docker 图像来绕过 lambda 层约束。这可以使用无服务器堆栈开发或仅通过控制台来完成。

2021 年之前,最好的方法是将 jar 文件部署到 S3,并用它创建 AWS lambda。

从 2021 年开始,AWS Lambda 开始支持容器镜像。阅读此处:https://aws.amazon.com/de/blogs/aws/new-for-aws-lambda-container-image-support/

所以从现在开始,您可能应该考虑将 Lambda 函数打包并部署为容器映像(最多 10 GB)。

这个来自 github (https://github.com/awslabs/aws-data-wrangler/releases) 的 aws wrangler zip 文件包括许多其他库,如 pandas 和 pymysql。在我的例子中,它是我唯一需要的层,因为它有很多其他的东西。可能对某些人有用。