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
Go
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
Python
Go
Java
Ruby
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.