Gerenciar funções

Você pode implantar, excluir e modificar funções usando comandos da Firebase CLI ou definindo opções de tempo de execução no código-fonte de suas funções.

Implantar funções

Para implantar funções, execute este comando da Firebase CLI:

$ firebase deploy --only functions

Por padrão, a Firebase CLI implanta todas as funções dentro do index.js ao mesmo tempo. Se o seu projeto contiver mais de 5 funções, recomendamos que você use o sinalizador --only com nomes de função específicos para implantar apenas as funções que você editou. A implantação de funções específicas dessa forma acelera o processo de implantação e ajuda a evitar o esgotamento das cotas de implantação. Por exemplo:

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

Ao implantar um grande número de funções, você pode exceder a cota padrão e receber mensagens de erro HTTP 429 ou 500. Para resolver isso, implante funções em grupos de 10 ou menos.

Consulte a referência da Firebase CLI para obter a lista completa de comandos disponíveis.

Por padrão, a Firebase CLI procura o código-fonte na pasta functions/ . Se preferir, você pode organizar funções em bases de código ou vários conjuntos de arquivos.

Excluir funções

Você pode excluir funções implantadas anteriormente das seguintes maneiras:

  • explicitamente na Firebase CLI com functions:delete
  • explicitamente usando o menu de contexto na lista de funções no console do Firebase
  • implicitamente removendo a função do index.js antes da implantação.

Todas as operações de exclusão solicitam que você confirme antes de remover a função da produção.

A exclusão explícita de função na Firebase CLI oferece suporte a vários argumentos, bem como a grupos de funções, e permite que você especifique uma função em execução em uma região específica. Além disso, você pode substituir o prompt de confirmação.

# 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

Com a exclusão de função implícita, firebase deploy analisa index.js e remove da produção todas as funções que foram removidas do arquivo.

Modificar o nome, região ou gatilho de uma função

Se você estiver renomeando ou alterando as regiões ou acionadores para funções que manipulam o tráfego de produção, siga as etapas nesta seção para evitar a perda de eventos durante a modificação. Antes de seguir essas etapas, primeiro certifique-se de que sua função seja idempotente , pois a nova versão e a versão antiga de sua função serão executadas ao mesmo tempo durante a alteração.

Renomear uma função

Para renomear uma função, crie uma nova versão renomeada da função em index.js e execute dois comandos de implantação separados. O primeiro comando implanta a função recém-nomeada e o segundo comando remove a versão implantada anteriormente. Por exemplo, se você tiver uma função chamada webhook que gostaria de alterar para webhookNew , revise o código da seguinte maneira:

// before
const {onRequest} = require('firebase-functions/v2/https');

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

// after
const {onRequest} = require('firebase-functions/v2/https');

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

Em seguida, execute os seguintes comandos para implantar a nova função:

# 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

Alterar a região ou regiões de uma função

Se você estiver alterando as regiões especificadas para uma função que está processando o tráfego de produção, poderá evitar a perda de eventos executando estas etapas na ordem:

  1. Renomeie a função e altere sua região ou regiões conforme desejado.
  2. Implante a função renomeada, que resulta na execução temporária do mesmo código em ambos os conjuntos de regiões.
  3. Exclua a função anterior.

Por exemplo, se você tem uma função chamada webhook que está atualmente na região de funções padrão de us-central1 e deseja migrá-la para asia-northeast1 , primeiro você precisa modificar seu código-fonte para renomear a função e revisar a região .

// before
const {onRequest} = require('firebase-functions/v2/https');

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

// after
const {onRequest} = require('firebase-functions/v2/https');

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

Em seguida, implante executando:

$ firebase deploy --only functions:webhookAsia

Agora há duas funções idênticas em execução: webhook está sendo executado em us-central1 e webhookasia está sendo executado em asia-northeast1 .

Em seguida, exclua webhook :

$ firebase functions:delete webhook

