Entorno de ejecución de Cloud Functions

Las funciones de Cloud Run se ejecutan en un entorno sin servidor totalmente gestionado en el que Google se encarga de la infraestructura, los sistemas operativos y los entornos de ejecución. Cada función se ejecuta en su propio contexto de ejecución seguro y aislado, se escala automáticamente y tiene un ciclo de vida independiente de otras funciones.

Tiempos de ejecución

Cloud Run Functions admite varios tiempos de ejecución de lenguajes. Cada uno contiene un conjunto estándar de paquetes del sistema, así como las herramientas y bibliotecas necesarias para ese idioma. Necesitará el valor ID de tiempo de ejecución si va a implementar funciones desde la línea de comandos o a través de Terraform.

Las actualizaciones de seguridad y mantenimiento están disponibles para todos los entornos de ejecución de primera y segunda generación. Estas actualizaciones se aplican automáticamente o manualmente, según el entorno y cómo lo hayas configurado. Para obtener más información sobre las actualizaciones del entorno de ejecución, consulta el artículo Protege tu función de Cloud Run.

Node.js

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
Node.js 24
(solo vista previa)
2.ª gen. Ubuntu 24.04 nodejs24 us-central1-docker.pkg.dev/serverless-runtimes/google-24-full/runtimes/nodejs24
Node.js 22 2.ª gen. Ubuntu 22.04 nodejs22 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js 20 1.ª gen., 2.ª gen. Ubuntu 22.04 nodejs20 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs20
Node.js 18 1.ª gen., 2.ª gen. Ubuntu 22.04 nodejs18 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs18
Node.js 16 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs16 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs16
Node.js 14 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs14 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs14
Node.js 12 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs12 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs12
Node.js 10 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs10 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs10
Node.js 8 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs8 Retirado
Node.js 6 1.ª gen., 2.ª gen. Ubuntu 18.04 nodejs6 Retirado

Python

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
Python 3.13 2.ª gen. Ubuntu 22.04 python313 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python313
Python 3.12 1.ª gen., 2.ª gen. Ubuntu 22.04 python312 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312
Python 3.11 1.ª gen., 2.ª gen. Ubuntu 22.04 python311 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311
Python 3.10 1.ª gen., 2.ª gen. Ubuntu 22.04 python310 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310
Python 3.9 1.ª gen., 2.ª gen. Ubuntu 18.04 python39 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39
Python 3.8 1.ª gen., 2.ª gen. Ubuntu 18.04 python38 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38
Python 3.7 1.ª gen. Ubuntu 18.04 python37 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37

Go

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
Go 1.25 2.ª gen. Ubuntu 22.04 go125 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go125
Go 1.24 2.ª gen. Ubuntu 22.04 go124 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go124
Go 1.23 2.ª gen. Ubuntu 22.04 go123 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go123
Go 1.22 2.ª gen. Ubuntu 22.04 go122 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go122
Go 1.21 1.ª gen., 2.ª gen. Ubuntu 22.04 go121 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go121
Go 1.20 1.ª gen., 2.ª gen. Ubuntu 22.04 go120 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go120
Go 1.19 1.ª gen., 2.ª gen. Ubuntu 22.04 go119 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go119
Go 1.18 1.ª gen., 2.ª gen. Ubuntu 22.04 go118 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go118
Go 1.16 1.ª gen., 2.ª gen. Ubuntu 18.04 go116 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go116
Go 1.13 1.ª gen., 2.ª gen. Ubuntu 18.04 go113 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go113
Go 1.11 1.ª gen., 2.ª gen. Ubuntu 18.04 go111 Retirado

Java

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
Java 21 2.ª gen. Ubuntu 22.04 java21 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21
Java 17 1.ª gen., 2.ª gen. Ubuntu 22.04 java17 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17
Java 11 1.ª gen., 2.ª gen. Ubuntu 18.04 java11 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11

Ruby

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
Ruby 3.4 2.ª gen. Ubuntu 22.04 ruby34 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby34
Ruby 3.3 1.ª gen., 2.ª gen. Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby33
Ruby 3.2 1.ª gen., 2.ª gen. Ubuntu 22.04 ruby32 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.0 1.ª gen., 2.ª gen. Ubuntu 18.04 ruby30 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30
Ruby 2.7 1.ª gen., 2.ª gen. Ubuntu 18.04 ruby27 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27
Ruby 2.6 1.ª gen., 2.ª gen. Ubuntu 18.04 ruby26 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26

PHP

Tiempo de ejecución Entorno Generación ID de entorno de ejecución Imagen de tiempo de ejecución
PHP 8.4 2.ª gen. Ubuntu 22.04 php84 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php84
PHP 8.3 2.ª gen. Ubuntu 22.04 php83 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83
PHP 8.2 1.ª gen., 2.ª gen. Ubuntu 22.04 php82 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82
PHP 8.1 1.ª gen., 2.ª gen. Ubuntu 18.04 php81 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81
PHP 7.4 1.ª gen., 2.ª gen. Ubuntu 18.04 php74 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74

