Облачные функции для Firebase, убитых из-за превышения лимита памяти

Я постоянно получаю спорадическую ошибку от облачных функций для Firebase при преобразовании относительно небольшого изображения (2 МБ). В случае успеха функция занимает около 2000 мс или меньше, и в соответствии с документацией Image Magick я не должен видеть никаких проблем.

Я попытался увеличить размер буфера для команды, которая не позволяет внутри Firebase, и я попытался найти альтернативы .spawn(), поскольку это может быть перегружено мусором и замедлить работу. Ничего не работает.

Ответ 1

[обновление] Как сказал один из комментаторов, это больше не должно быть проблемой, поскольку функции firebase теперь поддерживают свои настройки при повторном развертывании. Спасибо, firebase!

Оказывается, и это не очевидно или документировано, вы можете увеличить выделение памяти для своих функций в Консоль функций Google. Вы также можете увеличить тайм-аут для длительных функций. Он решил проблему с перегрузкой памяти, и теперь все отлично работает.

Изменить: обратите внимание, что Firebase будет reset ваши значения по умолчанию при развертывании, поэтому вам не следует заходить на консоль и сразу же обновлять их. Я по-прежнему ищу способ обновить эти настройки с помощью CLI, обновится, когда найду его.

Ответ 2

Я был потерян в пользовательском интерфейсе, не мог найти никакой возможности изменить память, но наконец нашел ее:

  1. Перейдите в консоль Google Cloud Platform (не консоль Firebase)
  2. Выберите Облачные функции в меню
  3. Теперь вы видите свою функцию firebase здесь, если она правильная. В противном случае проверьте, правильно ли вы выбрали проект.
  4. Игнорировать все флажки, кнопки и пункты меню, просто нажмите на название функции.
  5. Нажмите на редактировать (верхнее меню) и только измените выделенную память и нажмите Сохранить.

Ответ 3

Вы можете установить это в своем файле облачных функций в Firebase.

const runtimeOpts = {
  timeoutSeconds: 300,
  memory: '1GB'
}

exports.myStorageFunction = functions
  .runWith(runtimeOpts)
  .storage
  .object()
  .onFinalize((object) = > {
    // do some complicated things that take a lot of memory and time
  });

Возьмите документы здесь: https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation

Не забудьте затем запустить firebase deploy из вашего терминала.

Ответ 4

Последняя команда firebase deploy перезаписывает выделение памяти по умолчанию 256 МБ и время ожидания до 60 с.

В качестве альтернативы, чтобы указать желаемое распределение памяти и максимальное время ожидания, я использую команду gcloud, такую как:

бета-функции gcloud развертывают YourFunctionName --memory = 2048 МБ --timeout = 540 с

Другие варианты, пожалуйста, обратитесь к:

https://cloud.google.com/sdk/gcloud/reference/beta/functions/deploy

Ответ 5

Обновление: похоже, что теперь они сохраняют настройки при повторном развертывании, поэтому вы можете безопасно изменять распределение памяти в облачной консоли!

Ответ 6

Кажется, что конфигурация ресурса ImageMagick по умолчанию в облачных функциях Firebase не соответствует фактической памяти, выделенной функции.

Запуск identify -list resource в контексте Облачной функции Firebase дает:

File       Area         Memory        Map       Disk   Thread  Throttle       Time
--------------------------------------------------------------------------------
 18750    4.295GB       2GiB       4GiB  unlimited        8         0   unlimited  

Память по умолчанию, выделенная для FCF, составляет 256 Мбайт - по умолчанию экземпляр ImageMagick считает, что он имеет 2 ГБ и поэтому не выделяет буфер с диска и может легко попытаться перераспределить память, что приведет к сбою функции на Error: memory limit exceeded. Function killed.

Один из способов - увеличить требуемую память, как было предложено выше, - хотя по-прежнему существует риск, что IM попытается перераспределить в зависимости от вашего варианта использования и выбросов.

Безопаснее всего было бы установить правильный предел памяти для IM как часть процесса обработки изображений с помощью -limit memory [your limit]. Вы можете выяснить, как использовать вашу память, используя вашу логику IM с помощью `-debug Cache '- она ​​покажет вам все выделенные буферы, их размеры и если они были памятью или диском.

Если IM попадает в предел памяти, он начнет распределять буферы на диске (с отображением памяти, а затем с обычными дисковыми буферами). Вам нужно будет учитывать ваш конкретный баланс между производительностью ввода-вывода и стоимостью памяти. Цена каждого дополнительного байта памяти вы выделяете свой FCF, умножается на 100 мс использования - так что может быстро расти.

Ответ 7

Другой вариант здесь заключается в том, чтобы избежать использования .spawn() вообще.

Существует большой пакет обработки изображений для node Sharp, который использует библиотеку footprint с низкой памятью libvips. Вы можете проверить образец облачной функции на Github.

В качестве альтернативы существует оболочка node для ImageMagick (и GraphicsMagick), называемая gm. Он даже поддерживает параметр - limit, чтобы сообщать о своих ресурсных ограничениях для IM.