Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial se explica cómo crear una web PubSub para Socket.IO servicio en modo sin servidor y crear una aplicación de chat que se integre con Azure Function.
Busque ejemplos de código completos que se usan en este tutorial:
Importante
El modo predeterminado necesita un servidor persistente, no puede integrar Web PubSub para Socket.IO en modo predeterminado con Azure Function.
Importante
Las cadenas de conexión sin procesar solo aparecen en este artículo con fines de demostración.
Una cadena de conexión incluye la información de autorización necesaria para que la aplicación acceda al servicio Azure Web PubSub. La clave de acceso dentro de la cadena de conexión es similar a una contraseña raíz para el servicio. En entornos de producción, proteja siempre las claves de acceso. Use Azure Key Vault para administrar y rotar las claves de forma segura y proteja la conexión con WebPubSubServiceClient.
Evite distribuirlas a otros usuarios, codificarlas de forma rígida o guardarlas en un archivo de texto sin formato al que puedan acceder otros usuarios. Rote sus claves si cree que se han puesto en peligro.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. En caso de no tener ninguna, puede crear una gratis.
- Herramienta principal de Azure Function
- Conocimientos de la biblioteca de Socket.IO.
Crear un web PubSub para Socket.IO recurso en modo sin servidor
Para crear un Web PubSub para Socket.IO, puede usar el siguiente comando de la CLI de Azure:
az webpubsub create -g <resource-group> -n <resource-name>--kind socketio --service-mode serverless --sku Premium_P1
Creación de un proyecto de Azure Function localmente
Debe seguir los pasos para iniciar un proyecto local de Azure Functions.
Siga estos pasos para instalar la Herramienta principal de Azure Function más reciente
En la ventana de terminal, o desde un símbolo del sistema, ejecute el siguiente comando para crear un proyecto en la carpeta
SocketIOProject:func init SocketIOProject --worker-runtime javascript --model V4Este comando crea un proyecto de JavaScript. Y escriba la carpeta
SocketIOProjectpara ejecutar los siguientes comandos.Actualmente, la agrupación de funciones no incluye Socket.IO enlace de funciones, por lo que debe agregar manualmente el paquete.
Para eliminar la referencia de agrupación de funciones, edite el archivo host.json y quite las líneas siguientes.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Ejecuta el comando:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Cree una función para la negociación. La función de negociación que se usa para generar puntos de conexión y tokens para que el cliente acceda al servicio.
func new --template "Http Trigger" --name negotiateAbra el archivo en
src/functions/negotiate.jsy reemplace por el código siguiente:const { app, input } = require('@azure/functions'); const socketIONegotiate = input.generic({ type: 'socketionegotiation', direction: 'in', name: 'result', hub: 'hub' }); async function negotiate(request, context) { let result = context.extraInputs.get(socketIONegotiate); return { jsonBody: result }; }; // Negotiation app.http('negotiate', { methods: ['GET', 'POST'], authLevel: 'anonymous', extraInputs: [socketIONegotiate], handler: negotiate });Este paso crea una función
negotiatecon un desencadenador HTTP y un enlace de salidaSocketIONegotiation, lo que significa que puede usar una llamada HTTP para activar la función y devolver un resultado de negociación generado por el enlaceSocketIONegotiation.Cree una función para entregar mensajes.
func new --template "Http Trigger" --name messageAbra el archivo
src/functions/message.jsy reemplace por el código siguiente:const { app, output, trigger } = require('@azure/functions'); const socketio = output.generic({ type: 'socketio', hub: 'hub', }) async function chat(request, context) { context.extraOutputs.set(socketio, { actionName: 'sendToNamespace', namespace: '/', eventName: 'new message', parameters: [ context.triggerMetadata.socketId, context.triggerMetadata.message ], }); } // Trigger for new message app.generic('chat', { trigger: trigger.generic({ type: 'socketiotrigger', hub: 'hub', eventName: 'chat', parameterNames: ['message'], }), extraOutputs: [socketio], handler: chat });Esto usa
SocketIOTriggerpara desencadenarse mediante un mensaje de cliente de Socket.IO y usarSocketIOel enlace para difundir mensajes al espacio de nombres.Cree una función para devolver un html de índice para visitar.
Cree una carpeta
publicensrc/.Cree un archivo html
index.htmlcon el siguiente contenido.<html> <body> <h1>Socket.IO Serverless Sample</h1> <div id="chatPage" class="chat-container"> <div class="chat-input"> <input type="text" id="chatInput" placeholder="Type your message here..."> <button onclick="sendMessage()">Send</button> </div> <div id="chatMessages" class="chat-messages"></div> </div> <script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script> <script> function appendMessage(message) { const chatMessages = document.getElementById('chatMessages'); const messageElement = document.createElement('div'); messageElement.innerText = message; chatMessages.appendChild(messageElement); hatMessages.scrollTop = chatMessages.scrollHeight; } function sendMessage() { const message = document.getElementById('chatInput').value; if (message) { document.getElementById('chatInput').value = ''; socket.emit('chat', message); } } async function initializeSocket() { const negotiateResponse = await fetch(`/api/negotiate`); if (!negotiateResponse.ok) { console.log("Failed to negotiate, status code =", negotiateResponse.status); return; } const negotiateJson = await negotiateResponse.json(); socket = io(negotiateJson.endpoint, { path: negotiateJson.path, query: { access_token: negotiateJson.token } }); socket.on('new message', (socketId, message) => { appendMessage(`${socketId.substring(0,5)}: ${message}`); }) } initializeSocket(); </script> </body> </html>Para devolver la página HTML, cree una función y copie códigos:
func new --template "Http Trigger" --name indexAbra el archivo
src/functions/index.jsy reemplace por el código siguiente:const { app } = require('@azure/functions'); const fs = require('fs').promises; const path = require('path') async function index(request, context) { try { context.log(`HTTP function processed request for url "${request.url}"`); const filePath = path.join(__dirname,'../public/index.html'); const html = await fs.readFile(filePath); return { body: html, headers: { 'Content-Type': 'text/html' } }; } catch (error) { context.log(error); return { status: 500, jsonBody: error } } }; app.http('index', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: index });
Ejecución local de la aplicación
Una vez preparado el código, siga las instrucciones para ejecutar el ejemplo.
Configuración de Azure Storage para Azure Function
Azure Functions requiere que una cuenta de almacenamiento funcione incluso ejecutándose en el entorno local. Elija cualquiera de las dos opciones siguientes:
- Ejecute el emulador de Azurite gratuito.
- Use el servicio Azure Storage. Esto puede incurrir en costos si sigue utilizándolo.
- Instalación de Azurite
npm install -g azurite
- Inicie el emulador de almacenamiento de Azurite:
azurite -l azurite -d azurite\debug.log
- Asegúrese de que
AzureWebJobsStorageen local.settings.json esté establecido enUseDevelopmentStorage=true.
Configuración de Web PubSub para Socket.IO
- Agregue una cadena de conexión a Function APP:
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
- Agregar la configuración del centro a Web PubSub para Socket.IO
az webpubsub hub create -n <resource name> -g <resource group> --hub-name hub --event-handler url-template="tunnel:///runtime/webhooks/socketio" user-event-pattern="*"
El comando de la CLI de Azure puede obtener la cadena de conexión
az webpubsub key show -g <resource group> -n <resource name>
La salida contiene primaryConnectionString y secondaryConnectionString, y está disponible.
Configuración del túnel
En el modo sin servidor, el servicio usa webhooks para desencadenar la función. Al intentar ejecutar la aplicación localmente, un problema crucial es permitir que el servicio pueda acceder al punto de conexión de la función local.
Una manera más fácil de lograr es usar Herramienta de túnel
Instalación de la herramienta Tunnel:
npm install -g @azure/web-pubsub-tunnel-toolEjecución del túnel
awps-tunnel run --hub hub --connection "<connection string>" --upstream http://127.0.0.1:7071El
--upstreames la dirección URL que expone la función local de Azure. El puerto puede ser diferente y puede comprobar la salida al iniciar la función en el paso siguiente.
Ejecución de aplicación de ejemplo
Después de ejecutar la herramienta de túnel, puede ejecutar function App localmente:
func start
Y visite la página web en http://localhost:7071/api/index.
Pasos siguientes
A continuación, puede intentar usar Bicep para implementar la aplicación en línea con la autenticación basada en identidad: