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 necessárias para que o seu aplicativo acesse o serviço Azure Web PubSub. A chave de acesso dentro da cadeia de conexão é semelhante a uma senha raiz para o 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 pontos de extremidade 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 html de índice para visita.
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 que estão disponíveis.
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 conseguir é usar a Ferramenta de Túnel
Instalar a Ferramenta de Túnel:
npm install -g @azure/web-pubsub-tunnel-toolExecutar 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: