ECS任务只能从SQS队列中选择一条消息

时间:2019-02-05 08:53:48

标签: python python-3.x amazon-web-services boto3 amazon-sqs

我有一个类似的架构:

  • 一旦消息发送到SQS队列,ECS任务就会选择该消息并进行处理。
  • 这意味着,如果X消息发送到队列中,则X ECS任务将并行启动。 ECS任务只能提取一条消息(按照上面的代码)

ECS任务使用dockerized Python容器,并使用boto3 SQS client检索和解析SQS消息:

sqs_response = get_sqs_task_data('<sqs_queue_url>')
sqs_message = parse_sqs_message(sqs_response)

while sqs_message is not None:
    # Process it
    # Delete if from the queue

    # Get next message in queue
    sqs_response = get_sqs_task_data('<sqs_queue_url>')
    sqs_message = parse_sqs_message(sqs_response)

def get_sqs_task_data(queue_url):
    client = boto3.client('sqs')

    response = client.receive_message(
        QueueUrl=queue_url,
        MaxNumberOfMessages=1
    )

    return response

def parse_sqs_message(response_sqs_message):

    if 'Messages' not in response_sqs_message:
        logging.info('No messages found in queue')
        return None

    # ... parse it and return a dict

    return {
        data_1 = ..., 
        data_2 = ...
    }

总而言之,非常简单。

get_sqs_data()中,我明确指定我只想检索一条消息(因为1个ECS任务只需要处理一条消息)。 在parse_sqs_message()中,我测试

队列中是否还有一些消息
if 'Messages' not in response_sqs_message:
        logging.info('No messages found in queue')
        return None

当队列中只有一条消息时(表示已触发一个ECS任务),一切正常。 ECS任务能够选择,处理和删除消息。

但是,当同时在队列中填充X条消息(X > 1)时,会触发X ECS任务,但是只有ECS任务才能提取一条消息并处理它。
尽管还有No messages found in queue条消息尚待处理,但其他所有ECS任务将以X - 1退出。

那是为什么?为什么其他任务无法选择剩下的消息以供选择?

如果这很重要,则SQS的VisibilityTimeout设置为30分钟。

任何帮助将不胜感激!

如果需要,可以随时要求更高的精度。

2 个答案:

答案 0 :(得分:0)

我不确定要如何从SQS触发任务,但是根据我在SQS SDK文档中了解的内容,如果使用短轮询时消息数量很少,则可能会发生这种情况。从get_sqs_task_data定义中,我看到您正在使用短轮询。

Short poll is the default behavior where a weighted random set of machines
is sampled on a ReceiveMessage call. Thus, only the messages on the 
sampled machines are returned. If the number of messages in the queue 
is small (fewer than 1,000), you most likely get fewer messages than you requested 
per ReceiveMessage call. 
If the number of messages in the queue is extremely small, you might not receive any messages in a particular ReceiveMessage response. 
If this happens, repeat the request.

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sqs.html#SQS.Client.receive_message

您可能想尝试使用长轮询,其值要高于可见性超时

我希望对您有帮助

答案 1 :(得分:0)

我忘了回答这个问题。

问题在于将SQS设置为FIFO队列。 FIFO队列一次只允许一个使用者(保留消息的顺序)。将其更改为普通队列可以解决此问题。