Управление функциями


Вы можете развертывать, удалять и изменять функции с помощью команд Firebase CLI или путем установки параметров выполнения в исходном коде функций.

Развертывание функций

Для развертывания функций выполните следующую команду Firebase CLI:

firebase deploy --only functions

По умолчанию Firebase CLI развертывает все функции внутри вашего источника одновременно. Если ваш проект содержит более 5 функций, мы рекомендуем вам использовать флаг --only с определенными именами функций, чтобы развертывать только те функции, которые вы отредактировали. Развертывание определенных функций таким образом ускоряет процесс развертывания и помогает избежать квот развертывания. Например:

firebase deploy --only functions:addMessage,functions:makeUppercase

При развертывании большого количества функций вы можете превысить стандартную квоту и получить сообщения об ошибках HTTP 429 или 500. Чтобы решить эту проблему, развертывайте функции группами по 10 или меньше.

Полный список доступных команд смотрите в справочнике Firebase CLI .

По умолчанию Firebase CLI ищет исходный код в папке functions/ . Если вы предпочитаете, вы можете организовать функции в кодовых базах или нескольких наборах файлов.

Очистка артефактов развертывания

В рамках развертывания функций образы контейнеров генерируются и сохраняются в Artifact Registry . Эти образы не требуются для запуска развернутых функций; Cloud Functions извлекает и сохраняет копию образа при первоначальном развертывании, но сохраненные артефакты не требуются для работы функции во время выполнения.

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

Для управления расходами на хранение Firebase CLI 14.0.0 и выше позволяет настраивать политику очистки Artifact Registry для репозиториев, в которых хранятся артефакты развертывания после каждого развертывания функции.

Вы можете вручную настроить или отредактировать политику очистки с помощью functions:artifacts:setpolicy :

firebase functions:artifacts:setpolicy

По умолчанию эта команда настраивает Artifact Registry на автоматическое удаление образов контейнеров старше 1 дня. Это обеспечивает разумный баланс между минимизацией затрат на хранение и возможностью потенциальной проверки последних сборок.

Вы можете настроить период хранения с помощью параметра --days :

firebase functions:artifacts:setpolicy --days 7  # Delete images older than 7 days

Если вы развертываете функции в нескольких регионах, вы можете настроить политику очистки для определенного местоположения с помощью параметра --location :

$ firebase functions:artifacts:setpolicy --location europe-west1

Отказаться от очистки артефактов

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

$ firebase functions:artifacts:setpolicy --none

Эта команда удаляет любую существующую политику очистки, настроенную Firebase CLI, и не позволяет Firebase настраивать политику очистки после развертывания функций.

Удалить функции

Удалить ранее развернутые функции можно следующими способами:

  • явно в Firebase CLI с помощью functions:delete
  • явно в консоли Google Cloud .
  • неявно, путем удаления функции из источника перед развертыванием.

Все операции удаления запрашивают подтверждение перед удалением функции из производства.

Явное удаление функции в Firebase CLI поддерживает несколько аргументов, а также группы функций и позволяет указать функцию, работающую в определенном регионе. Также можно переопределить запрос подтверждения.

# Delete all functions that match the specified name in all regions.
firebase functions:delete myFunction
# Delete a specified function running in a specific region.
firebase functions:delete myFunction --region us-east-1
# Delete more than one function
firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group.
firebase functions:delete groupA
# Bypass the confirmation prompt.
firebase functions:delete myFunction --force

При неявном удалении функций firebase deploy анализирует ваш исходный код и удаляет из производства все функции, которые были удалены из файла.

Изменить имя функции, регион или триггер

Если вы переименовываете или изменяете регионы или триггер для функций, которые обрабатывают производственный трафик, следуйте инструкциям в этом разделе, чтобы избежать потери событий во время модификации. Перед тем, как следовать этим шагам, сначала убедитесь, что ваша функция является идемпотентной , поскольку и новая, и старая версии вашей функции будут работать одновременно во время изменения.

