Esercitazione: Creare un'app di chat in tempo reale serverless con Funzioni di Azure e il servizio Web PubSub di Azure

Il servizio Web PubSub di Azure consente di creare facilmente applicazioni Web di messaggistica in tempo reale usando WebSocket e il modello publish-subscribe. Funzioni di Azure è una piattaforma serverless che consente di eseguire il codice senza gestire alcuna infrastruttura. In questa esercitazione si apprenderà come usare il servizio Web PubSub di Azure e Funzioni di Azure per creare un'applicazione serverless con messaggistica in tempo reale e il modello publish-subscribe.

In questa esercitazione apprenderai a:

  • Creare un'app di chat in tempo reale serverless
  • Usare associazioni di trigger di funzione Web PubSub e associazioni di output
  • Distribuire la funzione nell'app per le funzioni di Azure
  • Configurare l'autenticazione di Azure
  • Configurare il gestore eventi Web PubSub per instradare eventi e messaggi all'applicazione

Prerequisiti

Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.

Accedere ad Azure

Accedere al portale di Azure all'indirizzo https://portal.azure.com/ con il proprio account Azure.

Creare un'istanza del servizio Web PubSub di Azure

L'applicazione si connetterà a un'istanza del servizio Web PubSub in Azure.

  1. Selezionare il pulsante Nuovo nell'angolo superiore sinistro del portale di Azure. Nella schermata Nuovo digitare Web PubSub nella casella di ricerca e premere INVIO. È anche possibile eseguire una ricerca in PubSub Web di Azure dalla Web categoria .

    Screenshot della ricerca nel sito Web pubSub di Azure nel portale.

  2. Selezionare Web PubSub nei risultati della ricerca e quindi selezionare Crea.

  3. Immettere le impostazioni seguenti.

    Impostazione Valore suggerito Descrizione
    Nome risorsa Nome globalmente univoco Nome univoco globale che identifica la nuova istanza del servizio Web PubSub. I caratteri validi sono a-z, A-Z, 0-9e -.
    Abbonamento Sottoscrizione in uso Sottoscrizione di Azure in cui viene creata la nuova istanza del servizio Web PubSub.
    Gruppo di risorse myResourceGroup Nome del nuovo gruppo di risorse in cui creare l'istanza del servizio Web PubSub.
    Location Stati Uniti occidentali Scegliere un'area nelle vicinanze.
    Piano tariffario Libero È prima possibile provare gratuitamente il servizio Web PubSub di Azure. Altre informazioni sui piani tariffari del servizio Web PubSub di Azure
    Unità: conteggio - Il numero di unità specifica il numero di connessioni che l'istanza del servizio Web PubSub può accettare. Ogni unità supporta al massimo 1.000 connessioni simultanee. È configurabili solo nel livello Standard.

    Screenshot della creazione dell'istanza Di Pubblicazione Web di Azure nel portale.

  4. Selezionare Crea per avviare la distribuzione dell'istanza del servizio Web PubSub.

Creare le funzioni

  1. Assicurarsi di aver installato Funzioni di Azure Core Tools. Creare quindi una directory vuota per il progetto. Eseguire il comando in questa directory di lavoro.

    func init --worker-runtime javascript --model V4
    
  2. Installare Microsoft.Azure.WebJobs.Extensions.WebPubSub.

    Confermare e aggiornare host.jsonl'estensioneBundle alla versione 4.* o successiva per ottenere il supporto di Web PubSub.

    {
      "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.*, 5.0.0)"
      }
    }
    
  3. Creare una index funzione per leggere e ospitare una pagina Web statica per i client.

    func new -n index -t HttpTrigger
    
    • Aggiornare e copiare src/functions/index.js i codici seguenti.
      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, 
              };
          }
      });
      
  4. Creare una negotiate funzione per consentire ai client di ottenere l'URL di connessione del servizio con il token di accesso.

    func new -n negotiate -t HttpTrigger
    

    Nota

    In questo esempio viene usata l'intestazione x-ms-client-principal-name dell'identità utente di Microsoft Entra ID per recuperare userId. E questo non funzionerà in una funzione locale. È possibile renderlo vuoto o passare ad altri modi per ottenere o generare userId durante la riproduzione in locale. Ad esempio, consentire al client di digitare un nome utente e passarlo in query, ad ?user={$username} esempio quando chiama negotiate la funzione per ottenere l'URL di connessione del servizio. E nella negotiate funzione impostare userId con il valore {query.user}.

    • Aggiornare e copiare src/functions/negotiate i codici seguenti.
      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')) };
          },
      });
      
  5. Creare una message funzione per trasmettere i messaggi client tramite il servizio.

    func new -n message -t HttpTrigger
    
    • Aggiornare e copiare src/functions/message.js i codici seguenti.
      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",
              };
          }
      });
      
  6. Aggiungere la singola pagina index.html client nella cartella radice del progetto e copiare il contenuto.

    <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>
    

Creare e distribuire l'app per le funzioni di Azure

Prima di distribuire il codice della funzione in Azure, è necessario creare tre risorse:

  • Un gruppo di risorse, ovvero un contenitore logico di risorse correlate.
  • Un account di archiviazione, usato per mantenere lo stato e altre informazioni sulle funzioni.
  • Un'app per le funzioni, che fornisce l'ambiente per l'esecuzione del codice della funzione. Un'app per le funzioni esegue il mapping al progetto di funzione locale e consente di raggruppare le funzioni come unità logica per semplificare la gestione, la distribuzione e la condivisione delle risorse.

Usare i comandi seguenti per creare questi elementi.

  1. Se non è già stato fatto, accedere ad Azure:

    az login
    
  2. Creare un gruppo di risorse oppure ignorare riutilizzando uno dei servizi Web PubSub di Azure:

    az group create -n WebPubSubFunction -l <REGION>
    
  3. Creare un account di archiviazione per utilizzo generico nel gruppo di risorse e nell'area:

    az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
    
  4. Creare l'app per le funzioni in 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

    Controllare Funzioni di Azure documentazione delle versioni di runtime per impostare il parametro sul --runtime-version valore supportato.

  5. Distribuire il progetto di funzione in Azure:

    Dopo aver creato l'app per le funzioni in Azure, è ora possibile distribuire il progetto di funzioni locali usando il comando func azure functionapp publish .

    func azure functionapp publish <FUNCIONAPP_NAME>
    
  6. Configurare per l'app per le WebPubSubConnectionString funzioni:

    Per prima cosa, trovare la risorsa Web PubSub dal portale di Azure e copiare il stringa di connessione in Chiavi. Passare quindi alle impostazioni dell'app per le funzioni nel portale di Azure ->Impostazioni ->Configuration. Aggiungere un nuovo elemento in Impostazioni applicazione, con nome uguale WebPubSubConnectionString a e valore è la risorsa Web PubSub stringa di connessione.

Configurare il servizio Web PubSub Event Handler

In questo esempio viene usato WebPubSubTrigger per ascoltare le richieste upstream del servizio. Pertanto, Web PubSub deve conoscere le informazioni sull'endpoint della funzione per inviare richieste client di destinazione. L'app per le funzioni di Azure richiede una chiave di sistema per la sicurezza relativa ai metodi webhook specifici dell'estensione. Nel passaggio precedente dopo aver distribuito l'app per le funzioni con message le funzioni, è possibile ottenere la chiave di sistema.

Passare a portale di Azure : trovare la risorsa dell'app per le funzioni ->Chiavi app ->Chiavi di sistema -webpubsub_extension>.> Copiare il valore come <APP_KEY>.

Screenshot delle chiavi di sistema get function.

Impostare Event Handler nel servizio Web PubSub di Azure. Passare a portale di Azure :> trovare la risorsa Web PubSub ->Impostazioni. Aggiungere un nuovo mapping delle impostazioni dell'hub a una funzione in uso. Sostituisci e <FUNCTIONAPP_NAME><APP_KEY> nel tuo.

  • Nome hub: simplechat
  • Modello URL: https://< FUNCTIONAPP_NAME.azurewebsites.net/runtime/webhooks/webpubsub?code>=<APP_KEY>
  • Modello di evento utente: *
  • Eventi di sistema: -(Non è necessario configurare in questo esempio)

Screenshot dell'impostazione del gestore eventi.

Configurare per abilitare l'autenticazione client

Passare a portale di Azure :> trovare la risorsa dell'app per le funzioni -> Autenticazione. Fare clic su Add identity provider. Impostare servizio app impostazioni di autenticazione su Consenti l'accesso non autenticato, in modo che la pagina dell'indice client possa essere visitata dagli utenti anonimi prima del reindirizzamento per l'autenticazione. Quindi fai clic su Salva.

In questo caso si sceglie Microsoft come provider di identificazione, che usa x-ms-client-principal-name come userId nella negotiate funzione . Inoltre, è possibile configurare altri provider di identità seguendo i collegamenti e non dimenticare di aggiornare il userId valore in negotiate funzione di conseguenza.

Provare l'applicazione

È ora possibile testare la pagina dall'app per le funzioni: https://<FUNCTIONAPP_NAME>.azurewebsites.net/api/index. Vedere snapshot.

  1. Fare clic login per autenticarsi.
  2. Digitare il messaggio nella casella di input per la chat.

Nella funzione messaggio viene trasmesso il messaggio del chiamante a tutti i client e viene restituito il chiamante con il messaggio [SYSTEM] ack. È quindi possibile sapere nello snapshot della chat di esempio, i primi quattro messaggi provengono dal client corrente e gli ultimi due messaggi provengono da un altro client.

Screenshot dell'esempio di chat.

Pulire le risorse

Se non si intende continuare a usare questa app, eliminare tutte le risorse create da questo documento con i passaggi seguenti in modo da non incorrere in alcun addebito:

  1. Nel portale di Azure selezionare Gruppi di risorse all'estrema sinistra e quindi selezionare il gruppo di risorse creato. È possibile usare la casella di ricerca per trovare il gruppo di risorse in base al nome.

  2. Nella finestra visualizzata selezionare il gruppo di risorse e quindi selezionare Elimina gruppo di risorse.

  3. Nella nuova finestra digitare il nome del gruppo di risorse da eliminare e quindi selezionare Elimina.

Passaggi successivi

In questa guida introduttiva si è appreso come eseguire un'applicazione chat serverless. A questo punto, è possibile iniziare a creare un'applicazione personalizzata.