.NET Core

Tiempo de ejecución Generación Entorno ID de entorno de ejecución Imagen de tiempo de ejecución
.NET Core 8 2.ª gen. Ubuntu 22.04 dotnet8 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8
.NET Core 6 1.ª gen., 2.ª gen. Ubuntu 22.04 dotnet6 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6
.NET Core 3 1.ª gen., 2.ª gen. Ubuntu 18.04 dotnet3 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3

Comportamiento del autoescalado

Cloud Run functions implementa el paradigma sin servidor, en el que ejecutas tu código sin preocuparte por la infraestructura subyacente, como servidores o máquinas virtuales. Una vez implementadas, tus funciones se gestionan y escalan automáticamente.

Cloud Run Functions gestiona las solicitudes entrantes asignándolas a instancias de tu función. En función del volumen de solicitudes y del número de instancias de función existentes, Cloud Run Functions puede asignar una solicitud a una instancia existente o crear una nueva.

En los casos en los que el volumen de solicitudes entrantes supera el número de instancias existentes, Cloud Run Functions puede iniciar varias instancias nuevas para gestionar las solicitudes. Este comportamiento de escalado automático permite que las funciones de Cloud Run gestionen muchas solicitudes en paralelo, cada una de ellas con una instancia diferente de tu función.

En algunos casos, puede que no sea recomendable usar un escalado ilimitado. Para solucionar este problema, Cloud Run functions te permite configurar un número máximo de instancias que pueden coexistir en un momento dado para una función concreta.

Sin reconocimiento del estado

Para habilitar la gestión y el escalado automáticos de tus funciones, estas deben ser sin estado. Es decir, una invocación de una función no debe depender del estado en memoria establecido por una invocación anterior. Las invocaciones pueden gestionarse mediante diferentes instancias de funciones, que no comparten variables globales, memoria, sistemas de archivos ni otro estado.

Si necesitas compartir el estado entre invocaciones de funciones, tu función debe usar un servicio como Memorystore, Datastore, Firestore o Cloud Storage para conservar los datos. Consulta las Google Cloud bases de datos y los Google Cloud productos de almacenamiento para obtener más información sobre las opciones de bases de datos y almacenamiento que ofrece Google Cloud.

Simultaneidad

Cloud Run Functions (2.ª gen.)

Las funciones de Cloud Run (2.ª gen.) admiten la gestión de varias solicitudes simultáneas en una sola instancia de función. Esto puede ser útil para evitar los inicios en frío, ya que una instancia ya activada puede procesar varias solicitudes simultáneamente, lo que reduce la latencia general. Para obtener más información, consulta Concurrencia.

Cloud Run Functions (1.ª gen.)

En Cloud Run Functions (1.ª gen.), cada instancia de una función gestiona solo una solicitud simultánea a la vez. Esto significa que, mientras tu código procesa una solicitud, no es posible que se dirija una segunda solicitud a la misma instancia. Por lo tanto, la solicitud original puede usar la cantidad total de recursos (memoria y CPU) que asignes.

Como las solicitudes simultáneas en Cloud Run Functions (1.ª gen.) se procesan mediante diferentes instancias de la función, no comparten variables ni memoria local. Para obtener más información, consulta los artículos sobre ausencia de estado y tiempo de vida de las instancias de funciones.

Arranques en frío

Una nueva instancia de función se inicia en dos casos:

  • Cuando despliegues tu función.

  • Cuando se crea automáticamente una nueva instancia de función para aumentar la capacidad en función de la carga o, en ocasiones, para sustituir una instancia.

Para iniciar una nueva instancia de función, se deben cargar el tiempo de ejecución y tu código. Las solicitudes que incluyen el inicio de una instancia de función, denominadas arranque en frío, pueden ser más lentas que las solicitudes dirigidas a instancias de función ya existentes. Sin embargo, si tu función recibe una carga constante, el número de arranques en frío suele ser insignificante, a menos que tu función falle con frecuencia y requiera reiniciar el entorno de la función.

Si el código de tu función genera una excepción no controlada o falla el proceso actual, es posible que se reinicie la instancia de la función. Esto puede provocar más inicios en frío, lo que conlleva una mayor latencia, por lo que te recomendamos que detectes las excepciones y evites que se termine el proceso actual.

Si tu función es sensible a la latencia, te recomendamos que definas un número mínimo de instancias para evitar los arranques en frío.

Tiempo de vida de la instancia de la función

Las instancias de función suelen ser resilientes y se reutilizan en invocaciones de función posteriores, a menos que el número de instancias se reduzca debido a la falta de tráfico continuo o a que tu función falle. Esto significa que, cuando finaliza la ejecución de una función, la misma instancia de la función puede gestionar otra invocación.

Permiso de función frente a permiso global

Una sola invocación de función da como resultado la ejecución únicamente del cuerpo de la función declarada como punto de entrada. El ámbito global del código fuente de tu función solo se ejecuta en los arranque en frío y no en las instancias que ya se hayan inicializado.

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

