Tutorial: criar um aplicativo de notificação 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. O Azure Functions é uma plataforma sem servidor que permite executar seu código sem gerenciar 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 em cenários de notificação.

Neste tutorial, você aprenderá como:

  • Criar um aplicativo de notificação sem servidor
  • Trabalhar com associações de entrada e saída de função do Web PubSub
  • Executar as funções de exemplo localmente
  • Implantar a função no aplicativo de funções do Azure

Pré-requisitos

Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

Entrar no Azure

Entre no portal do Azure em https://portal.azure.com/ com sua conta do Azure.

Criar uma instância do serviço Azure Web PubSub

Seu aplicativo se conectará a uma instância do serviço Web PubSub no Azure.

  1. Selecione no botão Novo localizado 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 categoria Web.)

    Captura de tela da pesquisa do Azure Web PubSub no portal.

  2. Selecione Web PubSub nos resultados da pesquisa e escolha Criar.

  3. Insira as configurações a seguir.

    Configuração Valor sugerido Descrição
    Nome do recurso Nome globalmente exclusivo O Nome globalmente exclusivo que identifica a nova instância do serviço Azure Web PubSub. Os caracteres válidos são a-z, 0-9 e -.
    Assinatura Sua assinatura A assinatura do Azure na qual essa nova instância do serviço Azure Web PubSub será criada.
    Grupo de Recursos myResourceGroup Nome do novo grupo de recursos no qual a instância do serviço Azure Web PubSub será criada.
    Localidade Oeste dos EUA Selecione uma região perto de você.
    Tipo de preços Grátis Primeiro, você pode experimentar o serviço Azure Web PubSub gratuitamente. Saiba mais detalhes sobre os tipos de preços do serviço Azure Web PubSub
    Contagem de unidades - A contagem de unidades especifica quantas conexões a instância do serviço Azure Web PubSub pode aceitar. Cada unidade dá suporte a, no máximo, 1.000 conexões simultâneas. Só é configurável na camada Standard.

    Captura de tela da criação da instância do Azure Web PubSub no Portal.

  4. Selecione Criar para começar a implantar a instância do serviço Azure Web PubSub.

Criar e executar as funções localmente

  1. Verifique se você tem o Azure Functions Core Tools instalado. E, em seguida, criar um diretório vazio para o projeto. Execute o comando neste diretório de trabalho.

    func init --worker-runtime javascript
    
  2. Instale o pacote de extensão de função Microsoft.Azure.WebJobs.Extensions.WebPubSub explicitamente.

    a. Remova a seção extensionBundle em host.json para habilitar a instalação do pacote de extensão específico na próxima etapa. Ou basta tornar o JSON do host o mais simples possível, como abaixo.

    {
        "version": "2.0"
    }
    

    b. Execute o comando para instalar o pacote de extensão de função específico.

    func extensions install --package Microsoft.Azure.WebJobs.Extensions.WebPubSub --version 1.0.0-beta.3
    
  3. Crie uma função index para ler e hospedar uma página da Web estática para clientes.

    func new -n index -t HttpTrigger
    
    • Atualize index/function.json e copie os seguintes códigos JSON.
      {
          "bindings": [
              {
                  "authLevel": "anonymous",
                  "type": "httpTrigger",
                  "direction": "in",
                  "name": "req",
                  "methods": [
                    "get",
                    "post"
                  ]
              },
              {
                  "type": "http",
                  "direction": "out",
                  "name": "res"
              }
          ]
      }
      
    • Atualize index/index.js e copie os seguintes códigos.
      var fs = require('fs');
      module.exports = function (context, req) {
          fs.readFile('index.html', 'utf8', function (err, data) {
              if (err) {
                  console.log(err);
                  context.done(err);
              }
              context.res = {
                  status: 200,
                  headers: {
                      'Content-Type': 'text/html'
                  },
                  body: data
              };
              context.done();
          });
      }
      
  4. Crie uma função negotiate para ajudar os clientes a obterem a URL de conexão do serviço com o token de acesso.

    func new -n negotiate -t HttpTrigger
    
    • Atualize negotiate/function.json e copie os seguintes códigos JSON.
      {
          "bindings": [
              {
                  "authLevel": "anonymous",
                  "type": "httpTrigger",
                  "direction": "in",
                  "name": "req"
              },
              {
                  "type": "http",
                  "direction": "out",
                  "name": "res"
              },
              {
                  "type": "webPubSubConnection",
                  "name": "connection",
                  "hub": "notification",
                  "direction": "in"
              }
          ]
      }
      
    • Atualize negotiate/index.js e copie os seguintes códigos.
      module.exports = function (context, req, connection) {
          context.res = { body: connection };
          context.done();
      };
      
  5. Crie uma função notification para a qual gerar notificações com TimerTrigger.

     func new -n notification -t TimerTrigger
    
    • Atualize notification/function.json e copie os seguintes códigos JSON.
      {
          "bindings": [
              {
              "name": "myTimer",
              "type": "timerTrigger",
              "direction": "in",
              "schedule": "*/10 * * * * *"
              },
              {
              "type": "webPubSub",
              "name": "webPubSubOperation",
              "hub": "notification",
              "direction": "out"
              }
          ]
      }
      
    • Atualize notification/index.js e copie os seguintes códigos.
      module.exports = function (context, myTimer) {
          context.bindings.webPubSubOperation = {
              "operationKind": "sendToAll",
              "message": `[DateTime: ${new Date()}] Temperature: ${getValue(22, 1)}\xB0C, Humidity: ${getValue(40, 2)}%`,
              "dataType": "text"
          }
          context.done();
      };
      
      function getValue(baseNum, floatNum) {
          return (baseNum + 2 * floatNum * (Math.random() - 0.5)).toFixed(3);
      }
      
  6. Adicione a página única do cliente index.html na pasta raiz do projeto e copie o conteúdo conforme mostrado abaixo.

    <html>
        <body>
        <h1>Azure Web PubSub Notification</h1>
        <div id="messages"></div>
        <script>
            (async function () {
                let messages = document.querySelector('#messages');
                let res = await fetch(`${window.location.origin}/api/negotiate`);
                let url = await res.json();
                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);
                };
            })();
        </script>
        </body>
    </html>
    
  7. Configurar e executar o aplicativo do Azure Functions

    • No navegador, abra o portal do Azure e confirme se a instância do serviço Web PubSub implantada anteriormente foi criada com êxito. Navegue até a instância.
    • Selecione Chaves e copie a cadeia de conexão.

    Captura de tela da cópia da cadeia de conexão do Web PubSub.

    Execute o comando abaixo na pasta de funções para definir a cadeia de conexão do serviço. Substitua <connection-string> pelo seu valor, conforme necessário.

    func settings add WebPubSubConnectionString "<connection-string>"
    

    Observação

    O TimerTrigger usado no exemplo tem dependência no Armazenamento do Azure, mas você pode usar um emulador de armazenamento local quando a função estiver sendo executada localmente. Se ocorrer algum erro como There was an error performing a read operation on the Blob Storage Secret Repository. Please ensure the 'AzureWebJobsStorage' connection string is valid., você precisará baixar e habilitar o Emulador de Armazenamento.

    Agora você pode executar a função local com o comando abaixo.

    func start
    

    E verificando os logs em execução, você pode ir até a página estática do host local acessando: https://localhost:7071/api/index.

