Ambiente de execução do Cloud Functions

As funções do Cloud Run são executadas num ambiente sem servidor totalmente gerido onde a Google trata da infraestrutura, dos sistemas operativos e dos ambientes de tempo de execução. Cada função é executada no seu próprio contexto de execução seguro isolado, é dimensionada automaticamente e tem um ciclo de vida independente de outras funções.

Tempos de execução

As funções do Cloud Run suportam vários tempos de execução de idiomas. Cada um contém um conjunto padrão de pacotes do sistema, bem como as ferramentas e as bibliotecas necessárias para esse idioma. Precisa do valor do ID de tempo de execução se estiver a implementar funções a partir da linha de comandos ou através do Terraform.

As atualizações de segurança e manutenção são disponibilizadas a todos os ambientes de execução de 1.ª e 2.ª geração. Estas atualizações são aplicadas automaticamente ou manualmente, consoante o ambiente e a forma como o configurou. Para mais informações acerca das atualizações do ambiente de execução, consulte o artigo Proteja a sua função do Cloud Run.

Node.js

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
Node.js 24
(apenas pré-visualização)
2.ª geração Ubuntu 24.04 nodejs24 us-central1-docker.pkg.dev/serverless-runtimes/google-24-full/runtimes/nodejs24
Node.js 22 2.ª geração Ubuntu 22.04 nodejs22 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js 20 1.ª geração, 2.ª geração Ubuntu 22.04 nodejs20 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs20
Node.js 18 1.ª geração, 2.ª geração Ubuntu 22.04 nodejs18 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs18
Node.js 16 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs16 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs16
Node.js 14 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs14 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs14
Node.js 12 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs12 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs12
Node.js 10 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs10 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs10
Node.js 8 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs8 Desativado
Node.js 6 1.ª geração, 2.ª geração Ubuntu 18.04 nodejs6 Desativado

Python

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
Python 3.13 2.ª geração Ubuntu 22.04 python313 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python313
Python 3.12 1.ª geração, 2.ª geração Ubuntu 22.04 python312 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312
Python 3.11 1.ª geração, 2.ª geração Ubuntu 22.04 python311 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311
Python 3.10 1.ª geração, 2.ª geração Ubuntu 22.04 python310 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310
Python 3.9 1.ª geração, 2.ª geração Ubuntu 18.04 python39 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39
Python 3.8 1.ª geração, 2.ª geração Ubuntu 18.04 python38 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38
Python 3.7 1.ª geração Ubuntu 18.04 python37 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37

Go

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
Go 1.25 2.ª geração Ubuntu 22.04 go125 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go125
Go 1.24 2.ª geração Ubuntu 22.04 go124 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go124
Go 1.23 2.ª geração Ubuntu 22.04 go123 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go123
Go 1.22 2.ª geração Ubuntu 22.04 go122 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go122
Go 1.21 1.ª geração, 2.ª geração Ubuntu 22.04 go121 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go121
Go 1.20 1.ª geração, 2.ª geração Ubuntu 22.04 go120 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go120
Go 1.19 1.ª geração, 2.ª geração Ubuntu 22.04 go119 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go119
Go 1.18 1.ª geração, 2.ª geração Ubuntu 22.04 go118 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go118
Go 1.16 1.ª geração, 2.ª geração Ubuntu 18.04 go116 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go116
Go 1.13 1.ª geração, 2.ª geração Ubuntu 18.04 go113 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go113
Go 1.11 1.ª geração, 2.ª geração Ubuntu 18.04 go111 Desativado

Java

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
Java 21 2.ª geração Ubuntu 22.04 java21 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21
Java 17 1.ª geração, 2.ª geração Ubuntu 22.04 java17 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17
Java 11 1.ª geração, 2.ª geração Ubuntu 18.04 java11 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11

Ruby

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
Ruby 3.4 2.ª geração Ubuntu 22.04 ruby34 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby34
Ruby 3.3 1.ª geração, 2.ª geração Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby33
Ruby 3.2 1.ª geração, 2.ª geração Ubuntu 22.04 ruby32 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.0 1.ª geração, 2.ª geração Ubuntu 18.04 ruby30 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30
Ruby 2.7 1.ª geração, 2.ª geração Ubuntu 18.04 ruby27 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27
Ruby 2.6 1.ª geração, 2.ª geração Ubuntu 18.04 ruby26 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26

PHP

