En este instructivo, se muestra cómo crear un servicio de chat multiusuario y en tiempo real mediante WebSockets con una conexión persistente para la comunicación bidireccional. Con WebSockets, el cliente y el servidor se pueden enviar mensajes entre sí sin sondear las actualizaciones del servidor.
Aunque puedes configurar Cloud Run para usar la afinidad de sesión, esto proporciona una afinidad de mejor esfuerzo, lo que significa que, potencialmente, cualquier solicitud nueva se puede seguir enrutando a una instancia diferente. Como resultado, los mensajes de los usuarios en el servicio de chat deben sincronizarse entre todas las instancias, no solo entre los clientes conectados a una instancia.
Descripción general del diseño
Este servicio de chat de muestra usa una instancia de Memorystore para Redis a fin de almacenar y sincronizar mensajes de usuarios en todas las instancias. Redis usa un mecanismo Pub/Sub, que no debe confundirse con el producto Cloud Pub/Sub, para enviar los datos a los clientes suscritos conectados a cualquier instancia a fin de eliminar el sondeo HTTP para obtener actualizaciones.
Sin embargo, incluso con las actualizaciones push, cualquier instancia que se inicie solo recibirá mensajes nuevos enviados al contenedor. Para cargar mensajes anteriores, el historial de mensajes tendría que almacenarse y recuperarse desde una solución de almacenamiento persistente. En este ejemplo, se usa la funcionalidad convencional de Redis de un depósito de objetos para almacenar en caché y recuperar el historial de mensajes.
La instancia de Redis está protegida de Internet mediante direcciones IP privadas con acceso controlado y limitado a servicios que se ejecutan en la misma red privada virtual que la instancia de Redis. Por lo tanto, se necesita un conector de acceso a VPC sin servidores para que el servicio de Cloud Run se conecte a Redis. Obtén más información sobre el Acceso a VPC sin servidores.
Limitaciones
En este instructivo, no se muestra la autenticación de usuario final ni el almacenamiento en caché de la sesión. Si deseas obtener más información sobre la autenticación de un usuario final, consulta el instructivo de Cloud Run para la autenticación de usuarios finales.
En este instructivo, no se implementa una base de datos como Firestore para almacenamiento indefinido y recuperación del historial de mensajes de chat.
Se necesitan elementos adicionales para que este servicio de muestra esté listo para la producción. Se recomienda una instancia de Redis de nivel Estándar para proporcionar alta disponibilidad mediante la replicación y la conmutación por error automática.
Objetivos
Escribir, compilar e implementar un servicio de Cloud Run que use WebSockets
Conéctate a una instancia de Memorystore para Redis a fin de publicar y suscribirte a mensajes nuevos en todas las instancias.
Conectar el servicio de Cloud Run con Memorystore mediante un conector de Acceso a VPC sin servidores
Costos
En este documento, usarás los siguientes componentes facturables de Google Cloud:
Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.
Antes de comenzar
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Run, Memorystore for Redis, Serverless VPC Access, Artifact Registry, and Cloud Build APIs.
- Instala e inicializa la CLI de gcloud
Roles obligatorios
Si quieres obtener los permisos que necesitas para completar el instructivo, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:
-
Lector de Artifact Registry (
roles/artifactregistry.reader
) -
Editor de Cloud Build (
roles/cloudbuild.builds.editor
) -
Administrador de Cloud Memorystore para Redis (
roles/redis.admin
) -
Administrador de Cloud Run (
roles/run.admin
) -
Crea cuentas de servicio (
roles/iam.serviceAccountCreator
) -
Administrador de IAM de proyecto (
roles/resourcemanager.projectIamAdmin
) -
Agente de servicio de Acceso a VPC sin servidores (
roles/vpcaccess.serviceAgent
) -
Administrador de cuenta de servicio (
roles/iam.serviceAccountAdmin
) -
Consumidor de Service Usage (
roles/serviceusage.serviceUsageConsumer
)
Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.
También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.
Configura los valores predeterminados de gcloud
A fin de configurar gcloud con los valores predeterminados para el servicio de Cloud Run, sigue estos pasos:
Configura el proyecto predeterminado:
gcloud config set project PROJECT_ID
Reemplaza PROJECT_ID por el nombre del proyecto que creaste para este instructivo.
Configura gcloud en la región que elegiste:
gcloud config set run/region REGION
Reemplaza REGION por la región de Cloud Run compatible que prefieras.
Ubicaciones de Cloud Run
Cloud Run es regional, lo que significa que la infraestructura que ejecuta los servicios se ubica en una región específica, y Google la administra para que esté disponible de manera redundante en todas las zonas de esa región.
El cumplimiento de los requisitos de latencia, disponibilidad o durabilidad es el factor principal para seleccionar la región en la que se ejecutan los servicios de Cloud Run.
Por lo general, puedes seleccionar la región más cercana a los usuarios, pero debes considerar la ubicación de los otros productos de Google Cloud que usa el servicio de Cloud Run.
Si usas productos de Google Cloud en varias ubicaciones, la latencia y el costo del servicio pueden verse afectados.
Cloud Run está disponible en las siguientes regiones:
Sujetas a los Precios del nivel 1
asia-east1
(Taiwán)asia-northeast1
(Tokio)asia-northeast2
(Osaka)asia-south1
(Bombay, India)europe-north1
(Finlandia) Bajo nivel de CO2europe-southwest1
(Madrid) Bajo nivel de CO2europe-west1
(Bélgica) Bajo nivel de CO2europe-west4
(Países Bajos) Bajo nivel de CO2europe-west8
(Milán)europe-west9
(París) Bajo nivel de CO2me-west1
(Tel Aviv)us-central1
(Iowa) Bajo nivel de CO2us-east1
(Carolina del Sur)us-east4
(Virginia del Norte)us-east5
(Columbus)us-south1
(Dallas) Bajo nivel de CO2us-west1
(Oregón) Bajo nivel de CO2
Sujetas a los Precios del nivel 2
africa-south1
(Johannesburgo)asia-east2
(Hong Kong)asia-northeast3
(Seúl, Corea del Sur)asia-southeast1
(Singapur)asia-southeast2
(Yakarta)asia-south2
Delhi (India)australia-southeast1
(Sídney)australia-southeast2
(Melbourne)europe-central2
(Varsovia, Polonia)europe-west10
(Berlín) Bajo nivel de CO2europe-west12
(Turín)europe-west2
(Londres, Reino Unido) Bajo nivel de CO2europe-west3
(Fráncfort, Alemania) Bajo nivel de CO2europe-west6
(Zúrich, Suiza) Bajo nivel de CO2me-central1
(Doha)me-central2
(Dammam)northamerica-northeast1
(Montreal) Bajo nivel de CO2northamerica-northeast2
(Toronto) Bajo nivel de CO2southamerica-east1
(São Paulo, Brasil) Bajo nivel de CO2southamerica-west1
(Santiago, Chile) Bajo nivel de CO2us-west2
(Los Ángeles)us-west3
(Salt Lake City)us-west4
(Las Vegas)
Si ya creaste un servicio de Cloud Run, puedes ver la región en el panel de Cloud Run en la consola de Google Cloud.
Recupera la muestra de código
A fin de recuperar la muestra de código para su uso, haz lo siguiente:
Clona el repositorio de muestra en tu máquina local:
Node.js
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.
Ve al directorio que contiene el código de muestra de Cloud Run:
Node.js
cd nodejs-docs-samples/run/websockets/
Comprende el código
Socket.io es una biblioteca que permite la comunicación bidireccional en tiempo real entre el navegador y el servidor. Si bien Socket.io no es una implementación de WebSocket, sí ajusta la funcionalidad a fin de proporcionar una API más simple para varios protocolos de comunicación con funciones adicionales, como una mayor confiabilidad, una reconexión automática y hacer una transmisión a todos los clientes o a un subconjunto de ellos.
Integración del cliente
El cliente crea una instancia de socket nueva para cada conexión. Debido a que este ejemplo es el procesamiento del servidor, no es necesario definir la URL del servidor. La instancia de socket puede emitir y escuchar eventos.
Integración del servidor
Del lado del servidor, el servidor de Socket.io se inicializa y se adjunta al servidor HTTP. Al igual que en el lado del cliente, una vez que el servidor Socket.io establece una conexión con el cliente, se crea una instancia de socket para cada conexión que se puede utilizar para emitir y escuchar mensajes. Socket.io también proporciona una interfaz sencilla para crear “salas” o un canal arbitrario al que los sockets pueden unirse y salir.
Socket.io también proporciona un adaptador de Redis para transmitir eventos a todos los clientes, sin importar qué servidor entrega el socket. Socket.io solo usa el mecanismo Pub/Sub de Redis y no almacena ningún dato.
El adaptador de Redis de Socket.io puede reutilizar el cliente de Redis que se usa para almacenar el historial de mensajes de la sala. Cada contenedor creará una conexión a la instancia de Redis, y Cloud Run puede crear una gran cantidad de instancias. Esto está muy por debajo de las 65,000 conexiones que admite Redis. Si necesitas admitir esta cantidad de tráfico, también debes evaluar la capacidad de procesamiento del conector de Acceso a VPC sin servidores.
Reconexión
Cloud Run tiene un tiempo de espera máximo de 60 minutos. Por lo tanto, debes agregar la lógica de reconexión para los posibles tiempos de espera. En algunos casos, Socket.io se vuelve a conectar automáticamente después de los eventos de error de conexión o de desconexión. No hay garantía de que el cliente se volverá a conectar a la misma instancia.
Las instancias se conservarán si hay una conexión activa hasta que todas las solicitudes se cierren o se agote el tiempo de espera. Incluso si usas la afinidad de sesión de Cloud Run, es posible que las cargas de las solicitudes nuevas se balanceen en contenedores activos, lo que permite que los contenedores reduzcan la escala. Si te preocupa que haya una gran cantidad de contenedores persistentes después de un aumento repentino de tráfico, puedes reducir el valor de tiempo de espera máximo para que los sockets sin usar se borren con más frecuencia.
Envía el servicio
Crea una instancia de Memorystore para Redis
gcloud redis instances create INSTANCE_ID --size=1 --region=REGION
Reemplace INSTANCE_ID por el nombre de la instancia, es decir,
my-redis-instance
, y REGION_ID por la región de todos sus recursos y servicios, es decirus-central1
.Se asignará un rango de IP del rango desde el rango de red del servicio predeterminado de forma automática a la instancia. En este instructivo, se usa 1 GB de memoria para la caché local de mensajes en la instancia de Redis. Obtén más información a fin de determinar el tamaño inicial de una instancia de Memorystore para tu caso de uso.
Configura un conector de Acceso a VPC sin servidores.
Para conectarte a tu instancia de Redis, tu servicio de Cloud Run necesita acceso a la red de VPC autorizada de la instancia de Redis.
Cada conector de VPC requiere su propia subred
/28
para colocar sus instancias. Este rango de IP no debe superponerse con ninguna reserva de dirección IP existente en la red de VPC. Por ejemplo,10.8.0.0
(/28
) funcionará en la mayoría de los proyectos nuevos o puedes especificar otro rango de IP personalizado sin usar, como10.9.0.0
(/28
). Puedes ver qué rangos de IP están reservados en este momento en la consola de Google Cloud.gcloud compute networks vpc-access connectors create CONNECTOR_NAME \ --region REGION \ --range "10.8.0.0/28"
Reemplaza CONNECTOR_NAME con el nombre de tu conector.
Este comando crea un conector en la red de VPC predeterminada, igual que la instancia de Redis, con el tamaño de máquina
e2-micro
. Aumentar el tamaño de la máquina del conector puede mejorar la capacidad de procesamiento del conector, pero también puede aumentar el costo. El conector también debe estar en la misma región que la instancia de Redis. Obtén más información sobre la configuración del Acceso a VPC sin servidores.Define una variable de entorno con la dirección IP de la red autorizada de tu instancia de Redis:
export REDISHOST=$(gcloud redis instances describe INSTANCE_ID --region REGION --format "value(host)")
Crea una cuenta de servicio para que funcione como la identidad del servicio. De forma predeterminada, esta no tiene otros privilegios más que la membresía del proyecto.
gcloud iam service-accounts create chat-identity gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:chat-identity@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/serviceusage.serviceUsageConsumer
Compila e implementa la imagen de contenedor en Cloud Run:
gcloud run deploy chat-app --source . \ --vpc-connector CONNECTOR_NAME \ --allow-unauthenticated \ --timeout 3600 \ --service-account chat-identity \ --update-env-vars REDISHOST=$REDISHOST
Responde a cualquier solicitud para instalar las API obligatorias. Para ello, responde
y
cuando se te solicite. Solo debes hacer esto una vez en un proyecto. Responde a otras solicitudes suministrando la plataforma y la región si no configuraste los valores predeterminados de estas como se describe en la página de configuración. Obtén más información para Implementa a partir del código fuente.
Prueba
Para probar el servicio completo, haz lo siguiente:
Dirige tu navegador a la URL proporcionada en el paso de implementación anterior.
Agrega tu nombre y una sala de chat para acceder.
Envía un mensaje a la sala.
Si eliges seguir desarrollando estos servicios, recuerda que tienen acceso restringido de la administración de identidades y accesos (IAM) al resto de Google Cloud y necesitarán tener funciones de IAM adicionales para acceder a muchos otros servicios.
Limpia
Si creaste un proyecto nuevo para este instructivo, bórralo. Si usaste un proyecto existente y deseas conservarlo sin los cambios que se agregaron en este instructivo, borra los recursos creados para el instructivo.
Borra el proyecto
La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.
Para borrar el proyecto, sigue estos pasos:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Borra los recursos del instructivo
Usa este comando para borrar el servicio de Cloud Run que implementaste en este instructivo:
gcloud run services delete SERVICE-NAME
En el ejemplo anterior, SERVICE-NAME es el nombre del servicio que elegiste.
También puedes borrar los servicios de Cloud Run desde la consola de Google Cloud.
Quita la configuración de región predeterminada de gcloud que agregaste durante la configuración en el instructivo:
gcloud config unset run/region
Quita la configuración del proyecto:
gcloud config unset project
Borra otros recursos de Google Cloud que creaste en este instructivo:
- Borra la imagen de contenedor del servicio llamada
gcr.io/PROJECT_ID/chat-app
de Artifact Registry. - Borra la cuenta de servicio
chat-identity@PROJECT_ID.iam.gserviceaccount.com
. - Borra la instancia de Memorystore para Redis.
- Borra el conector de Acceso a VPC sin servidores
- Borra la imagen de contenedor del servicio llamada
¿Qué sigue?
Obtén más información sobre cómo funciona Socket.io y un uso más avanzado.
Obtén más información en Configura el acceso a VPC sin servidores.
Revisa las prácticas recomendadas para Memorystore y Usa WebSockets en Cloud Run.
Explora Herramientas de diagnóstico de acceso a VPC sin servidores para solucionar cualquier problema de red sin servidores.