

# 创建用于执行定期数据库维护的应用程序
<a name="scheduled-task-app"></a>

您可以使用 AWS Lambda 来替换自动系统备份、文件转换和维护任务等计划进程。在此示例中，您将创建无服务器应用程序，该应用程序通过删除旧条目对 DynamoDB 表执行定期维护。该应用程序按照 cron 计划，使用 EventBridge 调度器调用 Lambda 函数。调用时，该函数会在表中查询早于一年的项目，然后将其删除。该函数会将每个已删除的项目记录在 CloudWatch Logs 中。

要实现此示例，请先创建 DynamoDB 表，并在其中填充部分测试数据以供您进行函数查询。然后，创建具有 EventBridge 调度器触发器和 IAM 执行角色的 Python Lambda 函数，该执行角色可授予函数读取和删除表中项目的权限。

![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/ExampleApps/cron_app.png)


**提示**  
若您为 Lambda 全新用户，建议先阅读教程（[创建第一个 Lambda 函数](getting-started.md)），再创建此示例应用程序。

您可以使用 AWS 管理控制台 创建并配置资源来手动部署应用程序。您也可以使用 AWS Serverless Application Model（AWS SAM）来部署应用程序。AWS SAM 是基础设施即代码（IaC）工具。若借助 IaC，则不必手动创建资源，只需在代码中定义资源，就能自动部署这些资源。

若想在部署此示例应用程序之前，了解有关将 Lambda 与 IaC 结合使用的更多信息，请参阅[将 Lambda 与基础设施即代码（IaC）结合使用](foundation-iac.md)。

## 先决条件
<a name="scheduled-task-app-prereqs"></a>

在创建示例应用程序之前，确保已安装好所需的命令行工具和程序。
+ **Python**

  为了填充您为测试应用程序而创建的 DynamoDB 表，此示例使用 Python 脚本和 CSV 文件将数据写入表中。确保在计算机上已安装 Python 3.8 或更高版本。
+ **AWS SAM CLI**

  若要使用 AWS SAM 创建 DynamoDB 表和部署示例应用程序，则需要同时安装 AWS SAM CLI。请按照《AWS SAM User Guide》**中的 [installation instructions](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) 操作。