Tempo de execução Ambiente Geração ID do ambiente de execução Imagem do tempo de execução
PHP 8.4 2.ª geração Ubuntu 22.04 php84 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php84
PHP 8.3 2.ª geração Ubuntu 22.04 php83 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83
PHP 8.2 1.ª geração, 2.ª geração Ubuntu 22.04 php82 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82
PHP 8.1 1.ª geração, 2.ª geração Ubuntu 18.04 php81 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81
PHP 7.4 1.ª geração, 2.ª geração Ubuntu 18.04 php74 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74

.NET Core

Tempo de execução Geração Ambiente ID do ambiente de execução Imagem do tempo de execução
.NET Core 8 2.ª geração Ubuntu 22.04 dotnet8 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8
.NET Core 6 1.ª geração, 2.ª geração Ubuntu 22.04 dotnet6 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6
.NET Core 3 1.ª geração, 2.ª geração Ubuntu 18.04 dotnet3 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3

Comportamento da escala automática

As funções do Cloud Run implementam o paradigma sem servidor, no qual executa o seu código sem se preocupar com a infraestrutura subjacente, como servidores ou máquinas virtuais. Após a implementação, as suas funções são geridas e dimensionadas automaticamente.

As funções do Cloud Run processam os pedidos recebidos atribuindo-os a instâncias da sua função. Consoante o volume de pedidos, bem como o número de instâncias de funções existentes, as funções do Cloud Run podem atribuir um pedido a uma instância existente ou criar uma nova.

Nos casos em que o volume de pedidos recebidos excede o número de instâncias existentes, as funções do Cloud Run podem iniciar várias novas instâncias para processar pedidos. Este comportamento de escalabilidade automática permite que as funções do Cloud Run processem muitos pedidos em paralelo, cada um usando uma instância diferente da sua função.

Em alguns casos, o aumento ilimitado pode ser indesejável. Para resolver este problema, as funções do Cloud Run permitem-lhe configurar um número máximo de instâncias que podem coexistir em qualquer altura para uma função específica.

Apátrida

Para ativar a gestão e o dimensionamento automáticos das suas funções, as funções têm de ser sem estado: uma invocação de função não pode depender do estado na memória definido por uma invocação anterior. As invocações podem ser processadas por diferentes instâncias de funções, que não partilham variáveis globais, memória, sistemas de ficheiros nem outro estado.

Se precisar de partilhar o estado entre invocações de funções, a sua função deve usar um serviço como o Memorystore, Datastore, Firestore ou Cloud Storage para persistir os dados. Consulte as Google Cloud bases de dados e os Google Cloud produtos de armazenamento para mais informações sobre as opções de bases de dados e armazenamento fornecidas pela Google Cloud.

Simultaneidade

Funções do Cloud Run (2.ª geração)

As funções do Cloud Run (2.ª geração) suportam o processamento de vários pedidos simultâneos numa instância de função única. Isto pode ser útil para evitar inícios a frio, uma vez que uma instância já aquecida pode processar vários pedidos em simultâneo, reduzindo assim a latência geral. Para obter detalhes, consulte a secção Concorrência.

Funções do Cloud Run (1.ª geração)

Nas funções do Cloud Run (1.ª geração), cada instância de uma função processa apenas um pedido concorrente de cada vez. Isto significa que, enquanto o seu código está a processar um pedido, não existe a possibilidade de um segundo pedido ser encaminhado para a mesma instância. Assim, o pedido original pode usar a quantidade total de recursos (memória e CPU) que atribui.

Uma vez que os pedidos simultâneos nas funções do Cloud Run (1.ª geração) são processados por instâncias de funções diferentes, não partilham variáveis nem memória local. Consulte os artigos Sem estado e Tempo de vida da instância da função para mais informações.

Inícios a frio

Uma nova instância de função é iniciada em dois casos:

  • Quando implementa a sua função.

  • Quando é criada automaticamente uma nova instância de função para aumentar a escala de acordo com a carga ou, ocasionalmente, para substituir uma instância existente.

O início de uma nova instância de função envolve o carregamento do tempo de execução e do seu código. Os pedidos que incluem o arranque da instância da função, denominado arranque a frio, podem ser mais lentos do que os pedidos encaminhados para instâncias de funções existentes. No entanto, se a sua função receber uma carga constante, o número de inícios a frio é normalmente insignificante, a menos que a função falhe frequentemente e exija o reinício do ambiente de funções.

Se o código da função gerar uma exceção não capturada ou falhar no processo atual, a instância da função pode ser reiniciada. Isto pode levar a inícios a frio, o que resulta numa latência mais elevada. Por isso, recomendamos que intercete exceções e, caso contrário, evite a terminação do processo atual.

