Dela via


Självstudie: Skapa en serverlös chattapp i realtid med Azure Functions och Azure Web PubSub-tjänsten

Tjänsten Azure Web PubSub hjälper dig att enkelt skapa webbprogram för meddelanden i realtid med hjälp av WebSockets och mönstret publicera-prenumerera. Azure Functions är en serverlös plattform som gör att du kan köra din kod utan att behöva hantera någon infrastruktur. I den här självstudien får du lära dig hur du använder Tjänsten Azure Web PubSub och Azure Functions för att skapa ett serverlöst program med meddelanden i realtid och mönstret publicera-prenumerera.

I den här självstudien lär du dig att:

  • Skapa en serverlös chattapp i realtid
  • Arbeta med Web PubSub-funktionsutlösarbindningar och utdatabindningar
  • Distribuera funktionen till Azure-funktionsappen
  • Konfigurera Azure-autentisering
  • Konfigurera Web PubSub Event Handler för att dirigera händelser och meddelanden till programmet

Förutsättningar

  • En kodredigerare, till exempel Visual Studio Code

  • Node.js version 18.x eller senare.

    Kommentar

    Mer information om vilka versioner av Node.js som stöds finns i dokumentationen om Azure Functions-körningsversioner.

  • Azure Functions Core Tools (v4 eller senare rekommenderas) för att köra Azure Function-appar lokalt och distribuera till Azure.

  • Azure CLI för att hantera Azure-resurser.

Om du inte har en Azure-prenumeration skapar du ett kostnadsfritt Azure-konto innan du börjar.

Logga in på Azure

Logga in på Azure Portal på https://portal.azure.com/ med ditt Azure-konto.

Skapa en Azure Web PubSub-tjänstinstans

Ditt program ansluter till en Web PubSub-tjänstinstans i Azure.

  1. Välj knappen Nytt högst upp till vänster i Azure-portalen. På skärmen Nytt skriver du Web PubSub i sökrutan och trycker på Retur. (Du kan också söka i Azure Web PubSub från Web kategorin.)

    Skärmbild av sökning i Azure Web PubSub i portalen.

  2. Välj Web PubSub i sökresultatet och välj sedan Skapa.

  3. Ange följande inställningar.

    Inställning Föreslaget värde beskrivning
    Resursnamn Globalt unikt namn Det globalt unika namn som identifierar din nya Web PubSub-tjänstinstans. Giltiga tecken är a-z, A-Z, 0-9och -.
    Abonnemang Din prenumeration Den Azure-prenumeration under vilken den här nya Web PubSub-tjänstinstansen skapas.
    Resursgrupp myResourceGroup Namn på den nya resursgrupp där du vill skapa din Web PubSub-tjänstinstans.
    Plats Västra USA Välj en region nära dig.
    Prisnivå Kostnadsfri Du kan prova tjänsten Azure Web PubSub kostnadsfritt. Läs mer om prisnivåer för Azure Web PubSub-tjänsten
    Antal enheter - Antal enheter anger hur många anslutningar din Web PubSub-tjänstinstans kan acceptera. Varje enhet stöder högst 1 000 samtidiga anslutningar. Det kan bara konfigureras på Standard-nivån.

    Skärmbild av hur du skapar Azure Web PubSub-instansen i portalen.

  4. Välj Skapa för att börja distribuera instansen av Web PubSub-tjänsten.

Skapa funktionerna

  1. Kontrollera att du har Azure Functions Core Tools installerat. Skapa sedan en tom katalog för projektet. Kör kommandot under den här arbetskatalogen.

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

    Bekräfta och uppdatera host.jsontilläggetBundle till version 4.* eller senare för att få support för Web PubSub.

    {
      "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.*, 5.0.0)"
      }
    }
    
  3. Skapa en index funktion för att läsa och vara värd för en statisk webbsida för klienter.

    func new -n index -t HttpTrigger
    
    • Uppdatera src/functions/index.js och kopiera följande koder.
      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. Skapa en negotiate funktion som hjälper klienter att hämta url:en för tjänstanslutning med åtkomsttoken.

    func new -n negotiate -t HttpTrigger
    

    Kommentar

    I det här exemplet använder vi användaridentitetshuvudet x-ms-client-principal-name för Microsoft Entra-ID för att hämta userId. Och detta fungerar inte i en lokal funktion. Du kan göra den tom eller ändra till andra sätt att hämta eller generera userId när du spelar lokalt. Låt till exempel klienten skriva ett användarnamn och skicka det i fråga som ?user={$username} när anropsfunktionen negotiate för att hämta url för tjänstanslutning. Och i negotiate funktionen anger du userId med värdet {query.user}.

    • Uppdatera src/functions/negotiate och kopiera följande koder.
      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. Skapa en message funktion för att sända klientmeddelanden via tjänsten.

    func new -n message -t HttpTrigger
    
    • Uppdatera src/functions/message.js och kopiera följande koder.
      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. Lägg till klientens enstaka sida index.html i projektets rotmapp och kopiera innehåll.

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

Skapa och distribuera Azure-funktionsappen

Innan du kan distribuera funktionskoden till Azure måste du skapa tre resurser:

  • En resursgrupp, som är en logisk container för relaterade resurser.
  • Ett lagringskonto som används för att underhålla tillstånd och annan information om dina funktioner.
  • En funktionsapp som tillhandahåller miljön för att köra funktionskoden. En funktionsapp mappar till ditt lokala funktionsprojekt och låter dig gruppera funktioner som en logisk enhet för enklare hantering, distribution och delning av resurser.

Använd följande kommandon för att skapa dessa objekt.

  1. Om du inte redan har gjort det loggar du in på Azure:

    az login
    
  2. Skapa en resursgrupp eller så kan du hoppa över genom att återanvända en av Azure Web PubSub-tjänsten:

    az group create -n WebPubSubFunction -l <REGION>
    
  3. Skapa ett allmänt lagringskonto i din resursgrupp och region:

    az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
    
  4. Skapa funktionsappen i 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>
    

    Kommentar

    Kontrollera dokumentationen för Azure Functions-körningsversioner för att ange --runtime-version parametern till det värde som stöds.

  5. Distribuera funktionsprojektet till Azure:

    När du har skapat funktionsappen i Azure är du nu redo att distribuera ditt lokala funktionsprojekt med hjälp av publiceringskommandot func azure functionapp .

    func azure functionapp publish <FUNCIONAPP_NAME>
    
  6. WebPubSubConnectionString Konfigurera för funktionsappen:

    Leta först upp din Web PubSub-resurs från Azure Portal och kopiera ut niska veze under Nycklar. Navigera sedan till Funktionsappsinställningar i Azure-portalen> Inställningar –> Konfiguration. Och lägg till ett nytt objekt under Programinställningar, med namnet lika WebPubSubConnectionString med och värdet är din Web PubSub-resurs niska veze.

Konfigurera tjänsten Web PubSub Event Handler

I det här exemplet använder WebPubSubTrigger vi för att lyssna på uppströmsbegäranden i tjänsten. Web PubSub behöver därför känna till funktionens slutpunktsinformation för att kunna skicka målklientbegäranden. Och Azure-funktionsappen kräver en systemnyckel för säkerhet för tilläggsspecifika webhookmetoder. I föregående steg när vi har distribuerat funktionsappen med message funktioner kan vi hämta systemnyckeln.

Gå till Azure-portalen –> Hitta funktionsappresursen ->Appnycklar ->Systemnycklar ->webpubsub_extension. Kopiera ut värdet som <APP_KEY>.

Skärmbild av hämta funktionssystemnycklar.

Ange Event Handler i Azure Web PubSub-tjänsten. Gå till Azure-portalen –> Hitta din Web PubSub-resurs –> Inställningar. Lägg till en ny hubbinställningsmappning till den funktion som används. <FUNCTIONAPP_NAME> Ersätt och <APP_KEY> till din.

  • Hubbnamn: simplechat
  • URL-mall: https://< FUNCTIONAPP_NAME.azurewebsites.net/runtime/webhooks/webpubsub?code>=<APP_KEY>
  • Användarhändelsemönster: *
  • Systemhändelser: -(Du behöver inte konfigurera i det här exemplet)

Skärmbild av hur du ställer in händelsehanteraren.

Konfigurera för att aktivera klientautentisering

Gå till Azure-portalen –> Hitta funktionsappresursen ->Autentisering. Klicka på Add identity provider. Ställ in autentiseringsinställningar för App Service på Tillåt oautentiserad åtkomst, så att klientindexsidan kan besökas av anonyma användare innan du omdirigerar till autentisering. Sedan spara.

Här väljer Microsoft vi som identifierare, som använder x-ms-client-principal-name som userId i negotiate funktionen. Dessutom kan du konfigurera andra identitetsprovidrar efter länkarna och glöm inte att uppdatera userId värdet i funktionen i negotiate enlighet med detta.

Testa programmet

Nu kan du testa sidan från funktionsappen: https://<FUNCTIONAPP_NAME>.azurewebsites.net/api/index. Se ögonblicksbild.

  1. Klicka om du login vill autentisera dig själv.
  2. Skriv meddelandet i indatarutan för att chatta.

I meddelandefunktionen sänder vi uppringarens meddelande till alla klienter och returnerar anroparen med meddelandet [SYSTEM] ack. Så vi kan veta i exempel på chattögonblicksbild att de första fyra meddelandena kommer från den aktuella klienten och att de två sista meddelandena kommer från en annan klient.

Skärmbild av chattexempel.

Rensa resurser

Om du inte kommer att fortsätta att använda den här appen tar du bort alla resurser som skapats av det här dokumentet med följande steg så att du inte debiteras några avgifter:

  1. Välj Resursgrupper i Azure Portal längst till vänster och välj sedan den resursgrupp du skapat. Du kan använda sökrutan för att hitta resursgruppen med dess namn i stället.

  2. I fönstret som öppnas väljer du resursgruppen och väljer sedan Ta bort resursgrupp.

  3. I det nya fönstret skriver du namnet på resursgruppen som ska tas bort och väljer sedan Ta bort.

Nästa steg

I den här snabbstarten har du lärt dig hur du kör ett serverlöst chattprogram. Nu kan du börja skapa ett eget program.