Google Cloud Pubsub клиент node.js не совместим с облачными функциями Google
Архитектура:
У нас есть архитектура, использующая две пары pubsub theme / subscription:
- Тема
T1
периодически запускается cronjob (например, каждые 5 минут). ПодпискаS1
является триггером для нашей облачной функции. - Тема
T2
служит очередью для фоновых заданий, которые публикуются одним из наших сервисов. ПодпискаS2
Читается облачной функцией при каждом выполнении для обслуживания фоновых заданий в очереди.
Это позволяет нам контролировать частоту обслуживания фоновых заданий независимо от того, когда они добавляются в очередь.
Облачная функция (запускается S1
) читает сообщения от S2
потянув. Он решает, какие фоновые задания готовы, и после успешного обслуживания задания он подтверждает соответствующие сообщения. Задания, не готовые или не выполненные, не обрабатываются ACK для последующего обслуживания.
Выпуск:
У нас есть проблемы с использованием официального клиента node.js pubusb от Google:
- Иногда сообщения ACK появляются снова (кажутся бесконечными). Мы проверили, что сообщения подтверждены до истечения крайнего срока ACK, и уверены, что мы звоним
ack()
исследуя наши журналы. - Иногда после первого выполнения (после повторного развертывания функции) последующие выполнения никогда не получают новые сообщения. Мы можем проверить сообщения в очереди в подписке
S2
либо путем проверки количества неподтвержденных сообщений в стеке-драйвере, либо путем повторного развертывания функции и наблюдения за обслуживанием сообщений.
Мы считаем, что это проблема с клиентом google's node.js pubsub. В облачной функции четко указано, что фоновые действия не запускаются. Однако, глядя на исходный клиентский файл node.js, он явно обслуживает подтверждения в фоновом режиме, используя тайм-ауты.
Не совместим ли клиент google's node.js pubsub с облачными функциями Google? Google рекомендует получать доступ к API-интерфейсу службы только в том случае, если клиентская библиотека не существует или не соответствует другим потребностям. Является ли запуск клиента в облачной функции "другими потребностями", требующими от нас написания нашего собственного клиента с использованием сервисных API?
Попытка обхода:
В качестве "обходного пути" мы попытались отложить завершение выполнения облачной функции, чтобы позволить завершить любые "фоновые" процессы в клиенте pubsub node.js, но это не помогло устранить проблему. Кажется, что клиент pubsub не дружествен к облачным функциям и не может восстановиться после остановки между выполнением облачных функций.
Обновление 22 февраля 2018
Я написал статью в нашем блоге, в которой подробно описывается, почему мы использовали PubSub таким образом и как мы работаем вокруг того факта, что клиент pubsub node.js не совместим с облачными функциями.
3 ответа
Разработчик из клиента pubsub для node.js подтвердил, что использование клиента для извлечения сообщений из облачной функции не поддерживается.
Альтернативой является использование сервисных API. Однако API REST имеют свои собственные предостережения при попытке извлечь все сообщения из подписки.
Как вы запускаете свои функции?
Согласно документации, если ваша функция использует сообщения pubsub, вам следует использовать триггер pubsub. При использовании триггера pubsub библиотека не нужна. Просто позвони callback()
в конце вашей функции, и сообщение pubsub будет правильно подтверждено.
Из-за того, что вы намереваетесь сделать, я не думаю, что ваша текущая архитектура является правильным вариантом.
Я бы переместил ваш первый шаг в Google App Engine с помощью задачи cron, и чтобы эта задача просто перемещала сообщения из T2
в T1
оставив функцию с триггером S2
и обработка сообщения.
Итак, ваши работы будут опубликованы на T2
и у вас будет приложение GAE с подпиской по запросу S2
запускается задачей cron, и это приложение повторно публикует сообщение в T1
, Тогда ваша функция будет вызвана подпиской S1
к теме T1
и будет запускать задание в сообщении, избегая дополнительной обработки импорта библиотеки pubsub и использования продукта, как ожидается.
Кроме того, я не уверен, как вы изначально публикуете свои работы в этой теме, но очереди задач - хороший вариант GAE (и не зависящий от продукта в Alpha) для задач, ограничивающих скорость.
Приложение GAE, используемое только для этого (установка 1 максимального экземпляра), будет находиться в пределах всегда свободного предела, поэтому затраты не будут заметно увеличены.
Я столкнулся с той же проблемой, я хотел лучше контролировать .ack()
, Глядя на библиотеку nodejs от Google, можно было бы изменить ack()
вернуть обещание, чтобы функция могла ждать ack()
завершить.
Subscriber.prototype.ack_ = function(message) {
var breakLease = this.breakLease_.bind(this, message);
this.histogram.add(Date.now() - message.received);
if (this.writeToStreams_ && this.isConnected_()) {
this.acknowledge_(message.ackId, message.connectionId).then(breakLease);
return;
}
this.inventory_.ack.push(message.ackId);
this.setFlushTimeout_().then(breakLease);
};