boto3 put_item 成功但没有出现记录

boto3 put_item succeeds but record does not appear

我在任何地方都找不到这个问题的答案,希望 SO 最终能够提供帮助。

我有一个 lambda 函数可以处理一条记录,然后将其写入 dynamodb table。从所有意图和目的来看,put_item 调用似乎成功了,但是,当我检查 dynamo table 时,记录没有出现在其中。

import json
import boto3
import uuid
import urllib3
from botocore.exceptions import ClientError

def lambda_handler(event, context):
  
  apiResponse = {}
  for record in event['Records']:
    decoded = json.loads(record['body'])
    listId = int(decoded['queryParams']['rec_id'])
    apiCall = "INTERNAL API"
    http = urllib3.PoolManager()
    request = http.request('GET', apiCall)
    apiResponse = json.loads(request.data.decode('utf-8'))

    try:
      client = boto3.resource('dynamodb')
      table = client.Table('HistoryAuditTable')
      saveStatus = table.put_item(Item={
        'UUID': uuid.uuid4().hex,
        'RecId': listId,
        'MessageType': decoded['queryParams']['type'],
        'MessageTimestampUTC': record['attributes']['SentTimestamp'],
        'Message': apiResponse
      })
      print("STATUS")
      print(saveStatus) # This prints out a 200 status code in CloudWatch
    except ClientError as e:
      # This error never happens.
      print("ERROR")
      print(e.response["Error"]['Message'])
      
  # Response Status
  response = {}
  response["body"] = json.dumps(decoded)

  return response

我的 apiResponse 是一个简单的 json 有效载荷,其中包含一些我们在记录更改时跟踪的审计数据。

我的发电机 table 有以下字段:

UUID: self-explanatory, 
RecId: an internal record identifier (we keep this separate from the PK because the same record might be updated again and again),
MessageType: String representing if the record was a "SEED_VALUE", "CREATE", "UPDATE", "ARCHIVE", or "SOFT_DELETE"
MessageTimestampUTC: self-explanatory
Message: JSON blob containing the record details

我必须用我们数据的当前状态(大约 400k 条记录)的初始加载为这个 table 播种,播种过程使用相同的 aws lambda 函数。我的第一个迹象是,40 万条记录中只有大约 10 万条记录实际上进入了 table,尽管所有 40 万行 returns 都是 200 响应代码,在我注意到这一点之后,我决定尝试并触发将单个记录推送到 table 的进程,我可以看到我的函数正确触发,我可以看到我的 api 调用正确返回,我可以看到 saveStatus 似乎是成功的,但是我没有在 dynamo table 中看到我的记录。我想我在这里有几个问题:

  1. dynamodb tables 有写入限制吗?我是否可能一开始就向其中推送了太多数据,而在我的限制重置之前我根本无法推送任何新数据? (我在网上的任何地方都找不到这个问题的直接答案)
  2. 我做错了什么吗?我的过程几乎完全是从 AWS 文档中复制的,但是 AWS 的文档是出了名的糟糕。
  3. 是否可以通过 cloudwatch 为 dynamodb 启用某种 error/write 日志记录? (我在任何地方都找不到这方面的任何信息)

我检查过的其他几件事:

老实说,我很茫然,我不明白 how/why 该过程适用于 10 万条记录,然后突然决定不再适用。

一般的一些建议、指示和观察,如果您回答评论中的问题,这可能会更具体。

看看 DynamoDB 中的 read and write capacity modes as well as partitioning。本质上,每个 1KB 的分区有 1000 次写入的上限。根据您的按键设置,您可能会点击它。您可以在 table 的指标中查明是否属于这种情况。另外:你会得到写入失败的异常,这让我进入下一点。

在您的代码中,您基本上将 DynamoDB 写入视为可有可无。如果它成功了,那就太好了,如果没有 - 您只需记录错误并继续。这不是调试的理想设置,在这种情况下,您可以考虑将写入 DynamoDB 的内容卸载到单独的 Lambda 中,例如通过将它们存储在 SQS 中并分批处理它们。如果写入对您的客户很重要,请不要“沉默”错误,引发适当的异常并向客户发出出错的信号。在一百万次成功的日志中寻找奇怪的错误并不有趣;-)

好消息是,您的做法并没有完全错误,但您可以优化一些内容。实例化 boto3 资源和客户端是一个相对昂贵的操作,如果你关心性能,你可以缓存它们。考虑使用 batching 来减少网络请求量。

您可以在 table 的 Metrics-Tab 中监控潜在的限制数量以及 read/write 错误。指标称为:

  • Throttled [write|read] requests
  • Throttled [write|read] events
  • System errors [write|read]