У меня есть тема Google Cloud PubSub, которая иногда содержит тысячи сообщений, а иногда и ноль сообщений. Эти сообщения представляют собой задачи, каждая из которых может занять более часа. Предпочтительно я могу использовать для этого Cloud Run, так как он очень хорошо масштабируется в зависимости от спроса: если будет опубликована тысяча сообщений, я хочу, чтобы 100 экземпляров Cloud Run развернулись. Эти экземпляры запуска запускаются с помощью принудительной подписки. Проблема в том, что PubSub имеет тайм-аут 600 секунд для подтверждения. Это означает, что для того, чтобы Cloud Run обработал эти сообщения, они должны быть обработаны в течение 600 секунд. В противном случае PubSub истекает время ожидания и отправляет его снова, в результате чего задача будет перезапущена до тех пор, пока первая задача, наконец, не подтвердит ее (это приводит к тому, что одна и та же задача запускается много раз). Cloud Run подтверждает сообщения, возвращая код состояния 2 ** HTTP. В документации указано
Когда приложение, работающее в Cloud Run, завершает обработку запроса, доступ экземпляра контейнера к ЦП будет отключен или серьезно ограничен. Следовательно, вы не должны запускать фоновые потоки или подпрограммы, которые выполняются за пределами обработчиков запросов.
Итак, возможно ли подтвердить запрос PubSub с помощью кода и продолжить обработку без передачи ресурсов Google Cloud Run? Или есть лучшее решение, о котором я не знаю?
Поскольку эти процессы требуют больших затрат кода / ресурсов, я считаю, что облачных функций будет недостаточно. Я просмотрел https://cloud.google.com/solutions/using-cloud-pub-sub-long-running-tasks и https://cloud.google.com/blog/products/gcp/how-google-cloud-pubsub.-supports-long-running-workloads . Но они не ответили на мой вопрос. Я посмотрел на Google Cloud Tasks, что может быть что-то? Но остальная часть проекта была построена вокруг PubSub / Run / Functions, поэтому я предпочитаю придерживаться этого.
Этот проект написан на Python. Поэтому желательно, чтобы мои задачи Google Cloud Run были такими:
@app.route('/', methods=['POST'])
def index():
"""Endpoint for Google Cloud PubSub messages"""
pubsub_message = request.get_json()
logger.info(f'Received PubSub pubsub_message {pubsub_message}')
if message_incorrect(pubsub_message):
return "Invalid request", 400 #use normal NACK handling
# acknowledge message here without returning
# ...
# Do actual processing of the task here
# ...
Итак, как можно или нужно решить эту проблему, чтобы ресурсоемкие задачи правильно масштабировались по запросу (например, подписка на push PubSub). И задачи выполняются только один раз.
Ответы: вкратце, что было дано. Cloud Run и Functions просто не подходят для этой проблемы. Невозможно заставить их выполнять задачи, которые занимают более 9 или 15 минут соответственно. Единственное решение - переключиться на другую службу Google и использовать подписку в стиле pull и потерять автоматическое масштабирование GC Run / Functions.