跳转到主要内容

为AWS Lambda和API Gateway提供无服务器Python Web服务

项目描述

Zappa Rocks!

Zappa - 服务器less Python

CI Coverage PyPI Slack

关于

Zappa Slides

赶时间吗?点击查看来自Serverless SF的幻灯片(现在有些过时):(now slightly out-dated)slides from Serverless SF

Zappa使构建和部署在AWS Lambda + API Gateway上的无服务器、事件驱动的Python应用程序(包括但不限于WSGI网络应用)变得超级简单。将其视为为您的Python应用程序提供的“无服务器”网络托管。这意味着 无限扩展零停机时间零维护 - 而且成本只有您当前部署的一小部分!

如果您有一个Python网络应用(包括Django和Flask应用),它就像这样

$ pip install zappa
$ zappa init
$ zappa deploy

现在您是无服务器的! 哇!

“无服务器”是什么意思?

好吧,所以服务器还在 - 但它的生命周期只有 40毫秒!在这个例子中,“无服务器”意味着 “没有任何永久的基础设施。”

使用传统的HTTP服务器,服务器全天候在线,逐个处理传入的请求。如果传入请求的队列太大,一些请求将超时。使用Zappa,每个请求都由Amazon API Gateway提供一个自己的虚拟HTTP“服务器”。AWS自动处理水平扩展,因此不会有任何请求超时。每个请求然后从AWS Lambda中的内存缓存调用您的应用程序,并通过Python的WSGI接口返回响应。您的应用程序返回后,“服务器”就会死亡。

更重要的是,使用Zappa,您只为使用的服务器时间付费,所以它比Linode或Heroku等VPS/PaaS托管商便宜许多个数量级 - 在大多数情况下,它完全是免费的。此外,您再也不用担心负载均衡或保持服务器在线了。

非常适合使用Flask和Bottle等框架部署无服务器微服务,以及使用Django托管大型Web应用和CMS。或者,您可以使用任何您喜欢的WSGI兼容的应用程序!您很可能不需要更改现有的应用程序来使用它,并且您不会被锁定在使用它。

Zappa还允许您构建混合事件驱动应用程序,可以在不增加您额外工作量的情况下扩展到每年数万亿事件!您还将获得免费SSL证书、全球应用部署、API访问管理、自动安全策略生成、预编译的C扩展、自动预热、超大的Lambda包以及许多其他独家功能!

最后,Zappa使用非常简单。您可以直接使用单个命令部署应用程序!

太酷了!

Zappa Demo Gif

安装和配置

在开始之前,请确保您正在运行Python 3.8/3.9/3.10/3.11/3.12,并且您拥有有效的AWS账户以及您的AWS凭据文件已正确安装。

Zappa可以通过pip轻松安装,如下所示

$ pip install zappa

请注意,Zappa 必须安装到您项目的虚拟环境中。虚拟环境名称不应与Zappa项目名称相同,因为这可能会导致错误。

(如果您使用pyenv并且喜欢使用pyenv-virtualenv管理虚拟环境,只需调用pyenv local [your_venv_name]即可。 Conda用户请在此处评论。)

接下来,您需要定义本地和服务器端设置。

运行初始设置/设置

Zappa可以使用init命令自动为您设置部署设置

$ zappa init

这将自动检测您的应用程序类型(Flask/Django - Pyramid用户请在此处查看)并帮助您定义部署配置设置。完成初始化后,您将在项目目录中有一个名为zappa_settings.json的文件,用于定义您的基本部署设置。对于大多数WSGI应用程序,它可能看起来像这样

{
    // The name of your stage
    "dev": {
        // The name of your S3 bucket
        "s3_bucket": "lambda",

        // The modular python path to your WSGI application function.
        // In Flask and Bottle, this is your 'app' object.
        // Flask (your_module.py):
        // app = Flask()
        // Bottle (your_module.py):
        // app = bottle.default_app()
        "app_function": "your_module.app"
    }
}

或者对于Django

{
    "dev": { // The name of your stage
       "s3_bucket": "lambda", // The name of your S3 bucket
       "django_settings": "your_project.settings" // The python path to your Django settings.
    }
}

提示:如果您第一次使用Zappa部署Django应用程序,您可能想阅读Edgar Roman的Django Zappa指南

您可以定义尽可能多的阶段 - 我们建议有devstagingproduction

现在,您已准备好部署了!

基本用法

初始部署

设置好设置后,您可以使用单个命令打包并部署您的应用程序到名为“production”的阶段

$ zappa deploy production
Deploying..
Your application is now live at: https://7k6anj0k99.execute-api.us-east-1.amazonaws.com/production

现在您的应用程序已经上线了!这有多酷?!

为了解释正在发生的事情,当您调用deploy时,Zappa将自动将您的应用程序和本地虚拟环境打包成与Lambda兼容的存档,将任何依赖项替换为与Lambda兼容的版本,设置函数处理程序和必要的WSGI中间件,将存档上传到S3,创建和管理必要的Amazon IAM策略和角色,将其注册为新的Lambda函数,创建新的API Gateway资源,为其创建WSGI兼容的路由,将其链接到新的Lambda函数,并最终从您的S3存储桶中删除存档。太方便了!

请注意,为执行Lambda而创建的默认IAM角色和策略应用了一组宽松的权限。这些权限很可能不适用于生产部署重要应用程序。有关更多详细信息,请参阅自定义AWS IAM角色和策略部分。

更新

如果您的应用程序已经部署并且您只需上传新的Python代码,而不需要修改底层的路由,您可以简单地

$ zappa update production
Updating..
Your application is now live at: https://7k6anj0k99.execute-api.us-east-1.amazonaws.com/production

这会创建一个新的存档,将其上传到S3并更新Lambda函数以使用新代码,但不会修改API网关路由。

Docker工作流程

版本0.53.0中,增加了使用Docker部署和更新Lambda函数的支持。

您可以使用zappa命令中的--docker-image-uri选项指定ECR镜像,在deployupdate时使用。Zappa期望该镜像已构建并推送到Amazon ECR存储库。

部署示例

$ zappa deploy --docker-image-uri {AWS ACCOUNT ID}.dkr.ecr.{REGION}.amazonaws.com/{REPOSITORY NAME}:latest

更新示例

$ zappa update --docker-image-uri {AWS ACCOUNT ID}.dkr.ecr.{REGION}.amazonaws.com/{REPOSITORY NAME}:latest

有关如何利用此功能以及何时可能想要使用的更多信息,请参阅博客文章

如果您正在使用自定义Docker镜像作为Lambda运行时(例如,如果您想使用Lambda默认不支持的新版本的Python)并且您想绕过Python版本检查,您可以通过设置环境变量来实现

$ export ZAPPA_RUNNING_IN_DOCKER=True

您也可以将其添加到您的Dockerfile中,如下所示

ENV ZAPPA_RUNNING_IN_DOCKER=True

回滚

您还可以通过指定要返回的修订次数来rollback已部署的代码到先前的版本。例如,要回滚到3个版本之前的版本

$ zappa rollback production -n 3

计划任务

Zappa可以轻松地安排函数在规律的时间间隔内执行。这提供了一个比Celery更佳、无需维护的替代方案!这些函数将与您的app_function一起打包和部署,并由处理程序自动调用。只需列出您的函数和用于安排它们的表达式,在您的zappa_settings.json文件中使用cron或rate语法

{
    "production": {
       ...
       "events": [{
           "function": "your_module.your_function", // The function to execute
           "expression": "rate(1 minute)" // When to execute it (in cron or rate format)
       }],
       ...
    }
}

然后

$ zappa schedule production

