Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tutorial explica como criar um Web PubSub para Socket.IO serviço no Modo sem Servidor e criar um aplicativo de chat integrando-se ao Azure Function.
Encontre exemplos de código completo que são usados neste tutorial:
Importante
O Modo Padrão precisa de um servidor persistente, você não pode integrar o Web PubSub para Socket.IO no modo padrão com o Azure Function.
Importante
As cadeias de conexão brutas aparecem neste artigo somente para fins de demonstração.
Uma cadeia de conexão inclui as informações de autorização que sua aplicação precisa para acessar o serviço Azure Web PubSub. A chave de acesso na cadeia de conexão funciona como uma senha root para o seu serviço. Em ambientes de produção, sempre proteja suas chaves de acesso. Use o Azure Key Vault para gerenciar e girar suas chaves com segurança e proteger sua conexão com WebPubSubServiceClient.
Evite distribuir chaves de acesso para outros usuários, fazer hard-coding com elas ou salvá-las em qualquer lugar em texto sem formatação que seja acessível a outras pessoas. Gire suas chaves se você acredita que elas podem ter sido comprometidas.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Se você não tiver uma, poderá criar uma conta gratuita.
- Ferramenta principal do Azure Function
- Alguma familiaridade com a biblioteca de Socket.IO.
Criar um recurso Web PubSub para Socket.IO no Modo Sem Servidor
Para criar um Web PubSub para Socket.IO, você pode usar o seguinte comando da CLI do Azure:
az webpubsub create -g <resource-group> -n <resource-name>--kind socketio --service-mode serverless --sku Premium_P1
Criar um projeto do Azure Function localmente
Você deve seguir as etapas para iniciar um projeto local do Azure Function.
Siga a etapa para instalar a ferramenta principal mais recente do Azure Function
Na janela do terminal ou em um prompt de comando, execute o seguinte comando para criar um projeto na pasta
SocketIOProject:func init SocketIOProject --worker-runtime javascript --model V4Este comando cria um projeto de JavaScript. E insira a pasta
SocketIOProjectpara executar os comandos a seguir.Atualmente, o Pacote de Function não inclui Socket.IO Vinculação do Function, portanto, você precisa adicionar manualmente o pacote.
Para eliminar a referência do pacote de funções, edite o arquivo host.json e remova as linhas a seguir.
"extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" }Execute o comando:
func extensions install -p Microsoft.Azure.WebJobs.Extensions.WebPubSubForSocketIO -v 1.0.0-beta.4
Crie uma função para negociação. A função de negociação usada para gerar endpoints e tokens para o cliente acessar o serviço.
func new --template "Http Trigger" --name negotiateAbra o arquivo em
src/functions/negotiate.jse substitua pelo seguinte código: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 });Esta etapa cria uma função
negotiatecom gatilho HTTP eSocketIONegotiationassociação de saída, o que significa que você pode usar uma chamada HTTP para disparar a função e retornar um resultado de negociação gerado pelaSocketIONegotiationassociação.Crie uma função para entregar mensagens.
func new --template "Http Trigger" --name messageAbra o arquivo
src/functions/message.jse substitua pelo código a seguir: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 });Isso usa
SocketIOTriggerpara ser disparado por uma mensagem de cliente Socket.IO e usar a vinculaçãoSocketIOpara transmitir mensagens para o namespace.Crie uma função para retornar um index.html para acesso.
Crie uma pasta
publicemsrc/.Crie um arquivo html
index.htmlcom o seguinte conteúdo.<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 retornar a página HTML, crie uma função e copie códigos:
func new --template "Http Trigger" --name indexAbra o arquivo
src/functions/index.jse substitua pelo código a seguir: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 });
Para executar o aplicativo localmente
Depois que o código é preparado, siga as instruções para executar o exemplo.
Configurar o Armazenamento do Azure para o Azure Function
O Azure Functions exige uma conta de armazenamento para funcionar, mesmo em execução local. Escolha uma das duas opções a seguir:
- Execute o emulador Azurite gratuito.
- Use o serviço de Armazenamento do Microsoft Azure. Isso poderá incorrer em custos se você continuar a usá-lo.
- Instalar o Azurite
npm install -g azurite
- Inicie o emulador de armazenamento do Azurite:
azurite -l azurite -d azurite\debug.log
- Garanta que o
AzureWebJobsStorageem local.settings.json está definido comoUseDevelopmentStorage=true.
Definir a configuração do Web PubSub para Socket.IO
- Adicionar cadeia de conexão ao APLICATIVO Function:
func settings add WebPubSubForSocketIOConnectionString "<connection string>"
- Adicionar configurações de hub ao 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="*"
A cadeia de conexão pode ser obtida pelo comando da CLI do Azure
az webpubsub key show -g <resource group> -n <resource name>
A saída contém primaryConnectionString e secondaryConnectionString, e qualquer um dos dois está disponível.
Configurar túnel
No modo sem servidor, o serviço usa webhooks para disparar a função. Quando você tenta executar o aplicativo localmente, um problema crucial é permitir que o serviço possa acessar seu ponto de extremidade de função local.
Uma maneira mais fácil de fazer isso é usar Tunnel Tool
Instalar Ferramenta Tunnel:
npm install -g @azure/web-pubsub-tunnel-toolIniciar o túnel
awps-tunnel run --hub hub --connection "<connection string>" --upstream http://127.0.0.1:7071--upstreamé a URL que o Azure Function local expõe. A porta pode ser diferente e você pode verificar a saída ao iniciar a função na próxima etapa.
Executar o aplicativo de exemplo
Depois que a ferramenta de túnel estiver em execução, você poderá executar o Aplicativo Function localmente:
func start
E visite a página da Web em http://localhost:7071/api/index.
Próximas etapas
Em seguida, você pode tentar usar o Bicep para implantar o aplicativo online com autenticação baseada em identidade: