Amazon web services 如何制作x小时的SQS延迟队列

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函数 因此,我想知道如何避免删除邮件,并使其在第一次处理时不可见 任何想法/帮助都将不胜感激。我测试了它。这似乎

我需要一个队列来处理x小时延迟后的消息。我需要一种数据驱动的、基于事件的方法,不使用任何调度器等

场景是,我将一些实时数据发送到SNS主题,并从那里发送到不同的SQS队列,供不同的AWS Lambda函数使用

其中一个Lambda函数需要在延迟3小时后处理消息。但是,最大交付延迟为15分钟。如果我第一次阅读该消息,它将自动从SQS中删除,因为我正在使用事件源映射触发器来调用lambda函数

因此,我想知道如何避免删除邮件,并使其在第一次处理时不可见


任何想法/帮助都将不胜感激。

我测试了它。这似乎是可行的。我使用下面的代码进行测试。然而,这似乎不是一种“好的实践”方式来实现你想要实现的目标。我看到两个主要问题:

  • 飞行中的按摩次数限制为12万次。因此,SQS队列的扩展几乎是无限的

  • 您的度量将充斥着错误调用,很难区分真正失败的调用和故意失败的调用

  • 因此,我将研究其他解决办法

    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}
    

    我测试过了。这似乎是可行的。我使用下面的代码进行测试。然而,这似乎不是一种“好的实践”方式来实现你想要实现的目标。我看到两个主要问题:

  • 飞行中的按摩次数限制为12万次。因此,SQS队列的扩展几乎是无限的

  • 您的度量将充斥着错误调用,很难区分真正失败的调用和故意失败的调用

  • 因此,我将研究其他解决办法

    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