现在您的函数将每分钟执行一次!

如果您想取消这些,请简单使用unschedule命令

$ zappa unschedule production

现在您的计划事件规则已被删除。

请参阅示例获取更多详细信息。

高级计划任务

多个表达式

有时一个函数需要多个表达式来描述其计划。要设置多个表达式,只需列出您的函数和用于安排它们的表达式列表,在您的zappa_settings.json文件中使用cron或rate语法

{
    "production": {
       ...
       "events": [{
           "function": "your_module.your_function", // The function to execute
           "expressions": ["cron(0 20-23 ? * SUN-THU *)", "cron(0 0-8 ? * MON-FRI *)"] // When to execute it (in cron or rate format)
       }],
       ...
    }
}

这可以用来解决您当地时区在业务时间穿越午夜时产生的UTC时区问题。

需要注意的是,重叠的表达式不会抛出警告,应该进行检查,以防止函数重复触发。

禁用事件

有时需要安排一个事件,但又不希望启用它。例如,可能只有生产环境中的事件应该运行,而沙盒不应该。在部署到生产环境之前,您可能仍然想将它们部署到沙盒以确保表达式没有问题。

在这种情况下,您可以通过将事件定义中的enabled设置为false来禁用其运行

{
    "sandbox": {
       ...
       "events": [{
           "function": "your_module.your_function", // The function to execute
           "expression": "rate(1 minute)", // When to execute it (in cron or rate format)
           "enabled": false
       }],
       ...
    }
}

未部署

如果您需要删除之前发布过的API网关和Lambda函数,您可以简单地

$ zappa undeploy production

在执行之前会要求您确认。

如果您为API网关服务启用了CloudWatch日志,并且您不想保留这些日志,您可以指定--remove-logs参数来清除API网关和Lambda函数的日志

$ zappa undeploy production --remove-logs

打包

如果您想在不上传和注册为Lambda函数的情况下构建您的应用程序包,可以使用package命令

$ zappa package production

如果您在callbacks设置中有zip回调,这也会被调用。

{
    "production": { // The name of your stage
        "callbacks": {
            "zip": "my_app.zip_callback"// After creating the package
        }
    }
}

您也可以使用-o指定包的输出文件名

$ zappa package production -o my_awesome_package.zip

Zappa如何制作打包文件

Zappa会自动将您的活动虚拟环境打包成一个在AWS Lambda上运行顺畅的包。

在此过程中,它会用AWS Lambda兼容的版本替换任何本地依赖项。依赖项按以下顺序包括

  • 来自本地缓存的与Lambda兼容的manylinux wheel
  • 来自PyPI的与Lambda兼容的manylinux wheel
  • 来自活动虚拟环境中的包
  • 来自本地项目目录中的包

它还会跳过某些不必要的文件,如果有.pyc文件,则忽略任何.py文件。

此外,Zappa还会自动设置正确的执行权限,配置包设置,并创建一个唯一的、可审计的包清单文件。

为了进一步减少最终包文件的大小,您可以

  • slim_handler设置为True,以上传到Lambda的小型处理程序,并将其余包上传到S3。有关更多详细信息,请参阅合并的pull请求原始问题中的讨论。另请参阅:大型项目
  • 使用excludeexclude_glob设置并提供要排除的模式的列表。默认情况下,Zappa会排除Boto,因为它已经在Lambda执行环境中可用

模板

类似于package,如果您只想获取API Gateway CloudFormation模板,请使用template命令

$ zappa template production --l your-lambda-arn -r your-role-arn

请注意,在这种情况下,您必须提供自己的Lambda ARN和Role ARN,因为它们可能还没有为您创建。

您可以使用--json直接获取JSON输出,并使用--output指定输出文件。

状态

如果您需要查看部署状态和事件计划,只需使用status命令。

$ zappa status production

跟踪日志

您可以通过调用tail管理命令来查看部署的日志。

$ zappa tail production

默认情况下,这将显示所有日志项。除了HTTP和其他事件外,任何打印到stdoutstderr的内容都将显示在日志中。

您可以使用--http参数过滤HTTP请求,它们将以Apache Common Log格式显示。

$ zappa tail production --http

类似地,您可以执行相反的操作,只显示非HTTP事件和日志消息

$ zappa tail production --non-http

如果您不喜欢默认的日志颜色,可以使用--no-color将其关闭。

您还可以使用--since限制日志的长度,它接受简单的持续时间字符串

$ zappa tail production --since 4h # 4 hours
$ zappa tail production --since 1m # 1 minute
$ zappa tail production --since 1mm # 1 month

您可以使用--filter过滤日志内容,如下所示

$ zappa tail production --http --filter "POST" # Only show POST HTTP requests

请注意,这使用的是CloudWatch Logs过滤器语法

要尾随日志而不跟随(在显示请求的日志的末尾后立即退出),请传递--disable-keep-open

$ zappa tail production --since 1h --disable-keep-open

远程函数调用

您可以使用invoke命令在任何时候直接执行应用程序中的任何函数。

例如,假设您有一个名为“my_app.py”的文件中的基本应用程序,并且您想调用其中的“my_function”函数。一旦您的应用程序部署完成,您可以通过以下方式在任何时候调用该函数

$ zappa invoke production my_app.my_function

然后,任何远程打印语句和函数返回的值都将打印到您的本地控制台。很酷!

您还可以使用--raw直接调用可解释的Python 3.8/3.9/3.10/3.11/3.12字符串,如下所示

$ zappa invoke production "print(1 + 2 + 3)" --raw

例如,如果您想在VPC中运行的RDS数据库(如Serverless Aurora)上创建第一个superuser,这可能会很有用

$ zappa invoke staging "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('username', 'email', 'password')" --raw

Django管理命令

作为一个便利,Zappa还可以使用manage命令调用远程Django 'manage.py'命令。例如,要执行基本的Django状态检查

$ zappa manage production showmigrations admin

显然,这仅适用于已经正确定义设置的Django项目。

对于具有自己参数的命令,您也可以将命令作为字符串传递,如下所示

$ zappa manage production "shell --version"

需要直接用户输入的命令,如createsuperuser,应该用使用zappa invoke <env> --raw的命令替换。

想了解更多Django集成,请查看zappa-django-utils项目。

SSL证书

Zappa可以部署到自定义域名和子域名,支持自定义SSL证书、Let's Encrypt证书以及AWS证书管理器(ACM)证书。

目前,这些方法中最容易使用的是AWS证书管理器证书,因为它们免费、自动续费,并且需要的工作量最少。

按照以下说明配置后,所有这些方法都使用相同的命令

$ zappa certify

从CI/CD系统部署时,您可以使用

$ zappa certify --yes

跳过确认提示。

使用AWS证书管理器部署到域名

亚马逊提供自己的免费替代Let's Encrypt的方案,称为AWS证书管理器(ACM)。要使用此服务与Zappa配合

  1. 在AWS证书管理器控制台中验证您的域名。
  2. 在控制台中,选择N.弗吉尼亚(us-east-1)区域,为您的域名或子域名(sub.yourdomain.tld)请求证书,或请求通配符域名(*.yourdomain.tld)。
  3. 复制该证书的整个ARN并将其放置在Zappa设置中的certificate_arn
  4. domain设置中设置您希望使用的域名。
  5. 调用$ zappa certify以使用该证书创建并关联API网关分发。

使用Let's Encrypt证书(DNS认证)部署到域名

如果您想在具有免费Let's Encrypt证书的域上使用Zappa,并使用基于自动Route 53的DNS身份验证,可以参考此实用指南

使用Let's Encrypt证书(HTTP认证)部署到域名

