Как использовать Google Cloud PubSub и Run для обработки ресурсоемких длительных задач?

У меня есть тема 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.




Ответы (2)


Ни облачных функций, ни Cloud Run недостаточно для сколь угодно длительных операций. Cloud Functions имеет жесткое ограничение в 9 минут на вызов, а Cloud Run до 60. Если вам нужно больше времени, вам придется делегировать работу другому продукту, например Google Compute Engine. Должна быть возможность запускать некоторую работу Compute Engine с одного из бессерверных продуктов.

Если ограничить количество подтверждений pubsub, вам, вероятно, придется найти способ, позволяющий клиенту опрашивать или прослушивать какой-либо ресурс, чтобы узнать, когда работа действительно сделана. Для этого вы можете использовать базу данных, а Cloud Firestore позволяет прослушивать документы, чтобы узнать, когда они меняются. Таким образом, вы можете использовать это, чтобы отслеживать статус вашей длительной работы.

person Doug Stevenson    schedule 05.08.2019
comment
Также стоит отметить, что при использовании Google Cloud Pub / Sub вне Cloud Run или Cloud Functions можно вызвать modAckDeadline, чтобы увеличить крайний срок для подтверждения сообщения, если процесс еще продолжается. Клиентские библиотеки Cloud Pub / Sub обрабатывают это автоматически. Максимальное время для вызова modAckDeadline можно контролировать с помощью свойство max_lease_duration. - person Kamal Aboul-Hosn; 05.08.2019
comment
С 3 июня 2021 г. таймауты запросов до 60 минут теперь общедоступны (GA). См. примечание к выпуску. - person Dondi; 25.06.2021

Cloud Run на GKE может обрабатывать длительные процессы, используя больше ресурсов ЦП и памяти, чем доступно на управляемой платформе. Однако у вас всегда работает кластер GKE, и вы теряете возможность «платить по мере использования».

Если вы хотите использовать это решение, не связывайте подписку PubSub push напрямую со своим Cloud Run on GKE. Используйте для этого Cloud Task с заданием HTTP. Тайм-аут больше, чем PubSub (до 24 часов вместо 10 минут), а политики повтора можно настраивать.

person guillaume blaquiere    schedule 05.08.2019