Agora há apenas uma função - webhookasia , que está sendo executada em asia-northeast1 .

Alterar o tipo de gatilho de uma função

À medida que você desenvolve sua implantação do Cloud Functions para Firebase ao longo do tempo, pode ser necessário alterar o tipo de acionador de uma função por vários motivos. Por exemplo, você pode querer:

  • Altere do evento onChange de armazenamento herdado para onFinalize , onDelete , onArchive e onMetadataUpdate . (Saiba mais sobre isso no guia de atualização beta para v1 ou v2 ).
  • Mude de um tipo de evento do Firebase Realtime Database ou Cloud Firestore para outro, como o evento onWrite genérico para o evento onCreate granular.

Não é possível alterar o tipo de evento de uma função apenas alterando o código-fonte e executando firebase deploy . Para evitar erros, altere o tipo de gatilho de uma função por este procedimento:

  1. Modifique o código-fonte para incluir uma nova função com o tipo de gatilho desejado.
  2. Implante a função, o que resulta na execução temporária das funções antigas e novas.
  3. Exclua explicitamente a função antiga da produção usando a Firebase CLI.

Por exemplo, se você teve uma função objectchanged que tem o tipo de evento onMetadataUpdated legado e gostaria de alterá-lo para onObjectFinalized , primeiro renomeie a função e edite-a para ter o tipo de evento onObjectFinalized .

// before
const {onMetadataUpdated} = require('firebase-functions/v2/storage');

exports.objectchanged = onMetadataUpdated((event) => {
    return console.log('File name is: ', event.data.name);
});

// after
const {onObjectFinalized} = require('firebase-functions/v2/storage');

exports.objectchanged = onObjectFinalized((event) => {
    return console.log('File name is: ', event.data.name);
});

Em seguida, execute os seguintes comandos para criar a nova função primeiro, antes de excluir a função antiga:

# 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

Definir opções de tempo de execução

O Cloud Functions para Firebase permite selecionar opções de tempo de execução, como a versão de tempo de execução do Node.js e o tempo limite por função, alocação de memória e instâncias de função mínima/máxima.

Definir a versão do Node.js

O SDK do Firebase para Cloud Functions v2 permite uma seleção de tempo de execução do Node.js. Você pode optar por executar todas as funções em um projeto exclusivamente no ambiente de tempo de execução correspondente a uma destas versões compatíveis do Node.js:

  • Node.js 16
  • Node.js 14
  • Node.js 12
  • Node.js 10

Para definir a versão do Node.js:

Configure a versão no campo engines no arquivo package.json que foi criado em seu diretório functions/ durante a inicialização. Por exemplo, para usar apenas a versão 16, edite esta linha em package.json :

  "engines": {"node": "16"}

O campo engines é obrigatório; ele deve especificar uma das versões compatíveis do Node.js para que você implante e execute funções. Atualmente, firebase init functions definem esse campo como 16 .

Atualize seu ambiente de execução do Node.js

Para fazer upgrade do ambiente de execução do Node.js:

  1. Certifique-se de que seu projeto esteja no plano de preços Blaze .
  2. Verifique se você está usando o Firebase CLI v9.17.0 ou posterior.
  3. Altere o valor dos engines no arquivo package.json que foi criado em seu diretório functions/ durante a inicialização. Por exemplo, se você estiver atualizando da versão 10 para a versão 16, a entrada deve ter esta aparência: "engines": {"node": "16"}
  4. Reimplante funções usando a Firebase CLI v9.17.0 ou posterior.

Comportamento de dimensionamento de controle

Por padrão, o Cloud Functions para Firebase dimensiona o número de instâncias em execução com base no número de solicitações recebidas, possivelmente reduzindo para zero instâncias em tempos de tráfego reduzido. No entanto, se seu aplicativo exigir latência reduzida e você quiser limitar o número de inicializações a frio, poderá alterar esse comportamento padrão especificando um número mínimo de instâncias de contêiner a serem mantidas aquecidas e prontas para atender às solicitações.

