Amazon web services 如何制作x小时的SQS延迟队列
我需要一个队列来处理x小时延迟后的消息。我需要一种数据驱动的、基于事件的方法,不使用任何调度器等 场景是,我将一些实时数据发送到SNS主题,并从那里发送到不同的SQS队列,供不同的AWS Lambda函数使用 其中一个Lambda函数需要在延迟3小时后处理消息。但是,最大交付延迟为15分钟。如果我第一次阅读该消息,它将自动从SQS中删除,因为我正在使用事件源映射触发器来调用lambda函数 因此,我想知道如何避免删除邮件,并使其在第一次处理时不可见Amazon web services 如何制作x小时的SQS延迟队列,amazon-web-services,aws-lambda,amazon-sqs,data-driven-tests,Amazon Web Services,Aws Lambda,Amazon Sqs,Data Driven Tests,我需要一个队列来处理x小时延迟后的消息。我需要一种数据驱动的、基于事件的方法,不使用任何调度器等 场景是,我将一些实时数据发送到SNS主题,并从那里发送到不同的SQS队列,供不同的AWS Lambda函数使用 其中一个Lambda函数需要在延迟3小时后处理消息。但是,最大交付延迟为15分钟。如果我第一次阅读该消息,它将自动从SQS中删除,因为我正在使用事件源映射触发器来调用lambda函数 因此,我想知道如何避免删除邮件,并使其在第一次处理时不可见 任何想法/帮助都将不胜感激。我测试了它。这似乎
任何想法/帮助都将不胜感激。我测试了它。这似乎是可行的。我使用下面的代码进行测试。然而,这似乎不是一种“好的实践”方式来实现你想要实现的目标。我看到两个主要问题:
import json
import os
import time
import boto3
sqs = boto3.client('sqs')
queue_url = os.environ['QUEUE_URL']
new_visibility_timeout = 120 # seconds
def lambda_handler(event, context):
print(json.dumps(event))
current_time = time.time()
no_of_new_records = 0
for record in event['Records']:
msg_timestamp = float(record['attributes']['SentTimestamp'])/1000
msg_age = current_time - msg_timestamp
print(f"Message age: {msg_age} seconds")
if msg_age > new_visibility_timeout:
print("Message to be successfully processed and deleted from queue")
response = sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=record['receiptHandle']
)
print(response)
else:
print("Set long visibility timeout")
response = sqs.change_message_visibility(
QueueUrl=queue_url,
ReceiptHandle=record['receiptHandle'],
VisibilityTimeout=new_visibility_timeout
)
print(response)
no_of_new_records += 1
if no_of_new_records > 0:
raise Exception("Fail the lambda")
return {'statusCode': 200}
我测试过了。这似乎是可行的。我使用下面的代码进行测试。然而,这似乎不是一种“好的实践”方式来实现你想要实现的目标。我看到两个主要问题:
import json
import os
import time
import boto3
sqs = boto3.client('sqs')
queue_url = os.environ['QUEUE_URL']
new_visibility_timeout = 120 # seconds
def lambda_handler(event, context):
print(json.dumps(event))
current_time = time.time()
no_of_new_records = 0
for record in event['Records']:
msg_timestamp = float(record['attributes']['SentTimestamp'])/1000
msg_age = current_time - msg_timestamp
print(f"Message age: {msg_age} seconds")
if msg_age > new_visibility_timeout:
print("Message to be successfully processed and deleted from queue")
response = sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=record['receiptHandle']
)
print(response)
else:
print("Set long visibility timeout")
response = sqs.change_message_visibility(
QueueUrl=queue_url,
ReceiptHandle=record['receiptHandle'],
VisibilityTimeout=new_visibility_timeout
)
print(response)
no_of_new_records += 1
if no_of_new_records > 0:
raise Exception("Fail the lambda")
return {'statusCode': 200}
AmazonSQS不会满足您的要求。此外,我不建议做任何“把戏”来迫使它推迟
我建议您查看AWS Step函数。它可以协调AWS Lambda函数之间的交互,并且可以配置为在调用AWS Lambda函数之前等待(睡眠)一段时间。此外,我不建议做任何“把戏”来迫使它推迟
我建议您查看AWS Step函数。它可以协调AWS Lambda函数之间的交互,并且可以配置为在调用AWS Lambda函数之前等待(睡眠)一段时间您不能在第一次阅读消息后删除它吗?也许您可以从队列中获取它,将其可见性更改为3h(最多12h),并在3h内再次正确处理它。一旦我读取它们,它们就会被事件源映射自动删除@Marcin,我本来打算读一次,然后把它放在那里,直到可见性超时达到重新处理的阈值。但是,它似乎是第一次被删除。我正在寻找一种避免此删除部分的方法。如果您从lambda返回successful,是的,事件源映射将假定消息已成功处理并将其删除。如果更改可见性超时后lambda失败,事件源映射将不会删除该消息。相反,它将重试再次提交。我认为返回200以外的状态代码将被视为失败?我得检查一下。哦!很高兴知道,我以为只有调用失败才会再次将MSG返回队列。。。所以我的lambda的任何例外都是正确的?我马上就去试试。。感谢您在第一次阅读邮件后不删除它吗?也许您可以从队列中获取它,将其可见性更改为3h(最多12h),并在3h内再次正确处理它。一旦我读取它们,它们就会被事件源映射自动删除@Marcin,我本来打算读一次,然后把它放在那里,直到可见性超时达到重新处理的阈值。但是,它似乎是第一次被删除。我正在寻找一种避免此删除部分的方法。如果您从lambda返回successful,是的,事件源映射将假定消息已成功处理并将其删除。如果更改可见性超时后lambda失败,事件源映射将不会删除该消息。相反,它将重试再次提交。我认为返回200以外的状态代码将被视为失败?我得检查一下。哦!很高兴知道,我以为只有调用失败才会再次将MSG返回队列。。。所以我的lambda的任何例外都是正确的?我马上就去试试。。谢谢我试过了,但对我无效!即使我引发了异常,消息仍然会被删除。我可以看到它甚至会更改可见性超时,但这与将消息标记为不可见不同。它只是删除它:|您的lambda是否有权使用SQS?还可以为主SQS队列设置DLQ,这样,如果处理不正确,消息就会转到那里。是的,我也可以手动调用delete message!但是没有意义!因为不管发生什么,它都在删除消息。我认为是从sqs到lambda的触发器导致了这种自动删除行为…如果我手动轮询队列,它将正常工作。您仍然使用延迟队列吗?我用所有默认设置在常规队列上测试了它。lambda的执行角色还具有完整的sqs权限。如果使用不同的设置,可能需要相应地调整代码。作为一个概念证明,您可以使用提供的代码控制可见性超时。我尝试了这个,但没有成功!即使我引发了异常,消息仍然会被删除。我可以看到它甚至会更改可见性超时,但这与将消息标记为不可见不同。它只是删除它:|您的lambda是否有权使用SQS?还可以为主要SQS queu设置DLQ