Serverless教程

Serverless DynamoDB

到目前为止,我们已经学习了几个与无服务器 lambda 部署相关的概念。现在是看一些例子的时候了。在本章中,我们将查看 Serverless 官方提供的示例之一。顾名思义,我们将创建一个 REST API。正如您所猜到的,我们所有的 lambda 函数都将由 API 网关触发。我们的 lambda 函数将与 dynamoDB 表进行交互,该表本质上是一个待办事项列表,用户将能够使用端点执行多项操作,例如创建新项目、获取现有项目、删除项目等。在部署后公开。如果您不熟悉 REST API,那么您可以阅读有关它们的更多信息 此处。

代码演练

代码可以在 GitHub 上找到-https://github.com/serverless/examples/tree/master/aws-python-rest-api-with-dynamodb
我们将看一下项目结构,讨论一些我们目前还没有看到的新概念,然后执行 serverless.yml 文件的演练。所有函数处理程序的演练将是多余的。因此,我们将走过呃只有一个函数处理程序。您可以将理解其他功能作为练习。

项目结构

现在,如果您查看项目结构,则 lambda 函数处理程序都位于 todos 文件夹中的单独 .py 文件中。 serverless.yml 文件在每个函数处理程序的路径中指定了 todos 文件夹。没有外部依赖项,因此没有 requirements.txt 文件。

新概念

现在,您可能第一次看到几个术语。让我们快速扫描这些-
dynamoDB-这是 AWS 提供的 NoSQL(不仅是 SQL)数据库。虽然不完全准确,但从广义上讲,NoSQL 之于 SQL,就像 Word 之于 Excel。您可以在此处阅读有关 NoSQL 的更多信息。 NoSQL 数据库有 4 种类型-文档数据库、键值数据库、宽列存储和图形数据库。 dynamoDB 是一个键值数据库,这意味着您可以不断地将键值对插入到数据库中。这类似于redis缓存。您可以通过引用其键来检索该值。 boto3-这是适用于 Python 的 AWS 开发工具包。如果您需要在 lambda 函数中配置、管理、调用或创建 AWS 的任何服务(EC2、dynamoDB、S3 等),您需要 boto3 SDK。您可以阅读更多关于 boto3 此处。
除此之外,在演练 serverless.yml 和处理程序函数的过程中,我们还会遇到一些概念。我们将在那里讨论它们。

serverless.yml 演练

serverless.yml 文件以服务的定义开始。
service: serverless-rest-api-with-dynamodb
接下来是通过以下行声明框架版本范围-
frameworkVersion: ">=1.1.0 <=2.1.1"
这就像一张支票。如果您的无服务器版本不在此范围内,则会引发错误。当您共享代码并希望使用此 serverless.yml 文件的每个人都使用相同的无服务器版本范围以避免出现问题时,这会有所帮助。
接下来,在提供程序中,我们会看到两个迄今为止尚未遇到的额外字段- environmentiamRoleStatements
provider:
   name: aws
   runtime: python3.8
   environment:
      DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
   iamRoleStatements:
     -Effect: Allow
         Action:
        -dynamodb:Query
        -dynamodb:Scan
        -dynamodb:GetItem
        -dynamodb:PutItem
        -dynamodb:UpdateItem
        -dynamodb:DeleteItem
         Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:
         *:table/${self:provider.environment.DYNAMODB_TABLE}"
Environment,如您所料,用于定义环境变量。此 serverless.yml 文件中定义的所有函数都可以获取这些环境变量。我们将在下面的函数处理程序演练中看到一个示例。在这里,我们将 dynamoDB 表名定义为环境变量。
$ 符号表示一个变量。 self 关键字指的是 serverless.yml 文件本身,而 opt 指的是我们可以在 sls deploy 期间提供的选项。因此,表名将是服务名称,后跟连字符,后跟文件找到的第一个阶段参数:无服务器部署期间可从选项中获得的一个,或提供者阶段,即 dev 由default.因此,在这种情况下,如果您在无服务器部署期间不提供任何选项,则 dynamoDB 表名称将是 serverless-rest-api-with-dynamodb-dev。您可以在此处阅读有关无服务器变量的更多信息。
iamRoleStatements 定义提供给函数的权限。在这种情况下,我们 允许函数对 dynamoDB 表执行以下操作- QueryScanGetItemPutItemUpdateItemDeleteItem。资源名称指定允许执行这些操作的确切表。如果您输入 "*" 代替资源名称,则您将允许对所有表执行这些操作。但是,在这里,我们希望只允许对一个表进行这些操作,因此,使用标准 arn 格式在资源名称中提供了该表的 arn(Amazon 资源名称)。这里再次使用选项区域(在无服务器部署期间指定)或提供程序中提到的区域(默认为 us-east-1)中的第一个。
在函数部分,函数是按照标准格式定义的。请注意,get、update、delete 都具有相同的路径,其中 id 作为路径参数。但是,每个人的方法都不同。
functions:
   create:
      handler: todos/create.create
      events:
        -http:
            path: todos
            method: post
            cors: true
   list:
      handler: todos/list.list
      events:
        -http:
            path: todos
            method: get
            cors: true
   get:
      handler: todos/get.get
      events:
        -http:
            path: todos/{id}
            method: get
            cors: true
   update:
      handler: todos/update.update
      events:
        -http:
            path: todos/{id}
            method: put
            cors: true
   delete:
      handler: todos/delete.delete
      events:
        -http:
            path: todos/{id}
            method: delete
            cors: true
