Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Dicas e truques

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Este documento descreve as práticas recomendadas para projetar, implementar, testar e implantar o Cloud Functions.

Correção

Esta seção descreve as práticas recomendadas gerais para projetar e implementar o Cloud Functions.

Escrever funções idempotentes

Suas funções devem produzir o mesmo resultado, mesmo que sejam chamadas várias vezes. Isso permite que você tente novamente uma invocação se a invocação anterior falhar no meio do seu código. Para obter mais informações, consulte repetir funções orientadas a eventos .

Não inicie atividades em segundo plano

Atividade em segundo plano é qualquer coisa que acontece após o término da sua função. Uma invocação de função termina quando a função retorna ou sinaliza a conclusão, como chamando o argumento de callback de chamada em funções orientadas a eventos do Node.js. Qualquer código executado após o término normal não pode acessar a CPU e não fará nenhum progresso.

Além disso, quando uma chamada subsequente é executada no mesmo ambiente, sua atividade em segundo plano é retomada, interferindo na nova chamada. Isso pode levar a comportamentos inesperados e erros difíceis de diagnosticar. O acesso à rede após o término de uma função geralmente leva à reinicialização das conexões (código de erro ECONNRESET ).

A atividade em segundo plano geralmente pode ser detectada em logs de invocações individuais, encontrando qualquer coisa que esteja registrada após a linha informando que a invocação foi concluída. A atividade em segundo plano às vezes pode ser enterrada mais profundamente no código, especialmente quando operações assíncronas, como retornos de chamada ou temporizadores, estão presentes. Revise seu código para garantir que todas as operações assíncronas sejam concluídas antes de encerrar a função.

Sempre excluir arquivos temporários

O armazenamento em disco local no diretório temporário é um sistema de arquivos na memória. Os arquivos que você grava consomem a memória disponível para sua função e, às vezes, persistem entre as invocações. A falha em excluir explicitamente esses arquivos pode levar a um erro de falta de memória e a uma inicialização a frio subsequente.

Você pode ver a memória usada por uma função individual selecionando-a na lista de funções no Console do GCP e escolhendo o gráfico de uso da memória .

Não tente gravar fora do diretório temporário e certifique-se de usar métodos independentes de plataforma/SO para construir caminhos de arquivo.

Você pode reduzir os requisitos de memória ao processar arquivos maiores usando pipelining. Por exemplo, você pode processar um arquivo no Cloud Storage criando um stream de leitura, passando-o por um processo baseado em stream e gravando o stream de saída diretamente no Cloud Storage.

Ferramentas

Esta seção fornece diretrizes sobre como usar ferramentas para implementar, testar e interagir com o Cloud Functions.

Desenvolvimento local

A implantação da função leva um pouco de tempo, portanto, geralmente é mais rápido testar o código da sua função localmente.

Os desenvolvedores do Firebase podem usar o Firebase CLI Cloud Functions Emulator .

Use Sendgrid para enviar e-mails

O Cloud Functions não permite conexões de saída na porta 25, portanto, não é possível fazer conexões não seguras com um servidor SMTP. A maneira recomendada de enviar e-mails é usar o SendGrid . Você pode encontrar outras opções para enviar e-mail no tutorial Enviar e-mail de uma instância para o Google Compute Engine.

atuação

Esta seção descreve as melhores práticas para otimizar o desempenho.

Use as dependências com sabedoria

Como as funções são sem estado, o ambiente de execução geralmente é inicializado do zero (durante o que é conhecido como inicialização a frio ). Quando ocorre uma inicialização a frio, o contexto global da função é avaliado.

Se suas funções importarem módulos, o tempo de carregamento desses módulos pode aumentar a latência de invocação durante uma inicialização a frio. Você pode reduzir essa latência, bem como o tempo necessário para implantar sua função, carregando as dependências corretamente e não carregando as dependências que sua função não usa.

Use variáveis ​​globais para reutilizar objetos em invocações futuras

Não há garantia de que o estado de uma Função do Cloud será preservado para invocações futuras. No entanto, o Cloud Functions geralmente recicla o ambiente de execução de uma invocação anterior. Se você declarar uma variável no escopo global, seu valor poderá ser reutilizado em invocações subsequentes sem precisar ser recalculado.

Dessa forma, você pode armazenar em cache objetos que podem ser caros para recriar em cada chamada de função. Mover esses objetos do corpo da função para o escopo global pode resultar em melhorias significativas de desempenho. O exemplo a seguir cria um objeto pesado apenas uma vez por instância de função e o compartilha em todas as invocações de função que atingem a instância especificada:

console.log('Global scope');
const perInstance = heavyComputation();
const functions = require('firebase-functions');

exports.function = functions.https.onRequest((req, res) => {
    console.log('Function invocation');
    const perFunction = lightweightComputation();

    res.send(`Per instance: ${perInstance}, per function: ${perFunction}`);
});

É particularmente importante armazenar em cache conexões de rede, referências de biblioteca e objetos de cliente de API no escopo global. Consulte Otimizando a rede para obter exemplos.

Faça a inicialização preguiçosa de variáveis ​​globais

Se você inicializar variáveis ​​no escopo global, o código de inicialização sempre será executado por meio de uma chamada de inicialização a frio, aumentando a latência de sua função. Em certos casos, isso causa timeouts intermitentes para os serviços que estão sendo chamados se eles não forem tratados adequadamente em um bloco try / catch . Se alguns objetos não forem usados ​​em todos os caminhos de código, considere inicializá-los lentamente sob demanda:

const functions = require('firebase-functions');
let myCostlyVariable;

exports.function = functions.https.onRequest((req, res) => {
    doUsualWork();
    if(unlikelyCondition()){
        myCostlyVariable = myCostlyVariable || buildCostlyVariable();
    }
    res.status(200).send('OK');
});

Isso é particularmente importante se você definir várias funções em um único arquivo e funções diferentes usarem variáveis ​​diferentes. A menos que você use inicialização lenta, você pode desperdiçar recursos em variáveis ​​que são inicializadas, mas nunca usadas.

Reduza as partidas a frio definindo um número mínimo de instâncias

Por padrão, o Cloud Functions dimensiona o número de instâncias com base no número de solicitações recebidas. Você pode alterar esse comportamento padrão definindo um número mínimo de instâncias que o Cloud Functions deve manter prontas para atender às solicitações. Definir um número mínimo de instâncias reduz as partidas a frio do seu aplicativo. Recomendamos definir um número mínimo de instâncias se seu aplicativo for sensível à latência.

Consulte Controlar o comportamento de dimensionamento para obter mais informações sobre essas opções de tempo de execução.

Recursos adicionais

Saiba mais sobre como otimizar o desempenho no vídeo "Google Cloud Performance Atlas" Cloud Functions Cold Boot Time .