如果您想在具有免费Let's Encrypt证书的域上使用Zappa,并使用HTTP身份验证,可以参考此指南

然而,现在使用基于Route 53的DNS身份验证要容易得多,这将允许您使用单个$ zappa certify命令使用Let's Encrypt证书。

使用自己的SSL证书部署到域名

  1. 第一步是创建一个自定义域名并获取您的SSL证书/密钥/包。
  2. 确保您已在Zappa设置JSON中设置了domain设置 - 这将避免自定义域和API调用URL之间基础路径映射的问题,该URL会附加Stage名称到URI
  3. 将SSL证书/密钥/包的路径分别添加到Zappa设置JSON中的certificatecertificate_keycertificate_chain设置中
  4. 如果您计划使用自己的DNS提供商而不是AWS Route53托管区域,请将route53_enabled设置为false
  5. 使用Zappa部署或更新您的应用程序
  6. 运行$ zappa certify以上传您的证书并将自定义域名注册到您的API网关。

响应AWS事件执行

类似地,您可以让您的函数在AWS生态系统中的事件发生时执行,例如S3上传、DynamoDB条目、Kinesis流、SNS消息和SQS队列。

在您的zappa_settings.json文件中,定义您的事件源和您希望执行的函数。例如,这将在新对象出现在您的my-bucket S3存储桶中时执行your_module.process_upload_function。请注意,process_upload_function必须接受eventcontext参数。

{
    "production": {
       ...
       "events": [{
            "function": "your_module.process_upload_function",
            "event_source": {
                  "arn":  "arn:aws:s3:::my-bucket",
                  "events": [
                    "s3:ObjectCreated:*" // Supported event types: http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#supported-notification-event-types
                  ],
                  "key_filters": [{ // optional
                    "type": "suffix",
                    "value": "yourfile.json"
                  },
                  {
                    "type": "prefix",
                    "value": "prefix/for/your/object"
                  }]
               }
            }],
       ...
    }
}

然后

$ zappa schedule production

现在,每当您的存储桶中出现新的上传时,您的函数都会执行!

要访问应用程序上下文中的密钥信息,您希望process_upload_function看起来像这样

import boto3
s3_client = boto3.client('s3')

def process_upload_function(event, context):
    """
    Process a file upload.
    """

    # Get the uploaded file's information
    bucket = event['Records'][0]['s3']['bucket']['name'] # Will be `my-bucket`
    key = event['Records'][0]['s3']['object']['key'] # Will be the file path of whatever file was uploaded.

    # Get the bytes from S3
    s3_client.download_file(bucket, key, '/tmp/' + key) # Download this file to writable tmp space.
    file_bytes = open('/tmp/' + key).read()

类似地,对于简单通知服务事件

        "events": [
            {
                "function": "your_module.your_function",
                "event_source": {
                    "arn":  "arn:aws:sns:::your-event-topic-arn",
                    "events": [
                        "sns:Publish"
                    ]
                }
            }
        ]

可选地,您可以添加SNS消息过滤器

        "events": [
            {
                "function": "your_module.your_function",
                "event_source": {
                    "arn":  "arn:aws:sns:::your-event-topic-arn",
                    "filters": {
                        "interests": ["python", "aws", "zappa"],
                        "version": ["1.0"]
                    },
                    ...
                }
            }
        ]

DynamoDBKinesis略有不同,因为它不是基于事件的,而是从流中拉取数据。

       "events": [
           {
               "function": "replication.replicate_records",
               "event_source": {
                    "arn":  "arn:aws:dynamodb:us-east-1:1234554:table/YourTable/stream/2016-05-11T00:00:00.000",
                    "starting_position": "TRIM_HORIZON", // Supported values: TRIM_HORIZON, LATEST
                    "batch_size": 50, // Max: 1000
                    "enabled": true // Default is false
               }
           }
       ]

SQS也正在从流中拉取消息。目前,只有“标准”队列可以触发Lambda事件,而不是“FIFO”队列。请仔细阅读AWS文档,因为Lambda会在您的函数成功完成后代表您调用SQS DeleteMessage API。

       "events": [
           {
               "function": "your_module.process_messages",
               "event_source": {
                    "arn":  "arn:aws:sqs:us-east-1:12341234:your-queue-name-arn",
                    "batch_size": 10, // Max: 10. Use 1 to trigger immediate processing
                    "enabled": true // Default is false
               }
           }
       ]

配置Lex Bot的意图触发事件

    "bot_events": [
        {
            "function": "lexbot.handlers.book_appointment.handler",
            "event_source": {
                "arn": "arn:aws:lex:us-east-1:01234123123:intent:TestLexEventNames:$LATEST", // optional. In future it will be used to configure the intent
                "intent":"intentName", // name of the bot event configured
                "invocation_source":"DialogCodeHook", // either FulfillmentCodeHook or DialogCodeHook
            }
        }
    ]

事件也可以接受关键字参数

       "events": [
            {
                "function": "your_module.your_recurring_function", // The function to execute
                "kwargs": {"key": "val", "key2": "val2"},  // Keyword arguments to pass. These are available in the event
                "expression": "rate(1 minute)" // When to execute it (in cron or rate format)
            }
       ]

要获取关键字参数,您需要查看事件字典内部

def your_recurring_function(event, context):
    my_kwargs = event.get("kwargs")  # dict of kwargs given in zappa_settings file

您可以在这里找到更多示例事件源

异步任务执行

Zappa现在还提供了在完全独立的AWS Lambda实例中无缝异步执行函数的能力!

例如,如果您有一个用于订购派对的Flask API,您可以使用zappa.asynchronous.task装饰器在完全独立的Lambda实例中无缝调用您的bake函数,如下所示

from flask import Flask
from zappa.asynchronous import task
app = Flask(__name__)

@task
def make_pie():
    """ This takes a long time! """
    ingredients = get_ingredients()
    pie = bake(ingredients)
    deliver(pie)

@app.route('/api/order/pie')
def order_pie():
    """ This returns immediately! """
    make_pie()
    return "Your pie is being made!"

就这样!您的API响应将立即返回,而make_pie函数将在一个完全不同的Lambda实例中执行。

当@task装饰的函数或zappa.asynchronous.run命令在Lambda之外发生,例如在您的本地开发环境中,函数将立即在本地执行。zappa异步功能仅在Lambda环境中或指定远程调用时才有效。

捕获异常

在一个异步任务上放置try..except块

@task
def make_pie():
    try:
        ingredients = get_ingredients()
        pie = bake(ingredients)
        deliver(pie)
    except Fault as error:
        """send an email"""
    ...
    return Response('Web services down', status=503)

将导致同一错误发送两封电子邮件。请参阅AWS中的异步重试。为了解决这种副作用,并使错误处理程序只执行一次,将返回值更改为

@task
def make_pie():
    try:
        """code block"""
    except Fault as error:
        """send an email"""
    ...
    return {} #or return True

任务来源

默认情况下,此功能使用直接AWS Lambda调用。您可以使用task_sns装饰器使用AWS Simple Notification Service作为任务事件源,如下所示

from zappa.asynchronous import task_sns
@task_sns

使用SNS还需要在您的zappa_settings中设置以下设置

{
  "dev": {
    ..
      "async_source": "sns", // Source of async tasks. Defaults to "lambda"
      "async_resources": true, // Create the SNS topic to use. Defaults to true.
    ..
    }
}

这将自动创建和订阅当您调用zappa schedule命令时代码将使用的SNS主题。

使用SNS还将返回一个消息ID,以防您需要跟踪您的调用。

直接调用

您也可以通过将函数传递给zappa.asynchronous.run来使用此功能而不使用装饰器,如下所示

