Приложениям, которые в настоящее время используют функции 1-го поколения, следует рассмотреть возможность перехода на 2-е поколение, следуя инструкциям в этом руководстве. Функции 2-го поколения используют Cloud Run для обеспечения лучшей производительности, лучшей конфигурации, лучшего мониторинга и многого другого.
Примеры на этой странице предполагают, что вы используете JavaScript с модулями CommonJS ( require
импорт стилей), но те же принципы применимы к JavaScript с ESM ( import … from
импорта стилей) и TypeScript.
Процесс миграции
Функции 1-го и 2-го поколения могут сосуществовать бок о бок в одном файле. Это позволяет легко переносить по частям, по мере готовности. Мы рекомендуем переносить по одной функции за раз, выполняя тестирование и проверку перед продолжением.
Проверьте версии Firebase CLI и firebase-function
Убедитесь, что вы используете Firebase CLI версии 12.00
и firebase-functions
версии 4.3.0
. Любая более новая версия будет поддерживать как 2-е, так и 1-е поколение.
Обновить импорт
Импорт функций 2-го поколения из подпакета v2
в firebase-functions
SDK. Этот другой путь импорта — все, что нужно Firebase CLI, чтобы определить, следует ли развертывать ваш код функции как функцию 1-го или 2-го поколения.
Подпакет v2
является модульным, и мы рекомендуем импортировать только тот конкретный модуль, который вам нужен.
До: 1-е поколение
const functions = require("firebase-functions/v1");
После: 2-е поколение
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Обновление определений триггеров
Поскольку SDK 2-го поколения отдает предпочтение модульному импорту, обновите определения триггеров, чтобы отразить измененный импорт из предыдущего шага.
Аргументы, передаваемые в обратные вызовы для некоторых триггеров, изменились. Обратите внимание, что в этом примере аргументы обратного вызова onDocumentCreated
были объединены в один объект event
. Кроме того, некоторые триггеры имеют удобные новые функции конфигурации, такие как опция cors
триггера onRequest
.
До: 1-е поколение
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
Использовать параметризованную конфигурацию
Функции 2-го поколения отказываются от поддержки functions.config
в пользу более безопасного интерфейса для декларативного определения параметров конфигурации внутри вашей кодовой базы. С новым модулем params
CLI блокирует развертывание, если все параметры не имеют допустимого значения, гарантируя, что функция не будет развернута с отсутствующей конфигурацией.
Перейти к подпакету params
Если вы использовали конфигурацию среды с помощью functions.config
, вы можете перенести существующую конфигурацию в параметризованную конфигурацию .
До: 1-е поколение
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
const date = new Date();
const formattedDate =
date.toLocaleDateString(functions.config().dateformat);
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");
const dateFormat = defineString("DATE_FORMAT");
exports.date = onRequest((req, res) => {
const date = new Date();
const formattedDate = date.toLocaleDateString(dateFormat.value());
// ...
});
Установить значения параметров
При первом развертывании Firebase CLI запрашивает все значения параметров и сохраняет значения в файле dotenv. Чтобы экспортировать значения functions.config, запустите firebase functions:config:export
.
Для дополнительной безопасности вы также можете указать типы параметров и правила проверки .
Особый случай: API-ключи
Модуль params
интегрируется с Cloud Secret Manager, который обеспечивает детальный контроль доступа к конфиденциальным значениям, таким как ключи API. Для получения дополнительной информации см. секретные параметры .
До: 1-е поколение
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");
// Define the secret parameter
const apiKey = defineSecret("API_KEY");
exports.getQuote = onRequest(
// make the secret available to this function
{ secrets: [apiKey] },
async (req, res) => {
// retrieve the value of the secret
const quote = await fetchMotivationalQuote(apiKey.value());
// ...
}
);
Установить параметры выполнения
Конфигурация параметров среды выполнения изменилась между 1-м и 2-м поколениями. 2-е поколение также добавляет новую возможность задавать параметры для всех функций.
До: 1-е поколение
const functions = require("firebase-functions/v1");
exports.date = functions
.runWith({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
})
// locate function closest to users
.region("asia-northeast1")
.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions
// locate function closest to users and database
.region("asia-northeast1")
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");
// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });
exports.date = onRequest({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
Использовать параллелизм
Значительным преимуществом функций 2-го поколения является способность одного экземпляра функции обслуживать более одного запроса одновременно. Это может значительно сократить количество холодных запусков, с которыми сталкиваются конечные пользователи. По умолчанию параллелизм установлен на 80, но вы можете установить его на любое значение от 1 до 1000:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
Настройка параллелизма может улучшить производительность и снизить стоимость функций. Узнайте больше о параллелизме в разделе Разрешить параллельные запросы .
Аудит использования глобальных переменных
Функции 1-го поколения, написанные без учета параллелизма, могут использовать глобальные переменные, которые устанавливаются и считываются при каждом запросе. Когда параллелизм включен и один экземпляр начинает обрабатывать несколько запросов одновременно, это может привести к ошибкам в вашей функции, поскольку параллельные запросы начинают устанавливать и считывать глобальные переменные одновременно.
При обновлении вы можете установить CPU вашей функции на gcf_gen1
и установить concurrency
на 1, чтобы восстановить поведение 1-го поколения:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
Однако это не рекомендуется в качестве долгосрочного решения, поскольку оно лишает вас преимуществ производительности функций 2-го поколения. Вместо этого проведите аудит использования глобальных переменных в ваших функциях и удалите эти временные настройки, когда будете готовы.
Перевести трафик на новые функции 2-го поколения
Так же, как и при изменении региона функции или типа триггера , вам нужно будет дать функции второго поколения новое имя и постепенно перевести на нее трафик.
Невозможно обновить функцию с 1-го до 2-го поколения с тем же именем и запустить firebase deploy
. Это приведет к ошибке:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Прежде чем выполнять эти шаги, сначала убедитесь, что ваша функция является идемпотентной , поскольку и новая, и старая версии вашей функции будут выполняться одновременно во время изменения. Например, если у вас есть функция 1-го поколения, которая реагирует на события записи в Firestore, убедитесь, что ответ на запись дважды, один раз функцией 1-го поколения и один раз функцией 2-го поколения, в ответ на эти события оставляет ваше приложение в согласованном состоянии.
- Переименуйте функцию в коде функций. Например, переименуйте
resizeImage
вresizeImageSecondGen
. - Разверните функцию так, чтобы работали как исходная функция 1-го поколения, так и функция 2-го поколения.
- В случае вызываемых триггеров, триггеров очереди задач и HTTP начните направлять всех клиентов на функцию 2-го поколения, обновив код клиента именем или URL-адресом функции 2-го поколения.
- Благодаря фоновым триггерам функции как первого, так и второго поколения будут реагировать на каждое событие немедленно после развертывания.
- После переноса всего трафика удалите функцию 1-го поколения с помощью команды firebase CLI
firebase functions:delete
.- При желании переименуйте функцию 2-го поколения, чтобы она соответствовала имени функции 1-го поколения.