+ **AWS CLI**

  要使用提供的 Python 脚本填充测试表，您需要安装并配置 AWS CLI。由于脚本使用 适用于 Python (Boto3) 的 AWS SDK，它需要访问您的 AWS Identity and Access Management（IAM）证书。您还需要安装 AWS CLI 才能使用 AWS SAM 部署资源。要安装 CLI，请按照《AWS Command Line Interface User Guide》**中的 [installation instructions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 操作。
+ **Docker**

  要使用 AWS SAM 部署应用程序，还必须在生成计算机上安装 Docker。按照 Docker 文档网站上的 [Install Docker Engine](https://docs.docker.com/engine/install/) 中的说明操作。

## 下载示例应用程序文件
<a name="scheduled-task-app-download"></a>

要创建示例数据库和用于定期维护的应用程序，请在项目目录中创建以下文件：

**数据库文件示例**
+ `template.yaml`：可用于创建 DynamoDB 表的 AWS SAM 模板
+ `sample_data.csv`：包含要加载到表中的示例数据的 CSV 文件
+ `load_sample_data.py`：用于将 CSV 文件中的数据写入表中的 Python 脚本

**用于定期维护的应用程序文件**
+ `lambda_function.py`：执行数据库维护的 Lambda 函数的 Python 函数代码
+ `requirements.txt` – 定义 Python 函数代码所需的依赖项的清单文件
+ `template.yaml` – 可用于部署应用程序的 AWS SAM 模板

**测试文件**
+ `test_app.py`：Python 脚本，用于扫描表并通过输出所有超过一年的记录来确认函数是否成功运行

展开以下各部分，查看代码，继而详细了解每个文件在创建和测试应用程序中所起的作用。要在本地计算机上创建文件，请复制并粘贴以下代码。

### AWS SAM 模板（DynamoDB 表示例）
<a name="scheduled-task-app-table-yaml"></a>

将以下代码复制并粘贴到名为 `template.yaml` 的文件。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for DynamoDB Table with Order_number as Partition Key and Date as Sort Key

Resources:
  MyDynamoDBTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Properties:
      TableName: MyOrderTable
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: Order_number
          AttributeType: S
        - AttributeName: Date
          AttributeType: S
      KeySchema:
        - AttributeName: Order_number
          KeyType: HASH
        - AttributeName: Date
          KeyType: RANGE
      SSESpecification:
        SSEEnabled: true
      GlobalSecondaryIndexes:
        - IndexName: Date-index
          KeySchema:
            - AttributeName: Date
              KeyType: HASH
          Projection:
            ProjectionType: ALL
      PointInTimeRecoverySpecification:
        PointInTimeRecoveryEnabled: true

Outputs:
  TableName:
    Description: DynamoDB Table Name
    Value: !Ref MyDynamoDBTable
  TableArn:
    Description: DynamoDB Table ARN
    Value: !GetAtt MyDynamoDBTable.Arn
```

**注意**  
AWS SAM 模板使用的标准命名约定为 `template.yaml`。在此示例中，您有两个模板文件：其中一个用于创建示例数据库，另一个用于创建应用程序本身。将它们保存在项目文件夹中的单独子目录中。

此 AWS SAM 模板定义了您为测试应用程序而创建的 DynamoDB 表资源。该表使用的主键为 `Order_number`，排序键为 `Date`。为了让 Lambda 函数直接按日期查找项目，我们还定义了名为 `Date-index` 的[全局二级索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html)。

要了解有关使用该 `AWS::DynamoDB::Table` 资源创建和配置 DynamoDB 表的更多信息，请参阅《AWS CloudFormation User Guide》中的 [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)。**

### 数据库数据文件示例
<a name="scheduled-task-app-csv-file"></a>

将以下代码复制并粘贴到名为 `sample_data.csv` 的文件。

```
Date,Order_number,CustomerName,ProductID,Quantity,TotalAmount
2023-09-01,ORD001,Alejandro Rosalez,PROD123,2,199.98
2023-09-01,ORD002,Akua Mansa,PROD456,1,49.99
2023-09-02,ORD003,Ana Carolina Silva,PROD789,3,149.97
2023-09-03,ORD004,Arnav Desai,PROD123,1,99.99
2023-10-01,ORD005,Carlos Salazar,PROD456,2,99.98
2023-10-02,ORD006,Diego Ramirez,PROD789,1,49.99
2023-10-03,ORD007,Efua Owusu,PROD123,4,399.96
2023-10-04,ORD008,John Stiles,PROD456,2,99.98
2023-10-05,ORD009,Jorge Souza,PROD789,3,149.97
2023-10-06,ORD010,Kwaku Mensah,PROD123,1,99.99
2023-11-01,ORD011,Li Juan,PROD456,5,249.95
2023-11-02,ORD012,Marcia Oliveria,PROD789,2,99.98
2023-11-03,ORD013,Maria Garcia,PROD123,3,299.97
2023-11-04,ORD014,Martha Rivera,PROD456,1,49.99
2023-11-05,ORD015,Mary Major,PROD789,4,199.96
2023-12-01,ORD016,Mateo Jackson,PROD123,2,199.99
2023-12-02,ORD017,Nikki Wolf,PROD456,3,149.97
2023-12-03,ORD018,Pat Candella,PROD789,1,49.99
2023-12-04,ORD019,Paulo Santos,PROD123,5,499.95
2023-12-05,ORD020,Richard Roe,PROD456,2,99.98
2024-01-01,ORD021,Saanvi Sarkar,PROD789,3,149.97
2024-01-02,ORD022,Shirley Rodriguez,PROD123,1,99.99
2024-01-03,ORD023,Sofia Martinez,PROD456,4,199.96
2024-01-04,ORD024,Terry Whitlock,PROD789,2,99.98
2024-01-05,ORD025,Wang Xiulan,PROD123,3,299.97
```

此文件包含部分测试数据示例，供以标准逗号分隔值（CSV）格式填充 DynamoDB 表。

### 用于加载示例数据的 Python 脚本
<a name="scheduled-task-app-load-script"></a>

将以下代码复制并粘贴到名为 `load_sample_data.py` 的文件。

```
import boto3
import csv
from decimal import Decimal

# Initialize the DynamoDB client
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('MyOrderTable') 
print("DDB client initialized.")

def load_data_from_csv(filename):
    with open(filename, 'r') as file:
        csv_reader = csv.DictReader(file)
        for row in csv_reader:
            item = {
                'Order_number': row['Order_number'],
                'Date': row['Date'],
                'CustomerName': row['CustomerName'],
                'ProductID': row['ProductID'],
                'Quantity': int(row['Quantity']),
                'TotalAmount': Decimal(str(row['TotalAmount']))
            }
            table.put_item(Item=item)
            print(f"Added item: {item['Order_number']} - {item['Date']}")

if __name__ == "__main__":
    load_data_from_csv('sample_data.csv')
    print("Data loading completed.")
```

此 Python 脚本首先使用 适用于 Python (Boto3) 的 AWS SDK 创建与 DynamoDB 表的连接。然后，它将迭代示例数据 CSV 文件中的各行，从该行创建项目，然后使用 boto3 SDK 将该项目写入 DynamoDB 表。

### Python 函数代码
<a name="scheduled-task-app-function-code"></a>

将以下代码复制并粘贴到名为 `lambda_function.py` 的文件。

```
import boto3
from datetime import datetime, timedelta
from boto3.dynamodb.conditions import Key, Attr
import logging

logger = logging.getLogger()
logger.setLevel("INFO")

def lambda_handler(event, context):
    # Initialize the DynamoDB client
    dynamodb = boto3.resource('dynamodb')
    
    # Specify the table name
    table_name = 'MyOrderTable'
    table = dynamodb.Table(table_name)
    
    # Get today's date
    today = datetime.now()
    
    # Calculate the date one year ago
    one_year_ago = (today - timedelta(days=365)).strftime('%Y-%m-%d')
    
    # Scan the table using a global secondary index
    response = table.scan(
        IndexName='Date-index',
        FilterExpression='#date < :one_year_ago',
        ExpressionAttributeNames={
            '#date': 'Date'
        },
        ExpressionAttributeValues={
            ':one_year_ago': one_year_ago
        }
    )
    
     # Delete old items
    with table.batch_writer() as batch:
        for item in response['Items']:
            Order_number = item['Order_number']
            batch.delete_item(
                Key={
                    'Order_number': Order_number,
                    'Date': item['Date']
                }
            )
            logger.info(f'deleted order number {Order_number}')
    
    # Check if there are more items to scan
    while 'LastEvaluatedKey' in response:
        response = table.scan(
            IndexName='DateIndex',
            FilterExpression='#date < :one_year_ago',
            ExpressionAttributeNames={
                '#date': 'Date'
            },
            ExpressionAttributeValues={
                ':one_year_ago': one_year_ago
            },
            ExclusiveStartKey=response['LastEvaluatedKey']
        )
        
        # Delete old items
        with table.batch_writer() as batch:
            for item in response['Items']:
                batch.delete_item(
                    Key={
                        'Order_number': item['Order_number'],
                        'Date': item['Date']
                    }
                )
    
    return {
        'statusCode': 200,
        'body': 'Cleanup completed successfully'
    }
```

Python 函数代码包含 Lambda 在调用函数时运行的[处理程序函数](python-handler.md) (`lambda_handler`)。

当 EventBridge 调度器调用函数时，它会使用 适用于 Python (Boto3) 的 AWS SDK 创建与要执行计划维护任务的 DynamoDB 表的连接。然后，它使用 Python `datetime` 库计算一年前的日期，然后扫描表中是否有早于该日期的项目，并将其删除。

请注意，来自 DynamoDB 查询和扫描操作的响应大小限制为最大 1 MB。如果响应大于 1 MB，则 DynamoDB 会对数据进行分页，并在响应中返回 `LastEvaluatedKey` 元素。为确保我们的函数将处理表中的所有记录，我们检查此密钥是否存在，并从上次评估的位置继续执行表扫描，直到扫描完整个表。

### `requirements.txt` 清单文件
<a name="scheduled-task-app-dependencies"></a>

将以下代码复制并粘贴到名为 `requirements.txt` 的文件。

```
boto3
```

在本示例中，函数代码只有一个不属于标准 Python 库的依赖项：即适用于 Python 的 SDK（Boto3），供函数用于扫描和删除来自 DynamoDB 表的项目。

**注意**  
适用于 Python 的 SDK（Boto3）的一个版本作为 Lambda 运行时的一部分包含在内，因此无需将 Boto3 添加到函数的部署包中，代码即可运行。不过，为了完全控制函数依赖项并避免可能出现的版本不一致问题，Python 的最佳实践是将所有函数依赖项包含在函数的部署包中。请参阅 [Python 中的运行时系统依赖项](python-package.md#python-package-dependencies)，了解更多信息。

### AWS SAM 模板（用于定期维护的应用程序）
<a name="scheduled-task-app-table-yaml"></a>

将以下代码复制并粘贴到名为 `template.yaml` 的文件。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda function and EventBridge Scheduler rule

Resources:
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: ScheduledDBMaintenance
      CodeUri: ./
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      Events:
        ScheduleEvent:
          Type: ScheduleV2
          Properties:
            ScheduleExpression: cron(0 3 1 * ? *)
            Description: Run on the first day of every month at 03:00 AM
      Policies:
        - CloudWatchLogsFullAccess
        - Statement:
            - Effect: Allow
              Action:
                - dynamodb:Scan
                - dynamodb:BatchWriteItem
              Resource: !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/MyOrderTable'

  LambdaLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${MyLambdaFunction}
      RetentionInDays: 30

Outputs:
  LambdaFunctionName:
    Description: Lambda Function Name
    Value: !Ref MyLambdaFunction
  LambdaFunctionArn:
    Description: Lambda Function ARN
    Value: !GetAtt MyLambdaFunction.Arn
```

**注意**  
AWS SAM 模板使用的标准命名约定为 `template.yaml`。在此示例中，您有两个模板文件：其中一个用于创建示例数据库，另一个用于创建应用程序本身。将它们保存在项目文件夹中的单独子目录中。

此 AWS SAM 模板用于定义应用程序的资源。我们使用 `AWS::Serverless::Function` 资源定义 Lambda 函数。用于调用 Lambda 函数的 EventBridge 调度器计划和触发的创建都使用了此资源的 `Events` 属性，类型为 `ScheduleV2`。要了解有关在 AWS SAM 模板中定义 EventBridge 调度器的更多信息，请参阅《AWS Serverless Application Model Developer Guide》**中的 [ScheduleV2](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-schedulev2.html)。

除了 Lambda 函数和 EventBridge 调度器计划外，我们还为函数定义了 CloudWatch 日志组，用于向其发送已删除项目的记录。

### 测试脚本
<a name="scheduled-task-app-test-script"></a>

将以下代码复制并粘贴到名为 `test_app.py` 的文件。

```
import boto3
from datetime import datetime, timedelta
import json

# Initialize the DynamoDB client
dynamodb = boto3.resource('dynamodb')

# Specify your table name
table_name = 'YourTableName'
table = dynamodb.Table(table_name)

# Get the current date
current_date = datetime.now()

# Calculate the date one year ago
one_year_ago = current_date - timedelta(days=365)

# Convert the date to string format (assuming the date in DynamoDB is stored as a string)
one_year_ago_str = one_year_ago.strftime('%Y-%m-%d')

# Scan the table
response = table.scan(
    FilterExpression='#date < :one_year_ago',
    ExpressionAttributeNames={
        '#date': 'Date'
    },
    ExpressionAttributeValues={
        ':one_year_ago': one_year_ago_str
    }
)

# Process the results
old_records = response['Items']

# Continue scanning if we have more items (pagination)
while 'LastEvaluatedKey' in response:
    response = table.scan(
        FilterExpression='#date < :one_year_ago',
        ExpressionAttributeNames={
            '#date': 'Date'
        },
        ExpressionAttributeValues={
            ':one_year_ago': one_year_ago_str
        },
        ExclusiveStartKey=response['LastEvaluatedKey']
    )
    old_records.extend(response['Items'])

for record in old_records:
    print(json.dumps(record))

# The total number of old records should be zero.
print(f"Total number of old records: {len(old_records)}")
```

此测试脚本使用 适用于 Python (Boto3) 的 AWS SDK 创建与 DynamoDB 表的连接，并扫描超过一年的项目。为确认 Lambda 函数是否成功运行，在测试结束时，该函数会打印表中仍存在超过一年的记录数。如果 Lambda 函数成功运行，则表中的旧记录数应为零。

## 创建和填充示例 DynamoDB 表
<a name="scheduled-task-app-create-table"></a>

要测试用于定期维护的应用程序，您需要先创建 DynamoDB 表，然后在其中填充部分示例数据。您可以使用 AWS 管理控制台 手动创建表，也可以使用 AWS SAM 创建表。我们建议您使用 AWS SAM，通过使用 AWS CLI 命令快速创建和配置表。

------
#### [ Console ]

**创建 DynamoDB 表**

1. 打开 DynamoDB 控制台中 [Tables page](https://console.aws.amazon.com/dynamodbv2/home#tables)（表页面）。

1. 选择**创建表**。

1. 通过执行以下操作创建表：

   1. 在**表详细信息**下，在**表名称**中输入 **MyOrderTable**。

   1. 对于**分区键**，输入 **Order\$1number**，并将数据类型设置为**字符串**。

   1. 对于**排序键**，输入 **Date**，并将类型设置为**字符串**。

   1. 将**表设置**设置为**默认设置**，然后选择**创建表**。

1. 当表创建完成且其**状态**显示为**有效**时，请执行以下操作来创建全局二级索引（GSI）。应用程序将使用此 GSI 直接按日期搜索项目，以确定要删除的内容。

   1. 从表列表中选择 **MyOrderTable**。

   1. 选择**索引**选项卡。

   1. 在**全局二级索引**下，选择**创建索引**。

   1. 在**索引详细信息**下，对于**分区键**，输入 **Date**，并将**数据类型**设置为**字符串**。

   1. 对于 **Index name (索引名称)**，输入 **Date-index**。

   1. 将所有其他参数设置为其默认值，滚动到页面底部，然后选择**创建索引**。

------
#### [ AWS SAM ]

**创建 DynamoDB 表**

1. 导航到您为 DynamoDB 表保存 `template.yaml` 文件的文件夹。请注意，此示例使用两个 `template.yaml` 文件。确保将它们保存在单独的子文件夹中，并且您位于包含模板的正确文件夹中，以便创建 DynamoDB 表。

1. 运行如下命令。

   ```
   sam build
   ```

   此命令会收集您想要部署资源的构建构件，并将其以适当的格式放置在适当的位置进行部署。

1. 要创建 `template.yaml` 文件中指定的 DynamoDB 资源，请运行以下命令。

   ```
   sam deploy --guided
   ```

   使用 `--guided` 标志意味着 AWS SAM 将向您显示提示，以指导您完成部署过程。对于此部署，输入 **cron-app-test-db** 的 `Stack name`，然后使用 Enter 接受所有其他选项的默认值。

   当 AWS SAM 创建完 DynamoDB 资源后，您将看到以下消息。

   ```
   Successfully created/updated stack - cron-app-test-db in us-west-2
   ```

1. 此外，您还可以通过打开 DynamoDB 控制台的[表](https://console.aws.amazon.com/dynamodbv2/home#tables)页面来确认 DynamoDB 表已创建。您应该会看到名为 `MyOrderTable` 的表。

------

创建表后，接下来要添加部分示例数据来测试应用程序。您之前下载的 CSV 文件 (`sample_data.csv`) 包含许多示例条目，包括订单号、日期以及客户和订单信息。使用提供的 python 脚本 (`load_sample_data.py`) 将此数据添加到表中。

**将示例数据添加到表中**

1. 导航到含有 `sample_data.csv` 和 `load_sample_data.py` 文件的目录。如果这些文件位于不同的目录中，请进行移动，将文件保存在相同的位置。

1. 通过运行以下命令，创建 Python 虚拟环境，以运行脚本。我们建议您使用虚拟环境，因为在接下来的步骤中，您需要安装 适用于 Python (Boto3) 的 AWS SDK。

   ```
   python -m venv venv
   ```

1. 通过运行以下命令激活虚拟环境。

   ```
   source venv/bin/activate
   ```

1. 通过运行以下命令，将 SDK for Python（Boto3）安装到虚拟环境中。该脚本使用此库连接到 DynamoDB 表并添加项目。

   ```
   pip install boto3
   ```

1. 通过运行以下命令，运行脚本以填充表。

   ```
   python load_sample_data.py
   ```

   如果脚本成功运行，则它应在加载项目和报告 `Data loading completed` 时将每个项目打印到控制台。

1. 通过运行以下命令停用虚拟环境。

   ```
   deactivate
   ```

1. 您可以执行以下操作，以验证数据是否已加载到 DynamoDB 表：

   1. 打开 DynamoDB 控制台中的[浏览项目](https://console.aws.amazon.com/dynamodbv2/home#item-explorer)页面，然后选择表 (`MyOrderTable`)。

   1. 在**返回的项目**窗格中，您应该会看到脚本添加到表中 CSV 文件中的 25 个项目。

## 创建用于定期维护的应用程序
<a name="scheduled-task-app-create-app"></a>

您可以使用 AWS 管理控制台 或通过使用 AWS SAM 创建并部署此示例应用程序的资源。在生产环境中，建议使用 AWS SAM 等基础设施即代码（IaC）工具来重复部署无服务器应用程序，无需采用手动流程。

在本示例中，可按照控制台或说明了解如何单独配置每种 AWS 资源，或按照 AWS SAM 说明，使用 AWS CLI 命令快速部署应用程序。

------
#### [ Console ]

**使用 AWS 管理控制台 创建函数**

首先，创建包含基本起始代码的函数。然后，通过将此代码替换为自己的函数代码，方法是将代码直接复制并粘贴到 Lambda 代码编辑器中，或者将代码作为 `.zip` 包上传。对于此任务，我们建议复制并粘贴代码。

1. 打开 Lamba 控制台的 [Functions page](https://console.aws.amazon.com/lambda/home#/functions)（函数页面）。

1. 选择 **Create function**（创建函数）。

1. 选择**从头开始创作**。

1. 在**基本信息**中，执行以下操作：

   1. 对于 **Function name（函数名称）**，请输入 `ScheduledDBMaintenance`。

   1. 对于**运行时**，请选择最新的 Python 版本。

   1. 对于**架构**，选择 **x86\$164**。

1. 选择**创建函数**。

1. 创建函数后，您可以使用提供的函数代码配置函数。

   1. 在**代码源**窗格中，将 Lambda 创建的 Hello world 代码替换为之前保存的 `lambda_function.py` 文件中的 Python 函数代码。

   1. 在**部署**部分，选择**部署**以更新函数的代码：  
![\[\]](http://docs.aws.amazon.com/zh_cn/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**配置函数内存和超时（控制台）**

1. 选择函数的**配置**选项卡。

1. 在**常规配置**窗格中，选择**编辑**。

1. 将**内存**设置为 256 MB，并将**超时**设置为 15 秒。如果您正在处理包含许多记录的大型表，例如在生产环境中，则可以考虑将**超时**设置为更大数值。此举会让函数有更多时间扫描和清理数据库。

1. 选择**保存**。

**配置日志格式（控制台）**

您可以将 Lambda 函数配置为以非结构化文本或 JSON 格式输出日志。我们建议将 JSON 格式用于日志，以简化搜索和筛选日志数据的流程。要了解有关 Lambda 日志配置选项的更多信息，请参阅[为 Lambda 函数配置高级日志记录控件](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)。

1. 选择函数的**配置**选项卡。

1. 选择**监控和操作工具**。

1. 在**日志记录配置**窗格中，选择**编辑**。

1. 对于**日志记录配置**，选择 **JSON**。

1. 选择**保存**。

**要设置 IAM 权限**

要向函数授予读取和删除 DynamoDB 项目所需的权限，您需要向函数的[执行](lambda-intro-execution-role.md)角色添加来定义必要权限的策略。

1. 打开**配置**选项卡，然后从左侧导航栏中选择**权限**。

1. 在**执行角色**下，选择角色名称。

1. 在 IAM 控制台中，选择**添加权限**，然后选择**创建内联策略**。

1. 使用 JSON 编辑器并输入以下策略：  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:Scan",
                   "dynamodb:DeleteItem",
                   "dynamodb:BatchWriteItem"
               ],
               "Resource": "arn:aws:dynamodb:*:*:table/MyOrderTable"
           }
       ]
   }
   ```

1. 将策略命名为 **DynamoDBCleanupPolicy**，然后创建策略。

**将 EventBridge 调度器设置为触发器（控制台）**

1. 打开 [EventBridge 控制台](https://console.aws.amazon.com/events/home)。

1. 在左侧导航窗格中，选择**调度器**部分下的**调度器**。

1. 选择**创建计划**。

1. 通过执行以下操作配置计划：

   1. 在**计划名称**下，输入计划的名称（例如：**DynamoDBCleanupSchedule**）。

   1. 在**计划模式**下，选择**定期计划**。

   1. 对于**计划类型**，将默认值保留为**基于 Cron 的计划**，然后输入以下计划详细信息：
      + **分钟**：**0**
      + **小时**：**3**
      + **日**：**1**
      + **月**：**\$1**
      + **星期**：**?**
      + **年**：**\$1**

      评估后，此 cron 表达式会在每月第 1 天上午 03:00 运行。

   1. 对于**灵活时间窗口**下，选择**关闭**。

1. 选择**下一步**。

1. 通过执行以下操作，为 Lambda 函数配置触发器：

   1. 在**目标详细信息**窗格中，将**目标 API** 设置为**模板化目标**，然后选择 **AWS Lambda 调用**。

   1. 在**调用**下，从下拉列表中选择 Lambda 函数 (`ScheduledDBMaintenance`)。

   1. 将**有效载荷**留空，然后选择**下一步**。

   1. 向下滚动到**权限**，然后选择**为此计划创建新角色**。使用控制台创建新 EventBridge 调度器计划时，EventBridge 调度器会创建新策略，该策略具有调用函数所需的必要权限。有关管理计划权限的更多信息，请参阅《EventBridge Scheduler User Guide》中的 [Cron-based schedules](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html#cron-based)。**

   1. 选择**下一步**。

1. 查看设置，然后选择**创建计划**以完成计划和 Lambda 触发器的创建。

------
#### [ AWS SAM ]

**要部署应用程序，请使用 AWS SAM**

1. 导航到您为应用程序保存 `template.yaml` 文件的文件夹。请注意，此示例使用两个 `template.yaml` 文件。确保将它们保存在单独的子文件夹中，并且您位于包含模板的正确文件夹中，以便创建应用程序。

1. 将之前下载的 `lambda_function.py` 和 `requirements.txt` 文件复制到同一个文件夹。AWS SAM 模板中指定的代码位置是 `./`，即当前位置。尝试部署应用程序时，AWS SAM 将在此文件夹中搜索 Lambda 函数代码。

1. 运行如下命令。

   ```
   sam build --use-container
   ```

   此命令会收集您想要部署资源的构建构件，并将其以适当的格式放置在适当的位置进行部署。指定 `--use-container` 选项会在类似 Lambda 的 Docker 容器中构建函数。我们在这里使用它，您无需在本地计算机上安装 Python 3.12 即可进行构建。

1. 要创建 `template.yaml` 文件中指定的 Lambda 和 EventBridge 调度器资源，请运行以下命令。

   ```
   sam deploy --guided
   ```

   使用 `--guided` 标志意味着 AWS SAM 将向您显示提示，以指导您完成部署过程。对于此部署，输入 **cron-maintenance-app** 的 `Stack name`，然后使用 Enter 接受所有其他选项的默认值。

   当 AWS SAM 创建完 Lambda 和 EventBridge 调度器资源后，您将看到以下消息。

   ```
   Successfully created/updated stack - cron-maintenance-app in us-west-2
   ```

1. 此外，您还可以通过打开 Lambda 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面，来确认系统已创建 Lambda 函数。您应该会看到名为 `ScheduledDBMaintenance` 的函数。

------

## 测试应用程序
<a name="scheduled-task-app-test-app"></a>

 要测试计划是否正确触发了函数，以及函数是否正确清理了数据库中的记录，您可以对计划进行临时修改，设置为在特定时间运行一次。然后，您可以再次运行 `sam deploy`，以将定期计划重置为每月运行一次。

**使用 AWS 管理控制台 运行应用程序。**

1. 导航回到 EventBridge 调度器控制台页面。

1. 选择计划，然后选择**编辑**。

1. 在**计划模式**部分的**定期**下，选择**一次性计划**。

1.  将调用时间设置为距现在起几分钟后，查看设置，然后选择**保存**。

 在计划运行并调用其目标之后，您可以运行 `test_app.py` 脚本来验证函数是否从 DynamoDB 表中成功删除了所有旧记录。

**使用 Python 脚本验证是否已删除旧记录**

1.  在命令行中，导航到保存 `test_app.py` 的文件夹。

1. 运行 脚本。

   ```
   python test_app.py
   ```

    如果成功删除，您将会看到以下输出。

   ```
   Total number of old records: 0
   ```

## 后续步骤
<a name="scheduled-task-app-next-steps"></a>

 现在，您可以修改 EventBridge 调度器以满足特定应用程序要求。EventBridge 调度器支持以下计划表达式：cron、速率和一次性计划。

 有关 EventBridge 调度器计划表达式的更多信息，请参阅[《EventBridge 调度器用户指南》](https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html)中的*计划类型*。《*IAM 用户指南*》中的[访问管理](https://docs.aws.amazon.com/IAM/latest/UserGuide/access.html) 