from zappa.asynchronous import run

run(your_function, args, kwargs) # Using Lambda
run(your_function, args, kwargs, service='sns') # Using SNS

远程调用

默认情况下,Zappa将使用lambda的当前函数名和当前AWS区域。如果您希望调用具有不同函数名/区域的lambda或从Lambda外部调用您的lambda,您必须指定remote_aws_lambda_function_nameremote_aws_region参数,以便应用程序知道要使用哪个函数和区域。例如,如果我们的一些披萨制作应用程序必须运行在EC2实例上,但我们希望从其自己的Lambda实例中调用make_pie()函数,我们将这样做

@task(remote_aws_lambda_function_name='pizza-pie-prod', remote_aws_region='us-east-1')
def make_pie():
   """ This takes a long time! """
   ingredients = get_ingredients()
   pie = bake(ingredients)
   deliver(pie)

如果未使用这些task()参数,则EC2将在本地执行该函数。这些相同的remote_aws_lambda_function_nameremote_aws_region参数也可以用在zappa.asynchronous.run()函数上。

限制

对此功能适用的以下限制

  • 函数必须具有干净的导入路径--也就是说,没有闭包、lambda或方法。
  • argskwargs必须是可JSON序列化的。
  • JSON序列化的参数必须在Lambda(256K)或SNS(256K)事件的尺寸限制内。

所有这段代码仍然与Lambda环境非兼容 - 它只是以阻塞方式执行并返回结果。

在VPC中运行任务

如果您在虚拟专用云(VPC)中运行Zappa,您需要配置您的子网以允许Lambda与VPC内部的以及公共互联网上的服务进行通信。最小设置需要两个子网。

subnet-a

  • 创建一个NAT
  • 创建一个互联网网关
  • 在路由表中,创建一个将互联网网关指向0.0.0.0/0的路由。

subnet-b

  • 放置您的lambda函数
  • 在路由表中,创建一个将属于 subnet-a 的NAT指向0.0.0.0/0的路由。

您可以将Lambda放置在多个与 subnet-b 配置相同的子网中,以实现高可用性。

一些有用的资源包括这个教程这个其他教程这个AWS文档页面

响应

可以捕获异步任务的响应。

Zappa将这些作为后端使用DynamoDB。

要捕获响应,必须在zappa_settings中配置一个async_response_table。这是DynamoDB表名。然后,当使用@task进行装饰时,传递capture_response=True

异步响应被分配一个response_id。这是作为由@task装饰器返回的LambdaAsyncResponse(或SnsAsyncResponse)对象的属性返回的。

示例

from zappa.asynchronous import task, get_async_response
from flask import Flask, make_response, abort, url_for, redirect, request, jsonify
from time import sleep

app = Flask(__name__)

@app.route('/payload')
def payload():
    delay = request.args.get('delay', 60)
    x = longrunner(delay)
    return redirect(url_for('response', response_id=x.response_id))

@app.route('/async-response/<response_id>')
def response(response_id):
    response = get_async_response(response_id)
    if response is None:
        abort(404)

    if response['status'] == 'complete':
        return jsonify(response['response'])

    sleep(5)

    return "Not yet ready. Redirecting.", 302, {
        'Content-Type': 'text/plain; charset=utf-8',
        'Location': url_for('response', response_id=response_id, backoff=5),
        'X-redirect-reason': "Not yet ready.",
    }

@task(capture_response=True)
def longrunner(delay):
    sleep(float(delay))
    return {'MESSAGE': "It took {} seconds to generate this.".format(delay)}

高级设置

