Tutorial: Criar um aplicativo de chat em tempo real sem servidor com o Azure Functions e o serviço Azure Web PubSub
O serviço Azure Web PubSub ajuda você a criar aplicativos Web de mensagens em tempo real usando WebSockets e o padrão publish-subscribe facilmente. As Funções do Azure são uma plataforma sem servidor que lhe permite executar código sem ter de gerir qualquer infraestrutura. Neste tutorial, você aprenderá a usar o serviço Azure Web PubSub e o Azure Functions para criar um aplicativo sem servidor com mensagens em tempo real e o padrão publicar-assinar.
Neste tutorial, irá aprender a:
- Crie um aplicativo de bate-papo em tempo real sem servidor
- Trabalhar com ligações de gatilho da função Web PubSub e ligações de saída
- Implantar a função no Azure Function App
- Configurar a Autenticação do Azure
- Configurar o manipulador de eventos Web PubSub para rotear eventos e mensagens para o aplicativo
Pré-requisitos
Um editor de código, como o Visual Studio Code
Node.js, versão 18.x ou superior.
Nota
Para obter mais informações sobre as versões com suporte do Node.js, consulte a documentação de versões de tempo de execução do Azure Functions.
Ferramentas Principais do Azure Functions (v4 ou superior preferencial) para executar aplicativos do Azure Function localmente e implantar no Azure.
A CLI do Azure para gerenciar recursos do Azure.
Se não tiver uma subscrição do Azure, crie uma conta gratuita do Azure antes de começar.
Iniciar sessão no Azure
Inicie sessão no portal do Azure em https://portal.azure.com/ com a sua conta do Azure.
Criar uma instância de serviço Azure Web PubSub
Seu aplicativo se conectará a uma instância de serviço Web PubSub no Azure.
Selecione o botão Novo, no canto superior esquerdo do portal do Azure. Na tela Novo, digite Web PubSub na caixa de pesquisa e pressione enter. (Você também pode pesquisar o Azure Web PubSub na
Web
categoria.)Selecione Web PubSub nos resultados da pesquisa e, em seguida, selecione Criar.
Introduza as seguintes definições.
Definição Valor sugerido Description Nome do recurso Nome globalmente exclusivo O Nome globalmente exclusivo que identifica sua nova instância de serviço Web PubSub. Os caracteres válidos são a-z
,A-Z
,0-9
, e-
.Subscrição a sua subscrição A assinatura do Azure sob a qual essa nova instância de serviço Web PubSub é criada. Grupo de Recursos myResourceGroup Nome para o novo grupo de recursos no qual criar sua instância de serviço Web PubSub. Location E.U.A. Oeste Escolha uma região perto de si. Escalão de preço Gratuito Primeiro, você pode experimentar o serviço Azure Web PubSub gratuitamente. Saiba mais detalhes sobre os níveis de preços do serviço Azure Web PubSub Contagem de unidades - A contagem de unidades especifica quantas conexões sua instância de serviço Web PubSub pode aceitar. Cada unidade suporta no máximo 1.000 conexões simultâneas. Pode configurar apenas no escalão Standard. Selecione Criar para iniciar a implantação da instância do serviço Web PubSub.
Criar as funções
Certifique-se de que tem as Ferramentas Principais do Azure Functions instaladas. E, em seguida, crie um diretório vazio para o projeto. Execute o comando neste diretório de trabalho.
func init --worker-runtime javascript --model V4
Instale o
Microsoft.Azure.WebJobs.Extensions.WebPubSub
.Confirme e atualize
host.json
o extensionBundle para a versão 4.* ou posterior para obter suporte ao Web PubSub.{ "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[4.*, 5.0.0)" } }
Crie uma
index
função para ler e hospedar uma página da Web estática para clientes.func new -n index -t HttpTrigger
- Atualize
src/functions/index.js
e copie os seguintes 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, }; } });
- Atualize
Crie uma função para ajudar os clientes a obter URL de
negotiate
conexão de serviço com token de acesso.func new -n negotiate -t HttpTrigger
Nota
Neste exemplo, usamos o cabeçalho
x-ms-client-principal-name
de identidade do usuário do Microsoft Entra ID para recuperaruserId
o . E isso não funcionará em uma função local. Você pode deixá-lo vazio ou mudar para outras maneiras de obter ou geraruserId
ao jogar no local. Por exemplo, permita que o cliente digite um nome de usuário e passe-o em consulta como?user={$username}
quando chamarnegotiate
a função para obter a URL da conexão de serviço. E nanegotiate
função, definiruserId
com valor{query.user}
.- Atualize
src/functions/negotiate
e copie os seguintes 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')) }; }, });
- Atualize
Crie uma
message
função para transmitir mensagens do cliente através do serviço.func new -n message -t HttpTrigger
- Atualize
src/functions/message.js
e copie os seguintes 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", }; } });
- Atualize
Adicione a página
index.html
única do cliente na pasta raiz do projeto e copie o conteúdo.<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>
Criar e implantar o aplicativo Azure Function
Antes de implantar seu código de função no Azure, você precisa criar três recursos:
- Um grupo de recursos, que é um contêiner lógico para recursos relacionados.
- Uma conta de armazenamento, que é usada para manter o estado e outras informações sobre suas funções.
- Um aplicativo de função, que fornece o ambiente para executar seu código de função. Um aplicativo de função mapeia para seu projeto de função local e permite agrupar funções como uma unidade lógica para facilitar o gerenciamento, a implantação e o compartilhamento de recursos.
Use os comandos a seguir para criar esses itens.
Se ainda não o fez, inicie sessão no Azure:
az login
Crie um grupo de recursos ou você pode ignorar reutilizando o do serviço Azure Web PubSub:
az group create -n WebPubSubFunction -l <REGION>
Crie uma conta de armazenamento de uso geral em seu grupo de recursos e região:
az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
Crie o aplicativo de função no 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
Verifique a documentação das versões de tempo de execução do Azure Functions para definir
--runtime-version
o parâmetro como valor suportado.Implante o projeto de função no Azure:
Depois de criar com êxito seu aplicativo de função no Azure, você está pronto para implantar seu projeto de funções locais usando o comando func azure functionapp publishing .
func azure functionapp publish <FUNCIONAPP_NAME>
Configure o
WebPubSubConnectionString
para o aplicativo de função:Primeiro, localize seu recurso Web PubSub do Portal do Azure e copie a cadeia de conexão em Chaves. Em seguida, navegue até Configurações do aplicativo de função no Portal do Azure ->Settings ->Configuration. E adicione um novo item em Configurações do aplicativo, com nome igual e valor é sua cadeia de
WebPubSubConnectionString
conexão de recurso Web PubSub.
Configurar o serviço Web PubSub Event Handler
Neste exemplo, estamos usando WebPubSubTrigger
para ouvir solicitações de serviço upstream. Portanto, o Web PubSub precisa conhecer as informações de ponto final da função para enviar solicitações de clientes alvo. E o Azure Function App requer uma chave do sistema para segurança em relação a métodos de webhook específicos de extensão. Na etapa anterior, depois de implantarmos o aplicativo de função com message
funções, conseguimos obter a chave do sistema.
Vá para o portal do Azure -> Encontre seu recurso do aplicativo de função ->Chaves do aplicativo ->Chaves do sistema ->webpubsub_extension
. Copie o valor como <APP_KEY>
.
Definido Event Handler
no serviço Azure Web PubSub. Vá para o portal do Azure -> Encontre seu recurso Web PubSub ->Settings. Adicione um novo mapeamento de configurações de hub para a função em uso. Substitua o e <APP_KEY>
para o <FUNCTIONAPP_NAME>
seu.
- Nome do Hub:
simplechat
- Modelo de URL: https://< FUNCTIONAPP_NAME.azurewebsites.net/runtime/webhooks/webpubsub?code>=<APP_KEY>
- Padrão de evento do usuário: *
- Eventos do sistema: -(Não é necessário configurar neste exemplo)
Configurar para habilitar a autenticação do cliente
Vá para o portal do Azure -> Encontre seu recurso de aplicativo de função ->Autenticação. Clique em Add identity provider
. Defina as configurações de autenticação do Serviço de Aplicativo como Permitir acesso não autenticado, para que sua página de índice do cliente possa ser visitada por usuários anônimos antes de redirecionar para autenticação. Em seguida, salve.
Aqui escolhemos Microsoft
como provedor de identificação, que usa x-ms-client-principal-name
como userId
na negotiate
função. Além disso, você pode configurar outros provedores de identidade seguindo os links, e não se esqueça de atualizar o userId
valor na função de negotiate
acordo.
Experimentar a aplicação
Agora você pode testar sua página a partir do seu aplicativo de função: https://<FUNCTIONAPP_NAME>.azurewebsites.net/api/index
. Veja o instantâneo.
- Clique
login
para se autenticar. - Digite mensagem na caixa de entrada para conversar.
Na função de mensagem, transmitimos a mensagem do chamador para todos os clientes e retornamos o chamador com a mensagem [SYSTEM] ack
. Assim, podemos saber no exemplo de instantâneo de bate-papo, as primeiras quatro mensagens são do cliente atual e as duas últimas mensagens são de outro cliente.
Clean up resources (Limpar recursos)
Se você não vai continuar a usar este aplicativo, exclua todos os recursos criados por este documento com as seguintes etapas para não incorrer em nenhum custo:
No portal do Azure, selecione Grupos de recursos à esquerda e, em seguida, selecione o grupo de recursos que criou. Em vez disso, você pode usar a caixa de pesquisa para localizar o grupo de recursos pelo nome.
Na janela que se abre, selecione o grupo de recursos e, em seguida, selecione Eliminar grupo de recursos.
Na nova janela, digite o nome do grupo de recursos a ser excluído e selecione Excluir.
Próximos passos
Neste início rápido, você aprendeu como executar um aplicativo de chat sem servidor. Agora, você pode começar a criar seu próprio aplicativo.