Confira tudo que foi anunciado no Firebase Summit e veja como usar o Firebase para acelerar o desenvolvimento de apps e executar os aplicativos com confiança. Saiba mais

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.

Escreva funções idempotentes

Suas funções devem produzir o mesmo resultado, mesmo que sejam chamadas várias vezes. Isso permite que você repita 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

A atividade em segundo plano é tudo o que acontece após o término de 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 nas funções orientadas a eventos do Node.js. Qualquer código executado após o encerramento 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. Acessar a rede após o término de uma função geralmente leva à redefinição das conexões (código de erro ECONNRESET ).

Muitas vezes, a atividade em segundo plano pode ser detectada em logs de invocações individuais, encontrando qualquer coisa registrada após a linha informando que a chamada foi concluída. Às vezes, a atividade em segundo plano pode ser mais profunda no código, especialmente quando operações assíncronas, como retornos de chamada ou cronômetros, 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 exclua 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 memória disponível para sua função e, às vezes, persistem entre invocações. Deixar de 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 de memória .

Não tente gravar fora do diretório temporário e certifique-se de usar métodos independentes de plataforma/sistema operacional 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, por isso geralmente é mais rápido testar o código de sua função localmente.

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

Use o Sendgrid para enviar e-mails

O Cloud Functions não permite conexões de saída na porta 25, portanto, você não pode 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 Enviando e-mail de uma instância para o Google Compute Engine.

Desempenho

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

Use as dependências com sabedoria

Como as funções não têm 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 importam 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 dependências corretamente e não carregando 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 Cloud Function será preservado para futuras invocações. No entanto, o Cloud Functions geralmente recicla o ambiente de execução de uma invocação anterior. Se você declarar uma variável em 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 tais 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 API em escopo global. Consulte Otimizando a rede para obter exemplos.

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

Se você inicializar variáveis ​​em 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 tempos limite 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 preguiçosamente 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 preguiçosa, você pode desperdiçar recursos em variáveis ​​que são inicializadas, mas nunca usadas.

Reduza as inicializações 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 pronto para atender às solicitações. Definir um número mínimo de instâncias reduz as inicializações a frio de 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 .