Implantar o aplicativo de funções no Azure

Para implantar o código da 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ções, que fornece o ambiente para a execução do código de função. Um aplicativo de funções é mapeado 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.

  1. Se você ainda não tiver feito isso, entre no Azure:

    az login
    
  2. Crie um grupo de recursos ou ignore essa etapa reutilizando o do serviço do Azure Web PubSub:

    az group create -n WebPubSubFunction -l <REGION>
    
  3. Crie uma conta de armazenamento para uso geral no grupo de recursos e na região:

    az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
    
  4. Criar o aplicativo de funções no Azure:

    az functionapp create --resource-group WebPubSubFunction --consumption-plan-location <REGION> --runtime node --runtime-version 12 --functions-version 3 --name <FUNCIONAPP_NAME> --storage-account <STORAGE_NAME>
    
  5. Implantar o projeto de funções no Azure:

    Depois de criar com sucesso o aplicativo de funções no Azure, você estará pronto para implantar um projeto local de funções usando o comando func azure functionapp publish.

    func azure functionapp publish <FUNCIONAPP_NAME> --publish-local-settings
    

    Observação

    Aqui estamos implantando as configurações locais local.settings.json junto com o parâmetro de comando --publish-local-settings. Se estiver usando Emulador de Armazenamento do Microsoft Azure, você poderá digitar no para ignorar a substituição desse valor no Azure após a mensagem de prompt: App setting AzureWebJobsStorage is different between azure and local.settings.json, Would you like to overwrite value in azure? [yes/no/show]. Além disso, você pode atualizar as configurações do Aplicativo de funções no Portal do Azure -> Definições -> Configuração.

  6. Agora você pode verificar o site no Aplicativo de funções do Azure navegando até a URL: https://<FUNCIONAPP_NAME>.azurewebsites.net/api/index.

Limpar recursos

Se você não pretende continuar usando este aplicativo, exclua todos os recursos criados por este documento com as seguintes etapas para não gerar custos:

  1. No portal do Azure, selecione Grupos de recursos na extremidade esquerda, depois selecione o recurso de grupo que você criou. Você poderá usar a caixa de pesquisa para localizar o grupo de recursos pelo nome.

  2. Na janela que será aberta, selecione o grupo de recursos e escolha Excluir grupo de recursos.

  3. Na nova janela, digite o nome do grupo de recursos a ser excluído e selecione Excluir.

Próximas etapas

Neste início rápido, você aprendeu a executar um aplicativo de chat sem servidor. Agora, você pode começar a criar seu próprio aplicativo.