您可以在本地设置中定义其他设置以更改Zappa的行为。请自行承担风险!

 {
    "dev": {
        "additional_text_mimetypes": [], // allows you to provide additional mimetypes to be handled as text when binary_support is true.
        "alb_enabled": false, // enable provisioning of application load balancing resources. If set to true, you _must_ fill out the alb_vpc_config option as well.
        "alb_vpc_config": {
            "CertificateArn": "your_acm_certificate_arn", // ACM certificate ARN for ALB
            "SubnetIds": [], // list of subnets for ALB
            "SecurityGroupIds": [] // list of security groups for ALB
        },
        "api_key_required": false, // enable securing API Gateway endpoints with x-api-key header (default False)
        "api_key": "your_api_key_id", // optional, use an existing API key. The option "api_key_required" must be true to apply
        "apigateway_enabled": true, // Set to false if you don't want to create an API Gateway resource. Default true.
        "apigateway_description": "My funky application!", // Define a custom description for the API Gateway console. Default None.
        "assume_policy": "my_assume_policy.json", // optional, IAM assume policy JSON file
        "attach_policy": "my_attach_policy.json", // optional, IAM attach policy JSON file
        "apigateway_policy": "my_apigateway_policy.json", // optional, API Gateway resource policy JSON file
        "async_source": "sns", // Source of async tasks. Defaults to "lambda"
        "async_resources": true, // Create the SNS topic and DynamoDB table to use. Defaults to true.
        "async_response_table": "your_dynamodb_table_name",  // the DynamoDB table name to use for captured async responses; defaults to None (can't capture)
        "async_response_table_read_capacity": 1,  // DynamoDB table read capacity; defaults to 1
        "async_response_table_write_capacity": 1,  // DynamoDB table write capacity; defaults to 1
        "aws_endpoint_urls": { "aws_service_name": "endpoint_url" }, // a dictionary of endpoint_urls that emulate the appropriate service.  Usually used for testing, for instance with `localstack`.
        "aws_environment_variables" : {"your_key": "your_value"}, // A dictionary of environment variables that will be available to your deployed app via AWS Lambdas native environment variables. See also "environment_variables" and "remote_env" . Default {}.
        "aws_kms_key_arn": "your_aws_kms_key_arn", // Your AWS KMS Key ARN
        "aws_region": "aws-region-name", // optional, uses region set in profile or environment variables if not set here,
        "binary_support": true, // Enable automatic MIME-type based response encoding through API Gateway. Default true.
        "callbacks": { // Call custom functions during the local Zappa deployment/update process
            "settings": "my_app.settings_callback", // After loading the settings
            "zip": "my_app.zip_callback", // After creating the package
            "post": "my_app.post_callback", // After command has executed
        },
        "cache_cluster_enabled": false, // Use APIGW cache cluster (default False)
        "cache_cluster_size": 0.5, // APIGW Cache Cluster size (default 0.5)
        "cache_cluster_ttl": 300, // APIGW Cache Cluster time-to-live (default 300)
        "cache_cluster_encrypted": false, // Whether or not APIGW Cache Cluster encrypts data (default False)
        "certificate": "my_cert.crt", // SSL certificate file location. Used to manually certify a custom domain
        "certificate_key": "my_key.key", // SSL key file location. Used to manually certify a custom domain
        "certificate_chain": "my_cert_chain.pem", // SSL certificate chain file location. Used to manually certify a custom domain
        "certificate_arn": "arn:aws:acm:us-east-1:1234512345:certificate/aaaa-bbb-cccc-dddd", // ACM certificate ARN (needs to be in us-east-1 region).
        "cloudwatch_log_level": "OFF", // Enables/configures a level of logging for the given staging. Available options: "OFF", "INFO", "ERROR", default "OFF".
        "cloudwatch_data_trace": false, // Logs all data about received events. Default false.
        "cloudwatch_metrics_enabled": false, // Additional metrics for the API Gateway. Default false.
        "cognito": { // for Cognito event triggers
            "user_pool": "user-pool-id", // User pool ID from AWS Cognito
            "triggers": [{
                "source": "PreSignUp_SignUp", // triggerSource from http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-pre-signup
                "function": "my_app.pre_signup_function"
            }]
        },
        "context_header_mappings": { "HTTP_header_name": "API_Gateway_context_variable" }, // A dictionary mapping HTTP header names to API Gateway context variables
        "cors": false, // Enable Cross-Origin Resource Sharing. Default false. If true, simulates the "Enable CORS" button on the API Gateway console. Can also be a dictionary specifying lists of "allowed_headers", "allowed_methods", and string of "allowed_origin"
        "dead_letter_arn": "arn:aws:<sns/sqs>:::my-topic/queue", // Optional Dead Letter configuration for when Lambda async invoke fails thrice
        "debug": true, // Print Zappa configuration errors tracebacks in the 500. Default true.
        "delete_local_zip": true, // Delete the local zip archive after code updates. Default true.
        "delete_s3_zip": true, // Delete the s3 zip archive. Default true.
        "django_settings": "your_project.production_settings", // The modular path to your Django project's settings. For Django projects only.
        "domain": "yourapp.yourdomain.com", // Required if you're using a domain
        "base_path": "your-base-path", // Optional base path for API gateway custom domain base path mapping. Default None. Not supported for use with Application Load Balancer event sources.
        "environment_variables": {"your_key": "your_value"}, // A dictionary of environment variables that will be available to your deployed app. See also "remote_env" and "aws_environment_variables". Default {}.
        "events": [
            {   // Recurring events
                "function": "your_module.your_recurring_function", // The function to execute (Pattern: [._A-Za-z0-9]+).
                "expression": "rate(1 minute)" // When to execute it (in cron or rate format)
            },
            {   // AWS Reactive events
                "function": "your_module.your_reactive_function", // The function to execute (Pattern: [._A-Za-z0-9]+).
                "event_source": {
                    "arn":  "arn:aws:s3:::my-bucket", // The ARN of this event source
                    "events": [
                        "s3:ObjectCreated:*" // The specific event to execute in response to.
                    ]
                }
            }
        ],
        "endpoint_configuration": ["EDGE", "REGIONAL", "PRIVATE"],  // Specify APIGateway endpoint None (default) or list `EDGE`, `REGION`, `PRIVATE`
        "exception_handler": "your_module.report_exception", // function that will be invoked in case Zappa sees an unhandled exception raised from your code
        "exclude": ["file.gz", "tests"], // A list of filename patterns to exclude from the archive (see `fnmatch` module for patterns).
        "exclude_glob": ["*.gz", "*.rar", "tests/**/*"], // A list of glob patterns to exclude from the archive. To exclude boto3 and botocore (available in an older version on Lambda), add "boto3*" and "botocore*".
        "extends": "stage_name", // Duplicate and extend another stage's settings. For example, `dev-asia` could extend from `dev-common` with a different `s3_bucket` value.
        "extra_permissions": [{ // Attach any extra permissions to this policy. Default None
            "Effect": "Allow",
            "Action": ["rekognition:*"], // AWS Service ARN
            "Resource": "*"
        }],
        "iam_authorization": false, // optional, use IAM to require request signing. Default false. Note that enabling this will override the authorizer configuration.
        "include": ["your_special_library_to_load_at_handler_init"], // load special libraries into PYTHONPATH at handler init that certain modules cannot find on path
        "authorizer": {
            "function": "your_module.your_auth_function", // Local function to run for token validation. For more information about the function see below.
            "arn": "arn:aws:lambda:<region>:<account_id>:function:<function_name>", // Existing Lambda function to run for token validation.
            "result_ttl": 300, // Optional. Default 300. The time-to-live (TTL) period, in seconds, that specifies how long API Gateway caches authorizer results. Currently, the maximum TTL value is 3600 seconds.
            "token_header": "Authorization", // Optional. Default 'Authorization'. The name of a custom authorization header containing the token that clients submit as part of their requests.
            "validation_expression": "^Bearer \\w+$", // Optional. A validation expression for the incoming token, specify a regular expression.
        },
        "keep_warm": true, // Create CloudWatch events to keep the server warm. Default true. To remove, set to false and then `unschedule`.
        "keep_warm_expression": "rate(4 minutes)", // How often to execute the keep-warm, in cron and rate format. Default 4 minutes.
        "lambda_description": "Your Description", // However you want to describe your project for the AWS console. Default "Zappa Deployment".
        "lambda_handler": "your_custom_handler", // The name of Lambda handler. Default: handler.lambda_handler
        "layers": ["arn:aws:lambda:<region>:<account_id>:layer:<layer_name>:<layer_version>"], // optional lambda layers
        "lambda_concurrency": 10, // Sets the maximum number of simultaneous executions for a function, and reserves capacity for that concurrency level. Default is None.
        "lets_encrypt_key": "s3://your-bucket/account.key", // Let's Encrypt account key path. Can either be an S3 path or a local file path.
        "log_level": "DEBUG", // Set the Zappa log level. Can be one of CRITICAL, ERROR, WARNING, INFO and DEBUG. Default: DEBUG
        "manage_roles": true, // Have Zappa automatically create and define IAM execution roles and policies. Default true. If false, you must define your own IAM Role and role_name setting.
        "memory_size": 512, // Lambda function memory in MB. Default 512.
        "ephemeral_storage": { "Size": 512 }, // Lambda function ephemeral_storage size in MB, Default 512, Max 10240
        "num_retained_versions":null, // Indicates the number of old versions to retain for the lambda. If absent, keeps all the versions of the function.
        "payload_compression": true, // Whether or not to enable API gateway payload compression (default: true)
        "payload_minimum_compression_size": 0, // The threshold size (in bytes) below which payload compression will not be applied (default: 0)
        "prebuild_script": "your_module.your_function", // Function to execute before uploading code
        "profile_name": "your-profile-name", // AWS profile credentials to use. Default 'default'. Removing this setting will use the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables instead.
        "project_name": "MyProject", // The name of the project as it appears on AWS. Defaults to a slugified `pwd`.
        "remote_env": "s3://my-project-config-files/filename.json", // optional file in s3 bucket containing a flat json object which will be used to set custom environment variables.
        "role_name": "MyLambdaRole", // Name of Zappa execution role. Default <project_name>-<env>-ZappaExecutionRole. To use a different, pre-existing policy, you must also set manage_roles to false.
        "role_arn": "arn:aws:iam::12345:role/app-ZappaLambdaExecutionRole", // ARN of Zappa execution role. Default to None. To use a different, pre-existing policy, you must also set manage_roles to false. This overrides role_name. Use with temporary credentials via GetFederationToken.
        "route53_enabled": true, // Have Zappa update your Route53 Hosted Zones when certifying with a custom domain. Default true.
        "runtime": "python3.12", // Python runtime to use on Lambda. Can be one of: "python3.8", "python3.9", "python3.10", "python3.11", or "python3.12". Defaults to whatever the current Python being used is.
        "s3_bucket": "dev-bucket", // Zappa zip bucket,
        "slim_handler": false, // Useful if project >50M. Set true to just upload a small handler to Lambda and load actual project from S3 at runtime. Default false.
        "settings_file": "~/Projects/MyApp/settings/dev_settings.py", // Server side settings file location,
        "tags": { // Attach additional tags to AWS Resources
            "Key": "Value",  // Example Key and value
            "Key2": "Value2",
            },
        "timeout_seconds": 30, // Maximum lifespan for the Lambda function (default 30, max 900.)
        "touch": true, // GET the production URL upon initial deployment (default True)
        "touch_path": "/", // The endpoint path to GET when checking the initial deployment (default "/")
        "use_precompiled_packages": true, // If possible, use C-extension packages which have been pre-compiled for AWS Lambda. Default true.
        "vpc_config": { // Optional Virtual Private Cloud (VPC) configuration for Lambda function
            "SubnetIds": [ "subnet-12345678" ], // Note: not all availability zones support Lambda!
            "SecurityGroupIds": [ "sg-12345678" ]
        },
        "xray_tracing": false // Optional, enable AWS X-Ray tracing on your lambda function.
    }
}

