delete_message_batch并没有真正从SQS队列中删除消息

时间:2018-01-29 03:47:43

标签: boto3 amazon-sqs

我正在使用标准的Amazon SQS队列。使用python3中的boto3库与SQS进行交互。以下是我收到邮件然后删除邮件的代码:

from boto3.session import Session
boto3_session = Session(region_name=SQS_REGION_NAME, aws_access_key_id=SQS_ACCESS_ID,
                                aws_secret_access_key=SQS_ACCESS_KEY)
sqs = boto3_session.client('sqs')

response = sqs.receive_message(
    MessageAttributeNames=[
        'EventToReport',
    ],
    QueueUrl=queue_url,
    MaxNumberOfMessages=10,
    VisibilityTimeout=0,
    WaitTimeSeconds=0
)
messages = response['Messages']
receipt_handles = [{'Id': str(index), 'ReceiptHandle': msg['ReceiptHandle']} for index, msg in enumerate(messages)]
sqs.delete_message_batch(QueueUrl=queue_url, Entries=receipt_handles)

这会返回成功回复:

{'Successful': [{'Id': '0'}, {'Id': '1'}, {'Id': '2'}, {'Id': '3'}, {'Id': '4'}, {'Id': '5'}, {'Id': '6'}, {'Id': '7'}, {'Id': '8'}, {'Id': '9'}], 'ResponseMetadata': {'RequestId': 'bb28855b-6522-5a1e-a649-d7b3fdabfebe', 'RetryAttempts': 0, 'HTTPStatusCode': 200, 'HTTPHeaders': {'content-length': '1008', 'connection': 'keep-alive', 'server': 'Server', 'date': 'Mon, 29 Jan 2018 03:34:33 GMT', 'content-type': 'text/xml', 'x-amzn-requestid': 'bb28855b-6522-5a1e-a649-d7b3fdabfebe'}}}

但是当我查看我的SQS管理控制台时,我发现没有任何消息被删除!消息的可见性超时为30秒。

我将队列的可见性超时时间增加到30分钟,现在只有1条消息被删除,尽管响应相同!

我知道删除完成需要时间,所以我每次都要等2-3分钟,但是消息仍然在队列中......我是否以错误的方式调用了API?据我所知,这是使用boto3调用sqs api的正确方法。

2 个答案:

答案 0 :(得分:1)

我终于发现了我的代码问题。虽然我在sqs控制台中描述了可见性超时,但是我的获取请求覆盖了该请求,所以我刚从我的receive_message代码中删除了以下两行:

VisibilityTimeout=0,
WaitTimeSeconds=0

现在工作正常。

答案 1 :(得分:1)

SQS如何处理删除请求

描述了为什么设置VisibilityTimeoutWaitTimeSeconds影响删除方法的行为。

  

注意

     

ReceiptHandle与接收消息的特定实例相关联。如果您多次收到一条消息,则每次收到一条消息时,ReceiptHandle都会不同。使用DeleteMessage操作时,必须为消息提供最近收到的ReceiptHandle(否则,请求将成功,但是可能不会删除该消息)。

     

对于标准队列,即使将其删除,也可能会收到一条消息。如果在您发送删除消息的请求时,其中一台存储消息副本的服务器不可用,则这种情况可能很少发生。该副本仍保留在服务器上,并可能在后续的接收请求中退还给您。您应该确保应用程序是幂等的,以便多次接收一条消息不会引起问题。

这部分是最重要的: ReceiptHandle与接收消息的特定实例相关联。如果您多次收到一条消息,那么每次收到一条消息时,ReceiptHandle都会有所不同。这意味着,如果该体系结构允许单个队列的多个使用者,则很可能一个使用者正在处理该消息,已被其他使用者再次检索一次,并且要删除该消息的ReceiptHandle已经不同。第二个重要的事情是请求成功,但是消息可能不会被删除。 SQS不会让您知道邮件没有删除。

设置如何提供帮助

以及为什么他们在任何情况下都无济于事

检索之间的延迟越短,则另一个使用者在处理消息时“不必要地”检索消息的可能性就越大。但是,如果消费者进行长时间的轮询并缓存RecipeHandle,则所需的VisibilityTimeout应该太长且具有如此大的价值,它将减慢轮询的速度,使其几乎是连续的。

解决方案

在您无法在检索后立即删除消息的情况下,应在单独的使用者中删除已处理的消息,否则,有可能将其保留为孤立的消息(该消息永远不会被处理,再次删除)。