后来,我们遇到了另一个我们以前没有见过的块, 资源块。此块基本上可以帮助您在 CloudFormation 模板中指定需要创建的资源,以使函数正常工作。在这种情况下,我们需要为函数创建一个 dynamoDB 表。到目前为止,我们已经指定了表的名称,甚至引用了它的 ARN。但是我们还没有创建表。在 resources 块中指定表的特征将为我们创建该表。
resources:
   Resources:
      TodosDynamoDbTable:
         Type: 'AWS::DynamoDB::Table'
         DeletionPolicy: Retain
         Properties:
         AttributeDefinitions:
           -
               AttributeName: id
               AttributeType: S
         KeySchema:
           -
               AttributeName: id
               KeyType: HASH
         ProvisionedThroughput:
            ReadCapacityUnits: 1
            WriteCapacityUnits: 1
            TableName: ${self:provider.environment.DYNAMODB_TABLE}
这里定义了很多配置,其中大部分是针对 dynamoDB 的。简而言之,我们要求无服务器创建一个"TodosDynamoDbTable",或键入"DynamoDB Table",其中 TableName(在底部提到)等于在 provider 的环境变量中定义的那个。我们将其删除策略设置为"保留",这意味着如果删除堆栈,则保留资源。请参阅此处。我们说该表将有一个名为 id 的属性,它的类型将为 String。我们还指定 id 属性将是 HASH 键或分区键。您可以在 dynamoDB 表中阅读有关 KeySchemas 的更多信息 此处。最后,我们指定表的读容量和写容量。
就是这样!我们的 serverless.yml 文件现已准备就绪。现在,由于所有函数处理程序或多或少相似,我们将仅介绍一个处理程序,即 create 函数的处理程序。

create 函数处理程序的演练

我们有几个导入语句
import json
import logging
import os
import time
import uuid
接下来,我们导入 boto3,如上所述,它是适用于 Python 的 AWS 开发工具包。我们需要 boto3 从 lambda 函数内部与 dynamoDB 交互。
import boto3
dynamodb = boto3.resource('dynamodb')
接下来,在实际的函数处理程序中,我们首先检查"事件"有效负载的内容(create API 使用 post 方法)。如果它的正文不包含"文本"键,我们还没有收到要添加到待办事项列表的有效项目。因此,我们提出了一个异常。
def create(event, context):
   data = json.loads(event['body'])
   if 'text' not in data:
      logging.error("Validation Failed")
      raise Exception("Couldn't create the todo item.")
考虑到我们按预期获得了 'text' 键,我们准备将其添加到 dynamoDB 表中。我们获取当前时间戳,并连接到 dynamoDB 表。注意 serverless.yml 中定义的环境变量是如何获取的(使用 os.environ)
timestamp = str(time.time())
table = dynamodb.Table(os.environ['DYNAMODB_TABLE'])
接下来,我们创建要添加到表中的项目,通过使用 uuid 包生成随机 uuid,使用接收到的数据作为文本,将 createdAt 和 updatedAt 设置为当前时间戳,并将字段 'checked' 设置为错误的。 'checked' 是另一个可以使用更新操作更新的字段,除了文本之外。
item = {
   'id': str(uuid.uuid1()),
   'text': data['text'],
   'checked': false,
   'createdAt': timestamp,
   'updatedAt': timestamp,
}
最后,我们将项目添加到 dynamoDB 表并将创建的项目返回给用户。
# write the todo to the database
table.put_item(Item=item)
# create a response
response = {
   "statusCode": 200,
   "body": json.dumps(item)
}
return response
通过本演练,我认为其他函数处理程序将不言自明。在某些函数中,您可能会看到此语句- "body"-json.dumps(result['Item'], cls=decimalencoder.DecimalEncoder)。这是用于 json.dumps 中的 bug 的解决方法。 json.dumps 默认无法处理十进制数,因此 decimalencoder.py 文件以包含处理此问题的 DecimalEncoder 类。
祝贺您了解您使用无服务器创建的第一个综合项目。该项目的创建者还在 README 文件。看一看。前往下一章查看另一个示例。
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4