Da mesma forma, você pode definir um número máximo para limitar o dimensionamento de instâncias em resposta a solicitações recebidas. Use essa configuração como forma de controlar seus custos ou limitar o número de conexões a um serviço de apoio, como um banco de dados.

Usando essas configurações junto com a configuração de simultaneidade por instância (nova na v2), você pode controlar e ajustar o comportamento de dimensionamento de suas funções. A natureza de seu aplicativo e função determinará quais configurações são mais econômicas e resultarão no melhor desempenho.

Para alguns aplicativos com baixo tráfego, uma opção de CPU mais baixa sem multi-simultaneidade é a ideal. Para outros em que as partidas a frio são um problema crítico, definir alta simultaneidade e instâncias mínimas significa que um conjunto de instâncias sempre é mantido aquecido para lidar com grandes picos de tráfego.

Para aplicativos de menor escala que recebem muito pouco tráfego, definir instâncias máximas baixas com alta simultaneidade significa que o aplicativo pode lidar com picos de tráfego sem incorrer em custos excessivos.

Permitir solicitações simultâneas

No Cloud Functions para Firebase v1, cada instância pode processar uma solicitação por vez, portanto, o comportamento de escalonamento foi definido apenas com as configurações de minInstances e maxInstances . Além de controlar o número de instâncias, no Cloud Functions para Firebase v2 você pode controlar o número de solicitações que cada instância pode atender ao mesmo tempo com a opção de concurrency . O valor padrão para simultaneidade é 80, mas você pode defini-lo como qualquer número inteiro entre 1 e 1000.

Funções com configurações de simultaneidade mais altas podem absorver picos de tráfego sem inicialização a frio porque cada instância provavelmente tem algum espaço livre. Se uma instância estiver configurada para lidar com até 50 solicitações simultâneas, mas no momento estiver processando apenas 25, ela poderá lidar com um pico de 25 solicitações adicionais sem exigir que uma nova instância seja inicializada a frio. Por outro lado, com uma configuração de simultaneidade de apenas 1, esse pico nas solicitações pode levar a 25 partidas a frio.

Ao experimentar configurações de simultaneidade mais altas no Cloud Functions para Firebase v2, lembre-se do seguinte:

  • Configurações de simultaneidade mais altas podem exigir CPU e RAM mais altas para desempenho ideal até atingir um limite prático. Uma função que faz processamento pesado de imagem ou vídeo, por exemplo, pode não ter recursos para lidar com 1.000 solicitações simultâneas, mesmo quando suas configurações de CPU e RAM estão maximizadas.
  • Como o Cloud Functions para Firebase v2 é desenvolvido pelo Cloud Run, você também pode consultar as orientações do Google Cloud para otimizar a simultaneidade .
  • Certifique-se de testar completamente a multiconcorrência em um ambiente de teste antes de mudar para multiconcorrência na produção.

Reduza o número de partidas a frio

Para definir o número mínimo de instâncias de uma função no código-fonte, use a opção minInstances . Por exemplo, esta função define um mínimo de 5 instâncias para manter quente:

  const { onCall } = require("firebase-functions/v2/https");

  exports.getAutocompleteResponse = onCall(
    {
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    },
    (event) => {
      // Autocomplete user’s search term
    }
  );

Aqui estão algumas coisas a serem consideradas ao definir um valor para minInstances :

  • Se o Cloud Functions para Firebase dimensionar seu aplicativo acima da configuração de minInstances , você experimentará uma inicialização a frio para cada instância acima desse limite.
  • As partidas a frio têm o efeito mais severo em aplicativos com tráfego intenso. Se seu aplicativo tiver tráfego intenso e você definir um valor de minInstances alto o suficiente para que as partidas a frio sejam reduzidas a cada aumento de tráfego, você verá uma latência significativamente reduzida. Para aplicativos com tráfego constante, as partidas a frio provavelmente não afetarão gravemente o desempenho.
  • Definir instâncias mínimas pode fazer sentido para ambientes de produção, mas geralmente deve ser evitado em ambientes de teste. Para escalar para zero em seu projeto de teste, mas ainda reduzir as partidas a frio em seu projeto de produção, você pode definir minInstances com base na variável de ambiente FIREBASE_CONFIG :

    // Get Firebase project ID from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = onRequest(
      {
        // 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,
      },
      (req, res) => {
        // render some html
      }
    );
    