YAML设置

如果您更喜欢YAML而不是JSON,也可以使用zappa_settings.yml,如下所示

---
dev:
  app_function: your_module.your_app
  s3_bucket: your-code-bucket
  events:
  - function: your_module.your_function
    event_source:
      arn: arn:aws:s3:::your-event-bucket
      events:
      - s3:ObjectCreated:*

您还可以随时使用-s参数提供自定义设置文件,例如

$ zappa deploy dev -s my-custom-settings.yml

类似地,您也可以提供zappa_settings.toml文件

[dev]
  app_function = "your_module.your_app"
  s3_bucket = "your-code-bucket"

高级用法

保持服务器活跃

Zappa会自动设置定期执行应用程序,以保持Lambda函数的活跃状态。可以通过keep_warm设置来禁用此功能。

服务静态文件/二进制上传

Zappa现在能够根据MIME类型检测到服务二进制文件。

然而,Zappa通常设计用于运行您的应用程序代码,而不是用于提供静态Web资产。如果您计划在Web应用程序中提供自定义静态资产(CSS/JavaScript/图像等),您可能需要使用AWS S3和AWS CloudFront的组合。

您的Web应用程序框架可能会自动处理这一点。对于Flask,有Flask-S3,对于Django,有Django-Storages

类似地,您可能希望设计您的应用程序,以便静态二进制上传直接发送到S3,然后触发在您的events设置中定义的事件响应!这是无服务器思维!

启用CORS

为您的Zappa应用程序启用CORS(跨源资源共享)的最简单方法是,在Zappa设置文件中将cors设置为true,并更新,这在AWS API网关控制台中相当于点击“启用CORS”按钮。默认情况下这是禁用的,但您可能希望为来自其他域等的API启用它。

您还可以直接在应用程序中处理CORS。您的Web框架可能有一个扩展来做这件事,比如django-cors-headersFlask-CORS。使用这些将使您的代码更具可移植性。

大型项目

AWS目前将Lambda压缩包大小限制为50MB。如果您的项目超过这个大小,请在zappa_settings.json中设置slim_handler: true。在这种情况下,您的大型应用程序包将被一个仅包含处理器的较小包所替代。然后,处理器文件将在运行时从S3拉取剩余的大型项目!大型项目的初始加载可能会增加启动开销,但对于一个热的Lambda函数来说,这种差异应该很小。请注意,这也会占用您应用程序函数的存储空间。请注意,AWS 支持 512 - 10240 MB范围内的自定义/tmp目录存储大小。如果您的项目大于默认的512 MB,请在zappa_settings.json中使用ephemeral_storage进行调整。

启用Bash自动补全

通过将以下内容添加到您的.bashrc中,可以启用Bash完成:

  eval "$(register-python-argcomplete zappa)"

register-python-argcomplete由argcomplete Python包提供。如果该包在虚拟环境中安装,则必须在其中运行此命令。或者,您可以执行

activate-global-python-argcomplete --dest=- > 文件

然后,可以将该文件的文件内容添加到例如~/.bashrc中。

在API网关上启用安全端点

API密钥

您可以使用api_key_required设置生成API密钥,用于您的API网关的所有路由。过程如下:

  1. 部署/重新部署(更新将不起作用),并记录已创建的密钥的id
  2. 转到AWS控制台 > Amazon API Gateway
    • 选择“API密钥”,找到密钥value(例如key_value
    • 选择“使用计划”,创建一个新的使用计划并将API密钥与Zappa为您创建的API相关联
  3. 发送一个请求,将密钥值作为名为x-api-key的标头传递以访问受限制的端点(例如,使用curl:curl --header "x-api-key: key_value")。请注意,如果没有x-api-key标头,您将收到403响应。

IAM策略

您可以将基于IAM(v4签名)的授权启用在API上,通过将iam_authorization设置设置为true。您的API将需要签名请求,并且可以通过IAM策略控制访问。未签名的请求将收到403响应,未授权访问API的请求者也将收到403响应。启用此功能将覆盖Authorizer配置(见下文)。

API网关Lambda授权器

如果您使用Zappa部署API端点,可以利用API Gateway Lambda Authorizers来实现基于令牌的认证——您需要做的就是提供一个创建所需输出的函数,Zappa会处理其余部分。函数的起点可以是AWS Labs蓝图示例

如果您想知道您会使用Authorizer做什么,以下是一些潜在用例:

  1. 调用OAuth提供者
  2. 直接解码JWT令牌
  3. 在自管理的数据库(例如DynamoDB)中查找

Zappa可以被配置为调用代码中的函数来进行授权,或者调用一些其他现有的Lambda函数(这允许您在多个Lambda之间共享授权器)。您可以通过在authorizer设置块中指定arnfunction_name值来控制行为。

例如,要获取Cognito身份,将以下内容添加到zappa_settings.yaml

  context_header_mappings:
    user_id: authorizer.user_id

现在可以这样在Flask中访问它

from flask import request

@route('/hello')
def hello_world:
   print(request.headers.get('user_id'))

Cognito用户池授权器

您还可以使用AWS Cognito User Pool Authorizer,通过添加

{
    "authorizer": {
        "type": "COGNITO_USER_POOLS",
        "provider_arns": [
            "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
        ]
    }
}

API网关资源策略

您还可以使用API Gateway资源策略。IP白名单的示例

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "1.2.3.4/32"
                    ]
                }
            }
        }
    ]
}

设置环境变量

本地环境变量

如果您想为部署阶段设置本地环境变量,您只需在zappa_settings.json中设置它们即可

{
    "dev": {
        ...
        "environment_variables": {
            "your_key": "your_value"
        }
    },
    ...
}

然后您可以在应用程序中使用以下方式访问这些变量

import os
your_value = os.environ.get('your_key')

如果你的项目需要了解部署的环境类型,你将能够随时获取 SERVERTYPE(AWS Lambda)、FRAMEWORK(Zappa)、PROJECT(你的项目名称)和 STAGEdevproduction 等)变量。

远程AWS环境变量

如果你想使用本地的 AWS Lambda 环境变量,可以使用 aws_environment_variables 配置设置。这些设置非常有用,因为你可以通过 AWS Lambda 控制台或 CLI 在运行时轻松地更改它们。它们还用于存储敏感凭据和利用环境变量的 KMS 加密。

在开发过程中,你可以通过以下方式将 Zappa 定义的变量添加到本地运行的 app 中(例如,对于 Django,针对 to manage.py)。

import json
import os

if os.environ.get('AWS_LAMBDA_FUNCTION_NAME') is None: # Ensures app is NOT running on Lambda
    json_data = open('zappa_settings.json')
    env_vars = json.load(json_data)['dev']['environment_variables']
    os.environ.update(env_vars)

远程环境变量

你在外部 Zappa(通过 AWS Lambda 控制台或 CLI)设置的任何环境变量,在执行 update 时将保持不变,除非它们也在 aws_environment_variables 中,在这种情况下,远程值将被设置文件中的值覆盖。如果你使用 KMS 加密的 AWS 环境变量,可以在 aws_kms_key_arn 设置中设置你的 KMS 密钥 ARN。确保在这种情况下设置的值已加密。

