使用 Python 通过 Lambda 访问 DynamoDB 而不会达到 read/write 容量
Accessing DynamoDB through Lambda with Python without hitting read/write capacity
出于某种原因,每次我 运行 我的 Lambda 函数都会收到来自 DynamoDB 的错误:
INSUFFICIENT_DATA Assets-ReadCapacityUnitsLimit-BasicAlarm
ConsumedReadCapacityUnits >= 240 for 5 datapoints within 5 minutes
我对 AWS 和 Python 的一切都是新手,所以希望有人能看一眼这段代码并指出我的愚蠢之处。
我想做的是使用 slack 中的“!Addme”命令将用户添加到数据库中。我已经设法让 slack 和 lambda 以发送命令和接收答案的形式相互交谈。对于我的下一步,我想学习如何让 Lambda 从 dynamoDB 中提取数据。
从我的警报来看,我每秒发出的 read/write 请求似乎太多了。这可能只是我缺乏 python 理解。所以我的问题是,在我定义的函数(getAssetTableIDList() 和 getUserIDExistance(userID))上,我在做一些愚蠢的事情吗?
感谢所有帮助。谢谢
我的 DynamoDB 的基本信息:
密钥 = 用户 ID(字符串)
Read/Write容量=1
################################
# Slack Lambda handler.
################################
import boto3
import os
import logging
import urllib
# Grab data from the environment.
BOT_TOKEN = os.environ["BOT_TOKEN"]
ASSET_TABLE = os.environ["ASSET_TABLE"]
REGION_NAME = os.getenv('REGION_NAME', 'us-east-1')
dynamo = boto3.client('dynamodb', region_name=REGION_NAME, endpoint_url="http://localhost:8000")
# Define the URL of the targeted Slack API resource.
SLACK_URL = "https://slack.com/api/chat.postMessage"
def getAssetTableIDList():
tables = dynamo.scan(TableName=ASSET_TABLE)
userIDList = {}
for item in tables['Items']:
userList[item['userID']['S']]
return userIDList
def getUserIDExistance(userID):
userIDList = getAssetTableIDList()
if userID in userIDList:
userIDExist = true
return userIDExist
def lambda_handler(data, context):
# Slack challenge answer.
if "challenge" in data:
return data["challenge"]
# Grab the Slack channel data.
slack_event = data['event']
slack_user = slack_event["user"]
slack_text = slack_event["text"]
channel_id = slack_event["channel"]
slack_userID = slack_user["ID"]
slack_reply = ""
# Ignore bot messages.
if "bot_id" in slack_event:
logging.warn("Ignore bot event")
else:
# Start data sift.
if slack_text.startswith("!networth"):
slack_reply = "Your networth is: "
elif slack_text.startwith("!price"):
command,asset = text.split()
slack_reply = "The price of a(n) %s is: " % (asset)
elif slack_text.startwith("!Addme"):
if not getUserIDExistance(slack_userID):
slack_reply = "Added user: %s" % (slack_user)
dynamo.update_item(TableName=ASSET_TABLE,
Key={'userID':{'S':'slack_userID'},
AttributeUpdates= {
'resources':{
'Action': 'ADD',
'Value': {'N': '1000'}
}
}
)
else
slack_reply = "User %s(%s) already exists" % (slack_user, slack_userID)
# We need to send back three pieces of information:
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id),
("text", slack_reply)
)
)
data = data.encode("ascii")
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
SLACK_URL,
data=data,
method="POST"
)
# Add a header mentioning that the text is URL-encoded.
request.add_header(
"Content-Type",
"application/x-www-form-urlencoded"
)
# Fire off the request!
urllib.request.urlopen(request).read()
# Everything went fine.
return "200 OK"
您正在执行完整 table 扫描以将整个 table 加载到内存中,然后遍历 table 中的每个对象以查看是否存在条目。您不需要进行扫描,而是需要使用相关 ID 进行查询,然后让 DynamoDB 告诉您该项目是否存在。
出于某种原因,每次我 运行 我的 Lambda 函数都会收到来自 DynamoDB 的错误:
INSUFFICIENT_DATA Assets-ReadCapacityUnitsLimit-BasicAlarm
ConsumedReadCapacityUnits >= 240 for 5 datapoints within 5 minutes
我对 AWS 和 Python 的一切都是新手,所以希望有人能看一眼这段代码并指出我的愚蠢之处。
我想做的是使用 slack 中的“!Addme”命令将用户添加到数据库中。我已经设法让 slack 和 lambda 以发送命令和接收答案的形式相互交谈。对于我的下一步,我想学习如何让 Lambda 从 dynamoDB 中提取数据。
从我的警报来看,我每秒发出的 read/write 请求似乎太多了。这可能只是我缺乏 python 理解。所以我的问题是,在我定义的函数(getAssetTableIDList() 和 getUserIDExistance(userID))上,我在做一些愚蠢的事情吗?
感谢所有帮助。谢谢
我的 DynamoDB 的基本信息: 密钥 = 用户 ID(字符串) Read/Write容量=1
################################
# Slack Lambda handler.
################################
import boto3
import os
import logging
import urllib
# Grab data from the environment.
BOT_TOKEN = os.environ["BOT_TOKEN"]
ASSET_TABLE = os.environ["ASSET_TABLE"]
REGION_NAME = os.getenv('REGION_NAME', 'us-east-1')
dynamo = boto3.client('dynamodb', region_name=REGION_NAME, endpoint_url="http://localhost:8000")
# Define the URL of the targeted Slack API resource.
SLACK_URL = "https://slack.com/api/chat.postMessage"
def getAssetTableIDList():
tables = dynamo.scan(TableName=ASSET_TABLE)
userIDList = {}
for item in tables['Items']:
userList[item['userID']['S']]
return userIDList
def getUserIDExistance(userID):
userIDList = getAssetTableIDList()
if userID in userIDList:
userIDExist = true
return userIDExist
def lambda_handler(data, context):
# Slack challenge answer.
if "challenge" in data:
return data["challenge"]
# Grab the Slack channel data.
slack_event = data['event']
slack_user = slack_event["user"]
slack_text = slack_event["text"]
channel_id = slack_event["channel"]
slack_userID = slack_user["ID"]
slack_reply = ""
# Ignore bot messages.
if "bot_id" in slack_event:
logging.warn("Ignore bot event")
else:
# Start data sift.
if slack_text.startswith("!networth"):
slack_reply = "Your networth is: "
elif slack_text.startwith("!price"):
command,asset = text.split()
slack_reply = "The price of a(n) %s is: " % (asset)
elif slack_text.startwith("!Addme"):
if not getUserIDExistance(slack_userID):
slack_reply = "Added user: %s" % (slack_user)
dynamo.update_item(TableName=ASSET_TABLE,
Key={'userID':{'S':'slack_userID'},
AttributeUpdates= {
'resources':{
'Action': 'ADD',
'Value': {'N': '1000'}
}
}
)
else
slack_reply = "User %s(%s) already exists" % (slack_user, slack_userID)
# We need to send back three pieces of information:
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id),
("text", slack_reply)
)
)
data = data.encode("ascii")
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
SLACK_URL,
data=data,
method="POST"
)
# Add a header mentioning that the text is URL-encoded.
request.add_header(
"Content-Type",
"application/x-www-form-urlencoded"
)
# Fire off the request!
urllib.request.urlopen(request).read()
# Everything went fine.
return "200 OK"
您正在执行完整 table 扫描以将整个 table 加载到内存中,然后遍历 table 中的每个对象以查看是否存在条目。您不需要进行扫描,而是需要使用相关 ID 进行查询,然后让 DynamoDB 告诉您该项目是否存在。