Limitar o número máximo de instâncias para uma função

Para definir o máximo de instâncias no código-fonte da função, use a opção maxInstances . Por exemplo, esta função define um limite de 100 instâncias para não sobrecarregar um banco de dados legado hipotético:

  const { onMessagePublished } = require("firebase-functions/v2/pubsub");

  exports.mirrorevents = onMessagePublished(
    { topic: "topic-name", maxInstances: 100 },
    (event) => {
      // Connect to legacy database
    }
  );

Se uma função HTTP for dimensionada até o limite maxInstances , novas solicitações serão enfileiradas por 30 segundos e, em seguida, rejeitadas com um código de resposta de 429 Too Many Requests se nenhuma instância estiver disponível até então.

Para saber mais sobre as práticas recomendadas para usar as configurações de instâncias máximas, confira estas práticas recomendadas para usar maxInstances .

Definir tempo limite e alocação de memória

Em alguns casos, suas funções podem ter requisitos especiais para um valor de tempo limite longo ou uma grande alocação de memória. Você pode definir esses valores no Console do Google Cloud ou no código-fonte da função (somente Firebase).

Para definir a alocação de memória e o tempo limite no código-fonte das funções, use o parâmetro options para personalizar a máquina virtual que executa suas funções. Essa opção de tempo de execução aceita um objeto JSON em conformidade com a interface RuntimeOptions . Por exemplo, esta função do Cloud Storage usa 1 GiB de memória e atinge o tempo limite após 300 segundos:

  exports.convertLargeFile = onObjectFinalized({
    timeoutSeconds: 300,
    memory: "1GiB",
  }, (event) => {
    // Do some complicated things that take a lot of memory and time
  });

O valor máximo para timeoutSeconds é 540 ou 9 minutos.

Para definir a alocação de memória e o tempo limite no Console do Google Cloud:

  1. No Console do Google Cloud, selecione Cloud Functions para Firebase no menu à esquerda.
  2. Selecione uma função clicando em seu nome na lista de funções.
  3. Clique no ícone Editar no menu superior.
  4. Selecione uma alocação de memória no menu suspenso denominado Memória alocada .
  5. Clique em Mais para exibir as opções avançadas e insira um número de segundos na caixa de texto Tempo limite .
  6. Clique em Salvar para atualizar a função.

Substituir os padrões da CPU

Até 2 GB de memória alocada, cada função no Cloud Functions para Firebase v2 assume como padrão uma CPU e aumenta para 2 CPUs para 4 e 8 GB. Observe que isso é significativamente diferente do comportamento padrão da v1 de maneiras que podem levar a custos um pouco mais altos para funções de pouca memória, conforme expresso na tabela a seguir:

RAM alocada CPU padrão da versão 1 (fracionária) CPU padrão da versão 2 Aumento de preço por ms
128 MB 1/12 1 10,5x
256 MB 1/6 1 5,3x
512 MB 1/3 1 2,7x
1 GB 12/07 1 1,6x
2 GB 1 1 1x
4GB 2 2 1x
8 GB 2 2 1x
16 GB n / D 4 n / D

Se você preferir preservar o comportamento da v1 para suas funções da v2, defina os padrões da v1 como uma opção global:

// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcfv1' });

Para funções com uso intensivo de CPU, a v2 oferece flexibilidade para configurar CPU adicional. Você pode aumentar a CPU por função, conforme mostrado:

// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
  // computer vision goes here
});