注意:如果你依赖这些以及 environment_variables,并且你有相同的键名,那么在 environment_variables 中的值将具有优先级,因为它们是在 lambda 处理程序中注入的。

通过S3文件远程环境变量

S3 远程环境变量是在 AWS 为 Lambda 引入本地环境变量(通过控制台和 CLI)之前添加到 Zappa 的。在采取此路线之前,请检查上述选项是否更适合您的用例。

如果你想要使用远程环境变量来配置应用程序(这对于敏感凭据之类的操作特别有用),你可以创建一个文件并将其放置在一个你的 Zappa 应用程序可以访问的 S3 桶中。为此,将 remote_env 键添加到 zappa_settings,指向包含平面 JSON 对象的文件,这样对象上的每个键值对都将设置为环境变量和值,每当一个新的 lambda 实例启动时。

例如,为了确保你的应用程序可以访问数据库凭据而无需将其存储在版本控制中,你可以在 S3 中添加一个包含连接字符串的文件,并使用 remote_env 配置设置将其加载到 lambda 环境中。

super-secret-config.json(上传到 my-config-bucket)

{
    "DB_CONNECTION_STRING": "super-secret:database"
}

zappa_settings.json

{
    "dev": {
        ...
        "remote_env": "s3://my-config-bucket/super-secret-config.json",
    },
    ...
}

现在在你的应用程序中你可以使用

import os
db_string = os.environ.get('DB_CONNECTION_STRING')

API网关上下文变量

如果你想将 API Gateway 上下文变量映射到 HTTP 头部,可以在 zappa_settings.json 中设置映射

{
    "dev": {
        ...
        "context_header_mappings": {
            "HTTP_header_name": "API_Gateway_context_variable"
        }
    },
    ...
}

例如,如果你想将 $context.identity.cognitoIdentityId 变量公开为 HTTP 头部 CognitoIdentityId,以及 $context.stage 为 APIStage,你会这样设置

{
    "dev": {
        ...
        "context_header_mappings": {
            "CognitoIdentityId": "identity.cognitoIdentityId",
            "APIStage": "stage"
        }
    },
    ...
}

捕获未处理的异常

默认情况下,如果代码中发生 未处理的 异常,Zappa 将仅将堆栈跟踪打印到 CloudWatch 日志中。如果你希望使用外部报告工具来记录这些异常,可以使用 exception_handler 配置选项。

zappa_settings.json

{
    "dev": {
        ...
        "exception_handler": "your_module.unhandled_exceptions",
    },
    ...
}

该函数必须接受三个参数:异常、事件和上下文

your_module.py

def unhandled_exceptions(e, event, context):
    send_to_raygun(e, event)  # gather data you need and send
    return True # Prevent invocation retry

你可能仍然需要在你的应用程序内部使用类似的异常处理器,这只是为了捕获在 Zappa/WSGI 层(通常基于事件的调用、配置错误、不良 Lambda 包和权限问题)中发生的异常。

默认情况下,AWS Lambda 将尝试在基于事件(非 API Gateway,例如 CloudWatch)的调用中抛出异常时重试。但是,你可以通过返回 True 来防止这种情况,如上例所示,这样 Zappa 将不会重新抛出未捕获的异常,从而防止 AWS Lambda 重试当前的调用。

使用自定义AWS IAM角色和策略

部署的自定义AWS IAM角色和策略

你可以通过定义 profile_name 设置来指定用于部署 Zappa 应用程序的 本地 配置文件,该设置将对应于你的 AWS 凭证文件中的一个配置文件。

执行的自定义AWS IAM角色和策略

由 Zappa 为执行 Lambda 创建的默认 IAM 策略非常宽松。它授权了对 CloudWatch、S3、Kinesis、SNS、SQS、DynamoDB 和 Route53 类型下所有资源的所有操作;对所有 Lambda 资源执行 lambda:InvokeFunction 操作;对所有 X-Ray 资源执行 Put 操作;以及所有网络接口操作对所有 EC2 资源。虽然这允许大多数 Lambda 在无需额外权限的情况下正确运行,但对于大多数持续集成管道或生产部署而言,这通常不是一组可接受的权限。相反,你可能需要手动管理你的 IAM 策略。

要手动定义 Lambda 执行角色的策略,你必须将 manage_roles 设置为 false,并在你的 Zappa 设置文件中定义 role_namerole_arn

{
    "dev": {
        ...
        "manage_roles": false, // Disable Zappa client managing roles.
        "role_name": "MyLambdaRole", // Name of your Zappa execution role. Optional, default: <project_name>-<env>-ZappaExecutionRole.
        "role_arn": "arn:aws:iam::12345:role/app-ZappaLambdaExecutionRole", // ARN of your Zappa execution role. Optional.
        ...
    },
    ...
}

关于 Zappa 部署所需的最小策略要求的持续讨论,请参见此处。预计很快将实施更健壮的解决方案来管理这些权限。

要向默认的 Zappa 执行策略添加权限,请使用 extra_permissions 设置。

{
    "dev": {
        ...
        "extra_permissions": [{ // Attach any extra permissions to this policy.
            "Effect": "Allow",
            "Action": ["rekognition:*"], // AWS Service ARN
            "Resource": "*"
        }]
    },
    ...
}

AWS X-Ray

你可以通过配置设置来启用函数的 AWS X-Ray 支持。

{
    "dev": {
        ...
        "xray_tracing": true
    },
    ...
}

这将启用 Lambda 函数,并允许你使用 X-Ray 仪表化你的代码。例如,对于 Flask:

from aws_xray_sdk.core import xray_recorder

app = Flask(__name__)

xray_recorder.configure(service='my_app_name')

@route('/hello')
@xray_recorder.capture('hello')
def hello_world:
    return 'Hello'

你可以使用捕获装饰器在函数周围创建子段,或者在一个函数中使用 xray_recorder.begin_subsegment('subsegment_name')xray_recorder.end_subsegment()。Python 官方 X-Ray 文档 提供了更多关于如何与你的代码一起使用此功能的详细信息。

请注意,你可以在你的代码中创建子段,但如果尝试创建段,将会抛出异常,因为段是由 Lambda 工作进程创建的。这也意味着,如果你使用 Flask,你不应该使用文档中建议的 XRayMiddleware

全球可用的无服务器架构

Global Zappa Slides

点击查看 ServerlessConf London 的幻灯片

init 过程中,你可以选择将你的应用程序“全局”部署。这将允许你同时将应用程序部署到所有可用的 AWS 区域,以提供一致的全球速度、增加冗余、数据隔离和法律合规性。你也可以选择仅将应用程序部署到“主要”位置,即名称中包含 -1 的 AWS 区域。

要了解更多关于这些功能的信息,请参见 ServerlessConf London 的这些幻灯片

提高AWS服务限制

默认情况下,AWS 为你的函数设置了 1000 个并发执行限制。如果你开始超过这些限制,你可能会看到像 ClientError: An error occurred (LimitExceededException) when calling the PutTargets.." 或类似的错误。

为了避免这种情况,你可以向亚马逊提交一个 服务工单,将你的限制提高到可能需要的数以万计的并发执行。这是亚马逊中相当常见的做法,旨在防止你意外创建极其昂贵的错误报告。因此,在提高服务限制之前,请确保你没有任何可能会意外创建数以万计的并行执行而不想付费的恶意脚本。

死信队列

如果你想利用 AWS Lambda 的死信队列功能,只需在 zappa_settings.json 中添加键 dead_letter_arn,其值为对应的 SNS 主题或 SQS 队列的完整 ARN。

