我有一个类似的架构:
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分钟。
任何帮助将不胜感激!
如果需要,可以随时要求更高的精度。
答案 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.
您可能想尝试使用长轮询,其值要高于可见性超时
我希望对您有帮助
答案 1 :(得分:0)
我忘了回答这个问题。
问题在于将SQS设置为FIFO队列。 FIFO队列一次只允许一个使用者(保留消息的顺序)。将其更改为普通队列可以解决此问题。