Переименовать функцию

Чтобы переименовать функцию, создайте новую переименованную версию функции в исходном коде, а затем выполните две отдельные команды развертывания. Первая команда развертывает новую названную функцию, а вторая команда удаляет ранее развернутую версию. Например, если у вас есть функция Node.js с именем webhook , которую вы хотите изменить на webhookNew , измените код следующим образом:

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

// after
const functions = require('firebase-functions/v1');

exports.webhookNew = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

Затем выполните следующие команды для развертывания новой функции:

# Deploy new function called webhookNew
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both webhookNew and webhook are running

# Delete webhook
firebase functions:delete webhook

Изменить регион или регионы функции

Если вы изменяете указанные регионы для функции, обрабатывающей производственный трафик, вы можете предотвратить потерю событий, выполнив следующие действия в указанном порядке:

  1. Переименуйте функцию и измените ее область или области по желанию.
  2. Разверните переименованную функцию, что приведет к временному запуску одного и того же кода в обоих наборах регионов.
  3. Удалить предыдущую функцию.

Например, если у вас есть функция с именем webhook , которая в настоящее время находится в регионе функций по умолчанию us-central1 , и вы хотите перенести ее в asia-northeast1 , вам необходимо сначала изменить исходный код, чтобы переименовать функцию и изменить регион.

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

// after
const functions = require('firebase-functions/v1');

exports.webhookAsia = functions
    .region('asia-northeast1')
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

Затем выполните развертывание, выполнив:

firebase deploy --only functions:webhookAsia

Теперь запущены две идентичные функции: webhook работает в us-central1 , а webhookAsia работает в asia-northeast1 .

Затем удалите webhook :

firebase functions:delete webhook

Теперь есть только одна функция - webhookAsia , которая работает в asia-northeast1 .

Изменить тип триггера функции

По мере того, как вы разрабатываете развертывание Cloud Functions for Firebase с течением времени, вам может потребоваться изменить тип триггера функции по разным причинам. Например, вы можете захотеть изменить один тип Firebase Realtime Database или событие Cloud Firestore на другой тип.

Невозможно изменить тип события функции, просто изменив исходный код и запустив firebase deploy . Чтобы избежать ошибок, измените тип триггера функции с помощью этой процедуры:

  1. Измените исходный код, включив новую функцию с желаемым типом триггера.
  2. Разверните функцию, что приведет к временному запуску как старой, так и новой функций.
  3. Явно удалите старую функцию из производства с помощью Firebase CLI.

Например, если у вас есть функция Node.js с именем objectChanged , имеющая устаревший тип события onChange , и вы хотите изменить его на onFinalize , сначала переименуйте функцию и отредактируйте ее так, чтобы она имела тип события onFinalize .

// before
const functions = require('firebase-functions/v1');

exports.objectChanged = functions.storage.object().onChange((object) => {
    return console.log('File name is: ', object.name);
});

// after
const functions = require('firebase-functions/v1');

exports.objectFinalized = functions.storage.object().onFinalize((object) => {
    return console.log('File name is: ', object.name);
});

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

# Create new function objectFinalized
firebase deploy --only functions:objectFinalized

# Wait until deployment is done; now both objectChanged and objectFinalized are running

# Delete objectChanged
firebase functions:delete objectChanged

Установить параметры выполнения

Cloud Functions for Firebase позволяет выбирать параметры среды выполнения, такие как версия среды выполнения Node.js, тайм-аут для каждой функции, выделение памяти и минимальное/максимальное количество экземпляров функций.

В качестве лучшей практики эти параметры (за исключением версии Node.js) следует устанавливать в объекте конфигурации внутри кода функции. Этот объект RuntimeOptions является источником истины для параметров времени выполнения вашей функции и переопределяет параметры, установленные любым другим методом (например, через консоль Google Cloud или gcloud CLI).