Puedes usar variables globales para optimizar el rendimiento, pero no debes depender del estado definido en el ámbito global por invocaciones de funciones anteriores. Consulta la sección Sin estado para obtener más información.

Puedes suponer que, en cada instancia de función, el ámbito global se ha ejecutado exactamente una vez antes de invocar el código de tu función. Sin embargo, no debes depender del número total ni de los tiempos de ejecución del ámbito global, ya que pueden variar en función de la actividad de autoescalado.

Cronología de la ejecución de la función

Una función solo tiene acceso a los recursos que se le han asignado (memoria y CPU) durante el tiempo que se ejecuta. No se garantiza que el código que se ejecute fuera del periodo de ejecución se ejecute y se puede detener en cualquier momento. Por lo tanto, siempre debes indicar el final de la ejecución de tu función correctamente y evitar ejecutar cualquier código después de ella. Para obtener más información, consulta los artículos sobre funciones HTTP, funciones en segundo plano y funciones de CloudEvent.

La ejecución de la función también está sujeta a la duración del tiempo de espera de la función. Consulta Tiempo de espera de la función para obtener más información.

Ten en cuenta la línea de tiempo de ejecución al inicializar tu aplicación. Las tareas en segundo plano no se deben crear en el ámbito global durante la inicialización, ya que se ejecutarían fuera de la duración de una solicitud.

Garantías de ejecución

Normalmente, las funciones se invocan una vez por cada evento entrante. Sin embargo, Cloud Run Functions no garantiza una sola invocación en todos los casos debido a las diferencias en los escenarios de error.

El número máximo o mínimo de veces que se puede invocar tu función para un solo evento depende del tipo de función:

  • Las funciones HTTP se invocan como máximo una vez. Esto se debe a la naturaleza síncrona de las llamadas HTTP, lo que significa que cualquier error que se produzca durante la invocación de la función se devolverá sin volver a intentarlo. Se espera que el llamante de una función HTTP gestione los errores y vuelva a intentarlo si es necesario.

  • Las funciones basadas en eventos se invocan al menos una vez. Esto se debe a la naturaleza asíncrona de los eventos, en la que no hay ningún llamante que espere la respuesta. En raras ocasiones, el sistema puede invocar una función basada en eventos más de una vez para asegurarse de que se entrega el evento. Si una invocación de una función basada en eventos falla con un error, la función no se volverá a invocar a menos que se habiliten los reintentos en caso de fallo para esa función.

Para asegurarte de que tu función se comporta correctamente en los intentos de ejecución repetidos, debes hacerla idempotente implementándola de forma que se produzcan los resultados deseados (y los efectos secundarios) aunque se envíe un evento varias veces. En el caso de las funciones HTTP, esto también significa devolver el valor deseado aunque el llamador vuelva a intentar llamar al endpoint de la función HTTP. Consulta el artículo Volver a probar funciones basadas en eventos para obtener más información sobre cómo hacer que tu función sea idempotente.

Memoria y sistema de archivos

Cada función tiene una cantidad de memoria asignada para su uso. Puedes configurar la cantidad de memoria durante la implementación. Consulta Configurar la memoria para obtener más información.

El entorno de ejecución de la función incluye un sistema de archivos en memoria que contiene los archivos de origen y los directorios implementados con tu función (consulta Estructura del código fuente). El directorio que contiene los archivos de origen es de solo lectura, pero el resto del sistema de archivos se puede escribir (excepto los archivos que usa el sistema operativo). El uso del sistema de archivos se tiene en cuenta en el uso de memoria de una función.

Tu función puede interactuar con el sistema de archivos mediante métodos estándar en cada lenguaje de programación.

Red

Tu función puede acceder a Internet público mediante métodos estándar en cada lenguaje de programación, ya sea a través de bibliotecas integradas que ofrece el tiempo de ejecución o de bibliotecas de terceros que incluyas como dependencias.

Intenta reutilizar las conexiones de red en las invocaciones de funciones. Sin embargo, ten en cuenta que el sistema puede cerrar una conexión que no se haya utilizado durante 10 minutos, y que los intentos posteriores de usar una conexión cerrada provocarán un error de "conexión restablecida". Tu código debe usar una biblioteca que gestione bien las conexiones cerradas o gestionarlas explícitamente si usas estructuras de red de bajo nivel.

Aislamiento de funciones

Cada función implementada está aislada de todas las demás funciones, incluso de las que se han implementado desde el mismo archivo de origen. En concreto, no comparten memoria, variables globales, sistemas de archivos ni otros estados.

Para compartir datos entre funciones implementadas, puedes usar servicios como Memorystore, Datastore, Firestore o Cloud Storage. También puedes invocar una función desde otra usando los activadores adecuados y transfiriendo los datos necesarios. Por ejemplo, puedes enviar una solicitud HTTP al endpoint de una función HTTP o publicar un mensaje en un tema de Pub/Sub para activar una función de Pub/Sub.