Se a sua função for sensível à latência, considere definir um número mínimo de instâncias para evitar inícios a frio.

Tempo de vida da instância da função

Normalmente, as instâncias de funções são resilientes e reutilizadas por invocações de funções subsequentes, a menos que o número de instâncias esteja a ser reduzido devido à falta de tráfego contínuo ou a sua função falhe. Isto significa que, quando a execução de uma função termina, outra invocação de função pode ser processada pela mesma instância de função.

Âmbito da função versus âmbito global

Uma única invocação de função resulta na execução apenas do corpo da função declarada como o ponto de entrada. O âmbito global do código fonte da sua função só é executado em inícios a frio e não em instâncias que já foram inicializadas.

Node.js

const functions = require('@google-cloud/functions-framework');

// TODO(developer): Define your own computations
const {lightComputation, heavyComputation} = require('./computations');

// Global (instance-wide) scope
// This computation runs once (at instance cold-start)
const instanceVar = heavyComputation();

/**
 * HTTP function that declares a variable.
 *
 * @param {Object} req request context.
 * @param {Object} res response context.
 */
functions.http('scopeDemo', (req, res) => {
  // Per-function scope
  // This computation runs every time this function is called
  const functionVar = lightComputation();

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

Python

import time

import functions_framework


# Placeholder
def heavy_computation():
    return time.time()


# Placeholder
def light_computation():
    return time.time()


# Global (instance-wide) scope
# This computation runs at instance cold-start
instance_var = heavy_computation()


@functions_framework.http
def scope_demo(request):
    """
    HTTP Cloud Function that declares a variable.
    Args:
        request (flask.Request): The request object.
        <http://flask.pocoo.org/docs/1.0/api/#flask.Request>
    Returns:
        The response text, or any set of values that can be turned into a
        Response object using `make_response`
        <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>.
    """

    # Per-function scope
    # This computation runs every time this function is called
    function_var = light_computation()
    return f"Instance: {instance_var}; function: {function_var}"

Go


// h is in the global (instance-wide) scope.
var h string

// init runs during package initialization. So, this will only run during an
// an instance's cold start.
func init() {
	h = heavyComputation()
	functions.HTTP("ScopeDemo", ScopeDemo)
}

// ScopeDemo is an example of using globally and locally
// scoped variables in a function.
func ScopeDemo(w http.ResponseWriter, r *http.Request) {
	l := lightComputation()
	fmt.Fprintf(w, "Global: %q, Local: %q", h, l)
}

Java


import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

public class Scopes implements HttpFunction {
  // Global (instance-wide) scope
  // This computation runs at instance cold-start.
  // Warning: Class variables used in functions code must be thread-safe.
  private static final int INSTANCE_VAR = heavyComputation();

  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException {
    // Per-function scope
    // This computation runs every time this function is called
    int functionVar = lightComputation();

    var writer = new PrintWriter(response.getWriter());
    writer.printf("Instance: %s; function: %s", INSTANCE_VAR, functionVar);
  }

  private static int lightComputation() {
    int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    return Arrays.stream(numbers).sum();
  }

  private static int heavyComputation() {
    int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    return Arrays.stream(numbers).reduce((t, x) -> t * x).getAsInt();
  }
}

Ruby

# Global (instance-wide) scope.
# This block runs on cold start, before any function is invoked.
#
# Note: It is usually best to run global initialization in an on_startup block
# instead at the top level of the Ruby file. This is because top-level code
# could be executed to verify the function during deployment, whereas an
# on_startup block is run only when an actual function instance is starting up.
FunctionsFramework.on_startup do
  instance_data = perform_heavy_computation

  # To pass data into function invocations, the best practice is to set a
  # key-value pair using the Ruby Function Framework's built-in "set_global"
  # method. Functions can call the "global" method to retrieve the data by key.
  # (You can also use Ruby global variables or "toplevel" local variables, but
  # they can make it difficult to isolate global data for testing.)
  set_global :my_instance_data, instance_data
end

FunctionsFramework.http "tips_scopes" do |_request|
  # Per-function scope.
  # This method is called every time this function is called.
  invocation_data = perform_light_computation

  # Retrieve the data computed by the on_startup block.
  instance_data = global :my_instance_data

  "instance: #{instance_data}; function: #{invocation_data}"
end

Pode usar variáveis globais como uma otimização do desempenho, mas não deve confiar no estado definido no âmbito global por invocações de funções anteriores. Consulte a secção Sem estado para mais informações.

Pode assumir que, para cada instância de função, o âmbito global foi executado exatamente uma vez antes de o código da função ser invocado. No entanto, não deve depender do número total nem do momento das execuções de âmbito global, uma vez que podem variar consoante a atividade de dimensionamento automático.

Linha cronológica da execução da função

Uma função tem acesso aos respetivos recursos atribuídos (memória e CPU) apenas durante a execução da função. Não é garantida a execução de código fora do período de execução, e este pode ser interrompido em qualquer altura. Por conseguinte, deve sempre sinalizar corretamente o fim da execução da função e evitar executar código para além da mesma. Consulte as funções HTTP, funções em segundo plano e funções CloudEvent para ver orientações.

A execução da função também está sujeita à duração do tempo limite da função. Consulte a secção Limite de tempo de processamento da função para mais informações.

Tenha em conta a cronologia de execução ao inicializar a sua aplicação. Não devem ser criadas tarefas em segundo plano no âmbito global durante a inicialização, uma vez que seriam executadas fora da duração de um pedido.

Garantias de execução

Normalmente, as suas funções são invocadas uma vez para cada evento recebido. No entanto, as funções do Cloud Run não garantem uma única invocação em todos os casos devido a diferenças nos cenários de erro.

O número máximo ou mínimo de vezes que a sua função pode ser invocada para um único evento depende do tipo de função:

  • As funções HTTP são invocadas, na maioria, uma vez. Isto deve-se à natureza síncrona das chamadas HTTP e significa que qualquer erro que ocorra durante a invocação da função é devolvido sem novas tentativas. O autor da chamada de uma função HTTP deve processar os erros e repetir a operação, se necessário.

  • As funções acionadas por eventos são invocadas, pelo menos, uma vez. Isto deve-se à natureza assíncrona dos eventos, em que não existe nenhum autor da chamada que aguarde a resposta. Em circunstâncias raras, o sistema pode invocar uma função acionada por eventos mais do que uma vez para garantir a entrega do evento. Se uma invocação de função baseada em eventos falhar com um erro, a função não é invocada novamente, a menos que as tentativas em caso de falha estejam ativadas para essa função.

Para se certificar de que a sua função se comporta corretamente em tentativas de execução repetidas, deve torná-la idempotente, implementando-a de modo que os resultados desejados (e os efeitos secundários) sejam produzidos mesmo que um evento seja enviado várias vezes. No caso das funções HTTP, isto também significa devolver o valor pretendido, mesmo que o autor da chamada volte a tentar chamar o ponto final da função HTTP. Consulte o artigo Voltar a tentar funções acionadas por eventos para mais informações sobre como tornar a sua função idempotente.

Memória e sistema de ficheiros

Cada função tem uma determinada quantidade de memória alocada para a sua utilização. Pode configurar a quantidade de memória na implementação. Consulte o artigo Configurar memória para mais informações.

O ambiente de execução da função inclui um sistema de ficheiros na memória que contém os ficheiros de origem e os diretórios implementados com a sua função (consulte a secção Estruturar o código-fonte). O diretório que contém os ficheiros de origem é apenas de leitura, mas o resto do sistema de ficheiros é gravável (exceto os ficheiros usados pelo sistema operativo). A utilização do sistema de ficheiros conta para a utilização de memória de uma função.

A sua função pode interagir com o sistema de ficheiros através de métodos padrão em cada linguagem de programação.

Rede

A sua função pode aceder à Internet pública através de métodos padrão em cada linguagem de programação, quer através de bibliotecas incorporadas oferecidas pelo tempo de execução ou bibliotecas de terceiros que inclui como dependências.

Tente reutilizar as ligações de rede nas invocações de funções. No entanto, tenha em atenção que uma ligação que permaneça não utilizada durante 10 minutos pode ser fechada pelo sistema, e as tentativas adicionais de usar uma ligação fechada resultam num erro "connection reset". O seu código deve usar uma biblioteca que processe bem as ligações fechadas ou processá-las explicitamente se usar construções de rede de baixo nível.

Isolamento de funções

Todas as funções implementadas estão isoladas de todas as outras funções, mesmo as que foram implementadas a partir do mesmo ficheiro de origem. Em particular, não partilham memória, variáveis globais, sistemas de ficheiros nem outro estado.

Para partilhar dados entre funções implementadas, pode usar serviços como o Memorystore, Datastore, Firestore ou Cloud Storage. Em alternativa, pode invocar uma função a partir de outra usando os respetivos acionadores adequados e transmitindo os dados necessários. Por exemplo, fazer um pedido HTTP ao ponto final de uma função HTTP ou publicar uma mensagem num tópico Pub/Sub para acionar uma função Pub/Sub.