你必须已经创建了相应的 SNS/SQS 主题/队列,并且 Lambda 函数执行角色必须已配置,以便对 DLQ 资源具有读取/发布/发送消息的访问权限。

唯一的打包ID

为了监控不同的部署,您的应用程序包根目录下的 package_info.json 文件中为每个包提供了唯一的UUID。您可以使用这些信息或该文件的哈希值进行跨不同部署跟踪错误、监控部署状态等,在Sentry和New Relic等服务上使用。该包将包含

{
  "build_platform": "darwin",
  "build_user": "frank",
  "build_time": "1509732511",
  "uuid": "9c2df9e6-30f4-4c0a-ac4d-4ecb51831a74"
}

应用负载均衡器事件源

Zappa可用于处理由应用程序负载均衡器(ALB)触发的事件。在某些情况下,这非常有用

  • 由于API网关在超时前有30秒的硬限制,您可以使用ALB来处理长时间运行请求。
  • API网关按请求计费;因此,对于高吞吐量服务,成本可能会过高。如果预计Lambda会有大量流量,ALB的定价模式在财务上更为合理。
  • ALB可以放置在VPC中,这可能比使用API网关的私有模型(使用AWS PrivateLink)对私有端点更有意义。

与API网关类似,Zappa可以自动为您配置ALB资源。您需要在您的 zappa_settings 中添加以下内容

"alb_enabled": true,
"alb_vpc_config": {
    "CertificateArn": "arn:aws:acm:us-east-1:[your-account-id]:certificate/[certificate-id]",
    "SubnetIds": [
        // Here, you'll want to provide a list of subnets for your ALB, eg. 'subnet-02a58266'
    ],
    "SecurityGroupIds": [
        // And here, a list of security group IDs, eg. 'sg-fbacb791'
    ]
}

有关如何将ALB用作Lambda事件源的更多信息,请参阅此处

重要提示:目前,Zappa将为每个负载均衡器部署一个Lambda,这意味着目前不支持与ALB配置一起使用base_path

端点配置

您可以将API网关配置为仅在VPC中访问。为此,请配置您的VPC以支持,然后将endpoint_configuration设置为PRIVATE,并在API网关上设置资源策略。关于这一点的一个说明;如果您正在使用私有端点,Zappa将无法在部署或更新时判断API是否返回成功状态码,因此您需要手动检查以确保您的设置正常工作。

有关端点配置选项的完整列表,请参阅API网关EndpointConfiguration文档

示例私有API网关配置

zappa_settings.json

{
    "dev": {
        ...
        "endpoint_configuration": ["PRIVATE"],
        "apigateway_policy": "apigateway_resource_policy.json",
        ...
    },
    ...
}

apigateway_resource_policy.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*",
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpc": "{{vpcID}}" // UPDATE ME
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "execute-api:/*"
        }
    ]
}

冷启动(实验性)

Lambda可能在冷启动初始化期间提供比配置时更多的资源。将INSTANTIATE_LAMBDA_HANDLER_ON_IMPORT=True设置为在导入时实例化Lambda处理器。这是一个实验性功能 - 如果启动时间至关重要,请考虑使用预留并发。

Zappa指南

媒体中的Zappa

使用Zappa的网站

您正在使用 Zappa 吗?告诉我们,我们将在这里列出您的网站!

相关项目

  • Mackenzie - AWS Lambda 感染工具包
  • NoDB - 基于 S3 的简单、无服务器、Pythonic 对象存储。
  • zappa-cms - 专为忙碌黑客设计的微型无服务器 CMS。仍在开发中。
  • zappa-django-utils - 帮助 Django 部署的实用命令。
  • flask-ask - 用于构建亚马逊 Alexa 应用程序的框架。使用 Zappa 进行部署。
  • zappa-file-widget - Django 插件,用于支持在 Zappa 上上传二进制文件。
  • zops - 使用 Zappa 的团队和持续集成工具。
  • cookiecutter-mobile-backend - 一个带有 Zappa 和 S3 上传支持的 cookiecutter Django 项目。
  • zappa-examples - Flask、Django、图片上传等!
  • zappa-hug-example - 使用 Zappa 的 Hug 应用程序示例。
  • Zappa Docker Image - 一个基于 Lambda Docker 的本地运行 Zappa 的 Docker 镜像。
  • zappa-dashing - 使用 Zappa 和 CloudWatch 监控您的 AWS 环境(健康/指标)。
  • s3env - 通过 CLI 操作远程 Zappa 环境变量键/值 JSON 文件。
  • zappa_resize_image_on_fly - 使用 Flask、Zappa、Pillow 和 OpenCV-python 在线调整图像大小。
  • zappaffmpeg - 在 Lambda 中运行 ffmpeg 的无服务器转换。
  • gdrive-lambda - 将 JSON 数据传递到 CSV 文件,供组织内部使用 Gdrive 的用户。
  • travis-build-repeat - 重复 TravisCI 构建,以避免测试结果过时。
  • wunderskill-alexa-skill - 用于添加到 Wunderlist 的 Alexa 技能。
  • xrayvision - 使用 AWS X-Ray 的实用工具和包装器。
  • terraform-aws-zappa - 用于创建 VPC、RDS 实例、ElastiCache Redis 和 CloudFront 分发的 Terraform 模块。
  • zappa-sentry - 与 Sentry 集成的 Zappa。
  • IOpipe - 监控、分析 Zappa 应用程序。

黑客技巧

Zappa 远远超出了 Lambda 和 API Gateway 的预期功能。因此,这里有一些技巧可以让它工作,包括但不限于...

  • 使用VTL将请求体、头部、方法、参数和查询字符串映射到JSON,然后将它们转换为有效的WSGI。
  • 将响应代码附加到响应体中,对整个内容进行Base64编码,使用该编码作为正则表达式来路由响应代码,在VTL中解码体,并将响应体映射到该代码。
  • 将多个cookie打包和Base58编码成一个单一的cookie,因为我们只能映射一种类型。
  • 强制"Set-Cookie"的大小写变化,以便同时返回多个头部。
  • 将设置cookie的301/302响应转换为带有HTML重定向的200响应,因为我们无法在重定向上设置头部。

贡献

非常欢迎贡献!

在提交补丁之前,请先提交讨论的票据。拉取请求应针对master,如果合并,则应使Zappa处于“可发货”状态。

如果您添加了大量新代码,请确保在您的PR中包含一个功能性的测试。对于AWS调用,我们使用placebo库,您可以在他们的README中了解如何使用。打开拉取请求后,测试套件将由Travis CI运行。

请将包含与您的更改相关的讨论的GitHub问题或拉取请求URL作为注释添加到代码中(示例)。这对项目的可维护性有很大帮助,因为它使我们能够追踪用例并解释决策。同样,请确保您满足拉取请求模板中列出的所有要求。

请随时处理任何开放的票据,特别是任何带有“help-wanted”标签的票据。如果您遇到困难或想进一步讨论问题,请加入我们的Slack频道,在那里您会发现一群聪明且有趣的人正致力于解决难题。Zappa Slack Auto Invite

Zappa不打算遵循PEP8,请将您的提交隔离,以便更改功能与您的linter所做的更改。

使用本地仓库

要使用git HEAD,您可能无法使用pip install -e 。相反,您应该将仓库克隆到您的机器上,然后在您的本地项目中运行pip install /path/to/zappa/repoln -s /path/to/zappa/repo/zappa zappa

项目详情


发布历史 发布通知 | RSS源

下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

zappa-0.59.0.tar.gz (204.5 kB 查看散列值)

上传时间 源代码

构建分发

zappa-0.59.0-py3-none-any.whl (118.5 kB 查看散列值)

上传时间 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面