Tutorial: Creación de una aplicación de chat en tiempo real sin servidor con Azure Functions y el servicio Azure Web PubSub
El servicio Azure Web PubSub le ayuda a crear aplicaciones web de mensajería en tiempo real mediante WebSockets y el patrón de publicación y suscripción fácilmente. Azure Functions es una plataforma sin servidor que le permite ejecutar el código sin tener que administrar ninguna infraestructura. En este tutorial, aprenderá a usar el servicio Azure Web PubSub y Azure Functions para crear una aplicación sin servidor con mensajería en tiempo real y el patrón de publicación y suscripción.
En este tutorial, aprenderá a:
- Compilar una aplicación de chat en tiempo real sin servidor
- Trabajar con enlaces de desencadenador de función y enlaces de salida de Web PubSub
- Implementar la función en Azure Function App
- Configurar la autenticación de Azure
- Configurar el controlador de eventos de Web PubSub para enrutar los eventos y mensajes a la aplicación
Requisitos previos
Un editor de código como Visual Studio Code
Node.js, versión 18.x o superior.
Nota:
Para más información sobre las versiones de Node.js que se admiten, consulte la documentación de las versiones del runtime de Azure Functions.
Azure Functions Core Tools (se prefiere la versión 4 o superiores) para ejecutar aplicaciones de Azure Functions localmente y realizar la implementación en Azure.
La CLI de Azure para administrar recursos de Azure.
Si no tiene una suscripción a Azure, cree una cuenta gratuita de Azure antes de empezar.
Inicio de sesión en Azure
Inicie sesión en Azure Portal en https://portal.azure.com/ con su cuenta de Azure.
Creación de una instancia de servicio de Azure Web PubSub
La aplicación se conectará a una instancia de servicio de Web PubSub en Azure.
Seleccione el botón Nuevo de la esquina superior izquierda en Azure Portal. En la pantalla "Nuevo", escriba Web PubSub en el cuadro de búsqueda y presione Entrar. (También puede buscar Azure Web PubSub en la categoría
Web
).Seleccione Web PubSub en los resultados de la búsqueda y, después, haga clic en Crear.
Escriba la siguiente configuración.
Configuración Valor sugerido Descripción Nombre del recurso Nombre único globalmente Nombre único global que identifica la nueva instancia del servicio Web PubSub. Los caracteres válidos son a-z
,A-Z
,0-9
y-
.Suscripción Su suscripción Suscripción de Azure en la que se va a crear esta instancia del servicio Web PubSub. Grupo de recursos myResourceGroup Nombre del grupo de recursos nuevo en el que se va a crear la instancia del servicio Web PubSub. Ubicación Oeste de EE. UU. Seleccione una región cerca de usted. Plan de tarifa Gratuito Pruebe el servicio Azure Web PubSub de forma gratuita. Más información sobre los planes de tarifa del servicio Azure Web PubSub. Recuento de unidades - El recuento de unidades especifica cuántas conexiones puede aceptar la instancia del servicio Web PubSub. Cada unidad admite 1000 conexiones simultáneas como máximo. Solo es configurable en el nivel Estándar. Seleccione Crear para empezar a implementar la instancia del servicio Web PubSub.
Creación de las funciones
Asegúrese de que Azure Functions Core Tools está instalado. Luego, cree un directorio vacío para el proyecto. Ejecute el comando en este directorio de trabajo.
func init --worker-runtime javascript --model V4
Instalar
Microsoft.Azure.WebJobs.Extensions.WebPubSub
.Confirme y actualice extensionBundle de
host.json
a la versión 4.* o posterior para obtener soporte para Web PubSub.{ "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" } }
Cree una función
index
para leer y hospedar una página web estática para los clientes.func new -n index -t HttpTrigger
- Actualice
src/functions/index.js
y copie los siguientes códigos.const { app } = require('@azure/functions'); const { readFile } = require('fs/promises'); app.http('index', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: async (context) => { const content = await readFile('index.html', 'utf8', (err, data) => { if (err) { context.err(err) return } }); return { status: 200, headers: { 'Content-Type': 'text/html' }, body: content, }; } });
- Actualice
Cree una función
negotiate
para ayudar a los clientes a obtener la dirección URL de conexión del servicio con el token de acceso.func new -n negotiate -t HttpTrigger
Nota:
En este ejemplo, usamos el encabezado de identidad de usuario de Microsoft Entra ID
x-ms-client-principal-name
para recuperaruserId
. No servirá en una función local. Puede dejarlo vacío o cambiar a otras formas de obtener o generaruserId
al reproducir en local. Por ejemplo, deje que el cliente escriba un nombre de usuario y lo pase en una consulta, como?user={$username}
, cuando llame a la funciónnegotiate
para obtener la dirección URL de conexión del servicio. Y en la funciónnegotiate
, establezcauserId
con el valor{query.user}
.- Actualice
src/functions/negotiate
y copie los siguientes códigos.const { app, input } = require('@azure/functions'); const connection = input.generic({ type: 'webPubSubConnection', name: 'connection', userId: '{headers.x-ms-client-principal-name}', hub: 'simplechat' }); app.http('negotiate', { methods: ['GET', 'POST'], authLevel: 'anonymous', extraInputs: [connection], handler: async (request, context) => { return { body: JSON.stringify(context.extraInputs.get('connection')) }; }, });
- Actualice
Cree una función
message
para difundir mensajes de clientes a través del servicio.func new -n message -t HttpTrigger
- Actualice
src/functions/message.js
y copie los siguientes códigos.const { app, output, trigger } = require('@azure/functions'); const wpsMsg = output.generic({ type: 'webPubSub', name: 'actions', hub: 'simplechat', }); const wpsTrigger = trigger.generic({ type: 'webPubSubTrigger', name: 'request', hub: 'simplechat', eventName: 'message', eventType: 'user' }); app.generic('message', { trigger: wpsTrigger, extraOutputs: [wpsMsg], handler: async (request, context) => { context.extraOutputs.set(wpsMsg, [{ "actionName": "sendToAll", "data": `[${context.triggerMetadata.connectionContext.userId}] ${request.data}`, "dataType": request.dataType }]); return { data: "[SYSTEM] ack.", dataType: "text", }; } });
- Actualice
Agregue la página única del cliente
index.html
en la carpeta raíz del proyecto y copie el contenido.<html> <body> <h1>Azure Web PubSub Serverless Chat App</h1> <div id="login"></div> <p></p> <input id="message" placeholder="Type to chat..." /> <div id="messages"></div> <script> (async function () { let authenticated = window.location.href.includes( "?authenticated=true" ); if (!authenticated) { // auth let login = document.querySelector("#login"); let link = document.createElement("a"); link.href = `${window.location.origin}/.auth/login/aad?post_login_redirect_url=/api/index?authenticated=true`; link.text = "login"; login.appendChild(link); } else { // negotiate let messages = document.querySelector("#messages"); let res = await fetch(`${window.location.origin}/api/negotiate`, { credentials: "include", }); let url = await res.json(); // connect let ws = new WebSocket(url.url); ws.onopen = () => console.log("connected"); ws.onmessage = (event) => { let m = document.createElement("p"); m.innerText = event.data; messages.appendChild(m); }; let message = document.querySelector("#message"); message.addEventListener("keypress", (e) => { if (e.charCode !== 13) return; ws.send(message.value); message.value = ""; }); } })(); </script> </body> </html>
Creación e implementación de una aplicación de funciones de Azure
Antes de poder implementar el código de la función en Azure, debe crear tres recursos:
- Un grupo de recursos, que es un contenedor lógico de recursos relacionados.
- Una cuenta de almacenamiento, que se usa para mantener el estado y otra información sobre sus funciones.
- Una aplicación de funciones, que proporciona el entorno para ejecutar el código de función. Una aplicación de funciones se asigna a un proyecto de función local y le permite agrupar funciones como una unidad lógica, lo que facilita la administración, la implementación y el uso compartido de recursos.
Utilice los comandos siguientes para crear los elementos.
Si todavía no lo ha hecho, inicie sesión en Azure:
az login
Cree un grupo de recursos. O bien, utilice el grupo de recursos del servicio Azure Web PubSub para omitir esta acción:
az group create -n WebPubSubFunction -l <REGION>
Cree una cuenta de almacenamiento de uso general en el grupo de recursos y la región:
az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
Cree la aplicación de funciones en Azure:
az functionapp create --resource-group WebPubSubFunction --consumption-plan-location <REGION> --runtime node --runtime-version 18 --functions-version 4 --name <FUNCIONAPP_NAME> --storage-account <STORAGE_NAME>
Nota
Consulte la documentación de versiones en tiempo de ejecución de Azure Functions para establecer el parámetro
--runtime-version
al valor compatible.Implemente el proyecto de función en Azure:
Después de haber creado correctamente su aplicación de funciones en Azure, está listo para implementar el proyecto de funciones local mediante el comando func azure functionapp publish.
func azure functionapp publish <FUNCIONAPP_NAME>
Configure el elemento
WebPubSubConnectionString
para la aplicación de funciones:En primer lugar, busque el recurso Web PubSub en Azure Portal y copie la cadena de conexión en Claves. A continuación, vaya a la configuración de la aplicación de funciones en Azure Portal ->Configuración ->Configuración. Y agregue un nuevo elemento en Configuración de la aplicación, con un nombre igual a
WebPubSubConnectionString
y el valor es la cadena de conexión del recurso Web PubSub.
Configuración Event Handler
del servicio Web PubSub
En este ejemplo, se usa WebPubSubTrigger
para escuchar las solicitudes ascendentes del servicio. Por lo tanto, Web PubSub tiene que conocer la información del punto de conexión de la función para enviar solicitudes de cliente de destino. Y la aplicación de funciones de Azure requiere una clave del sistema para la seguridad con respecto a los métodos de webhook específicos de la extensión. En el paso anterior, después de implementar la aplicación de funciones con funciones message
, pudimos obtener la clave del sistema.
Vaya a Azure Portal -> Busque su recurso de aplicación de funciones ->Claves de la aplicación ->Claves del sistema ->webpubsub_extension
. Copie el valor como <APP_KEY>
.
Establezca Event Handler
en el servicio Azure Web PubSub. Vaya a Azure Portal -> Busque su recurso de Web PubSub ->Configuración. Agregue una nueva asignación de configuración del centro a la única función en uso. Reemplace <FUNCTIONAPP_NAME>
y <APP_KEY>
por los suyos.
- Nombre del centro:
simplechat
- Plantilla de dirección URL:https://<NOMBRE_APLICACIÓNFUNCIONES>.azurewebsites.net/runtime/webhooks/webpubsub?code=<CLAVE_APLICACIÓN>
- Patrón de evento de usuario: *
- Eventos del sistema: (no es necesario configurar en este ejemplo)
Configuración para habilitar la autenticación de cliente
Vaya a Azure Portal -> Busque su recurso de aplicación de funciones ->Autenticación. Haga clic en Add identity provider
. Establezca la configuración de autenticación de App Service en Permitir acceso no autenticado para que los usuarios anónimos puedan visitar la página de índice del cliente antes de su redireccionamiento al proceso de autenticación. A continuación, guarde la operación.
Aquí elegimos Microsoft
como proveedor de identificación, que utiliza x-ms-client-principal-name
como userId
en la función negotiate
. Además, puede configurar otros proveedores de identidades siguiendo los vínculos. No olvide actualizar el valor userId
de la función negotiate
en consecuencia.
Prueba de la aplicación
Ahora puede probar la página desde la aplicación de funciones: https://<FUNCTIONAPP_NAME>.azurewebsites.net/api/index
. Consulte la instantánea.
- Haga clic en
login
para autenticarse. - Escriba el mensaje en el cuadro de entrada para chatear.
En la función message, se difunde el mensaje del autor de la llamada a todos los clientes y se devuelve el mensaje [SYSTEM] ack
al autor de la llamada. Por tanto, en la instantánea de chat del ejemplo, sabemos que los cuatro primeros mensajes son del cliente actual y los dos últimos son de otro cliente.
Limpieza de recursos
Si no va a seguir usando esta aplicación, siga los pasos que se indican a continuación para eliminar todos los recursos creados por este documento, con el fin de que no se le apliquen cargos:
En Azure Portal, seleccione Grupos de recursos en el extremo izquierdo y luego seleccione el grupo de recursos que creó. Puede usar el cuadro de búsqueda para buscar el grupo de recursos por su nombre en su lugar.
En la ventana que se abrirá, seleccione el grupo de recursos y luego seleccione Eliminar grupo de recursos.
En la nueva ventana, escriba el nombre del grupo de recursos que desea eliminar y, después, seleccione Eliminar.
Pasos siguientes
En este inicio rápido, ha aprendido a ejecutar una aplicación de chat sin servidor. Ahora, puede empezar a crear su propia aplicación.