Если ваш рабочий процесс разработки включает ручную настройку параметров среды выполнения через консоль Google Cloud или gcloud CLI и вы не хотите, чтобы эти значения переопределялись при каждом развертывании, установите для параметра preserveExternalChanges значение true . Если для этого параметра установлено значение true , Firebase объединяет параметры среды выполнения, заданные в вашем коде, с настройками текущей развернутой версии вашей функции со следующим приоритетом:

  1. В коде функций установлена ​​опция: переопределять внешние изменения.
  2. В коде функций параметру присвоено значение RESET_VALUE : переопределять внешние изменения значением по умолчанию.
  3. Параметр не задан в коде функции, но задан в текущей развернутой функции: используйте параметр, указанный в развернутой функции.

Использование параметра preserveExternalChanges: true не рекомендуется для большинства сценариев, поскольку ваш код больше не будет полным источником истины для параметров времени выполнения для ваших функций. Если вы его используете, проверьте консоль Google Cloud или используйте gcloud CLI для просмотра полной конфигурации функции.

Установить версию Node.js

Firebase SDK для Cloud Functions позволяет выбирать среду выполнения Node.js. Вы можете выбрать запуск всех функций в проекте исключительно в среде выполнения, соответствующей одной из этих поддерживаемых версий Node.js:

  • Node.js 20 (предварительный просмотр)
  • Node.js 18
  • Node.js 16
  • Node.js 14

Чтобы установить версию Node.js:

Вы можете установить версию в поле engines в файле package.json , который был создан в вашем каталоге functions/ во время инициализации. Например, чтобы использовать только версию 18, отредактируйте эту строку в package.json :

  "engines": {"node": "18"}

Если вы используете менеджер пакетов Yarn или у вас есть другие особые требования к области engines , вы можете вместо этого установить среду выполнения для Firebase SDK для Cloud Functions в firebase.json :

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs14, nodejs16 or nodejs20
    }
  }

CLI использует значение, заданное в firebase.json , в качестве приоритета по сравнению с любым значением или диапазоном, которые вы задаете отдельно в package.json .

Обновите среду выполнения Node.js

Чтобы обновить среду выполнения Node.js:

  1. Убедитесь, что ваш проект включен в тарифный план Blaze .
  2. Убедитесь, что вы используете Firebase CLI v11.18.0 или более позднюю версию.
  3. Измените значение engines в файле package.json , который был создан в вашем каталоге functions/ во время инициализации. Например, если вы обновляетесь с версии 16 до версии 18, запись должна выглядеть так: "engines": {"node": "18"}
  4. При желании протестируйте свои изменения с помощью Firebase Local Emulator Suite .
  5. Перераспределить все функции.

Управление поведением масштабирования

По умолчанию Cloud Functions for Firebase масштабирует количество запущенных экземпляров на основе количества входящих запросов, потенциально уменьшая количество экземпляров до нуля в периоды снижения трафика. Однако, если вашему приложению требуется уменьшенная задержка и вы хотите ограничить количество холодных запусков, вы можете изменить это поведение по умолчанию, указав минимальное количество экземпляров контейнера, которые будут поддерживаться в тепле и готовыми обслуживать запросы.

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

Уменьшите количество холодных пусков

Чтобы задать минимальное количество экземпляров для функции в исходном коде, используйте метод runWith . Этот метод принимает объект JSON, соответствующий интерфейсу RuntimeOptions , который определяет значение для minInstances . Например, эта функция устанавливает минимум 5 экземпляров для поддержания тепла:

exports.getAutocompleteResponse = functions
    .runWith({
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    })
    .https.onCall((data, context) => {
      // Autocomplete a user's search term
    });

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

  • Если Cloud Functions for Firebase масштабирует ваше приложение выше установленного вами значения minInstances , вы столкнетесь с холодным запуском для каждого экземпляра, превышающего это пороговое значение.
  • Холодные запуски оказывают наиболее сильное влияние на приложения с резким трафиком. Если у вашего приложения резкий трафик и вы устанавливаете значение minInstances достаточно высоким, чтобы холодные запуски уменьшались при каждом увеличении трафика, вы увидите значительное снижение задержки. Для приложений с постоянным трафиком холодные запуски вряд ли сильно повлияют на производительность.
  • Установка минимального количества экземпляров может иметь смысл для производственных сред, но обычно ее следует избегать в тестовых средах. Чтобы масштабировать до нуля в тестовом проекте, но при этом уменьшить количество холодных запусков в производственном проекте, вы можете установить minInstances на основе переменной среды FIREBASE_CONFIG :

    // Get Firebase project id from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = functions
        .runWith({
          // Keep 5 instances warm for this latency-critical function
          // in production only. Default to 0 for test projects.
          minInstances: envProjectId === "my-production-project" ? 5 : 0,
        })
        .https.onRequest((req, res) => {
          // render some html
        });
    

Ограничить максимальное количество экземпляров функции

Чтобы задать максимальное количество экземпляров в исходном коде функции, используйте метод runWith . Этот метод принимает объект JSON, соответствующий интерфейсу RuntimeOptions , который определяет значения для maxInstances . Например, эта функция устанавливает ограничение в 100 экземпляров, чтобы не перегружать гипотетическую устаревшую базу данных:

exports.mirrorOrdersToLegacyDatabase = functions
    .runWith({
      // Legacy database only supports 100 simultaneous connections
      maxInstances: 100,
    })
    .firestore.document("orders/{orderId}")
    .onWrite((change, context) => {
      // Connect to legacy database
    });

Если функция HTTP масштабируется до предела maxInstances , новые запросы помещаются в очередь на 30 секунд, а затем отклоняются с кодом ответа 429 Too Many Requests если к тому времени ни один экземпляр не будет доступен.

Чтобы узнать больше о передовых методах использования настроек максимального количества экземпляров, ознакомьтесь с этими передовыми методами использования maxInstances .

Установить тайм-аут и выделение памяти

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

Чтобы задать выделение памяти и тайм-аут в исходном коде функций, используйте параметр runWith представленный в Firebase SDK для Cloud Functions 2.0.0. Этот параметр времени выполнения принимает объект JSON, соответствующий интерфейсу RuntimeOptions , который определяет значения для timeoutSeconds и memory . Например, эта функция хранения использует 1 ГБ памяти и тайм-аут через 300 секунд:

exports.convertLargeFile = functions
    .runWith({
      // Ensure the function has enough memory and time
      // to process large files
      timeoutSeconds: 300,
      memory: "1GB",
    })
    .storage.object()
    .onFinalize((object) => {
      // Do some complicated things that take a lot of memory and time
    });

Максимальное значение для timeoutSeconds составляет 540 или 9 минут. Объем памяти, предоставленный функции, соответствует выделенному для функции процессору, как подробно описано в этом списке допустимых значений для memory :

  • 128MB — 200 МГц
  • 256MB — 400 МГц
  • 512MB — 800 МГц
  • 1GB — 1,4 ГГц
  • 2GB — 2,4 ГГц
  • 4GB — 4,8 ГГц
  • 8GB — 4,8 ГГц

Чтобы настроить распределение памяти и тайм-аут в консоли Google Cloud :

  1. В консоли Google Cloud выберите Cloud Functions в левом меню.
  2. Выберите функцию, щелкнув ее название в списке функций.
  3. Нажмите значок «Изменить» в верхнем меню.
  4. Выберите распределение памяти из раскрывающегося меню с надписью Выделенная память .
  5. Нажмите «Дополнительно» , чтобы отобразить дополнительные параметры, и введите количество секунд в текстовом поле «Время ожидания» .
  6. Нажмите «Сохранить» , чтобы обновить функцию.