Tutorial: Veröffentlichen und Abonnieren von Nachrichten zwischen WebSocket-Clients mit einem Unterprotokoll

Im Tutorial zum Erstellen einer Chat-App haben Sie gelernt, wie Sie WebSocket-APIs zum Senden und Empfangen von Daten mit Azure Web PubSub verwenden. Sie sehen, dass kein Protokoll erforderlich ist, wenn der Client mit dem Dienst kommuniziert. Sie können z. B. jede Art von Daten mithilfe von WebSocket.send() senden, und der Server empfängt ihn genauso wie er ist. Der WebSocket-APIs-Prozess ist einfach zu verwenden, die Funktionalität ist jedoch eingeschränkt. Sie können z. B. nicht den Ereignisnamen angeben, wenn Sie das Ereignis an Ihren Server senden, oder die Nachricht für andere Clients veröffentlichen, anstatt sie an Ihren Server zu senden. In diesem Tutorial erfahren Sie, wie Sie ein Unterprotokoll verwenden, um die Funktionalität des Clients zu erweitern.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen einer Web PubSub-Dienstinstanz
  • Generieren der vollständigen URL zum Herstellen der WebSocket-Verbindung
  • Veröffentlichen von Nachrichten zwischen WebSocket-Clients mit einem Unterprotokoll

Wenn Sie nicht über ein Azure-Konto verfügen, erstellen Sie ein kostenloses Konto , bevor Sie beginnen.

Voraussetzungen

  • Für dieses Setup ist mindestens Version 2.22.0 der Azure CLI erforderlich. Bei Verwendung von Azure Cloud Shell ist die aktuelle Version bereits installiert.

Wichtig

Unformatierte Verbindungszeichenfolgen werden in diesem Artikel nur zu Demonstrationszwecken angezeigt.

Eine Verbindungszeichenfolge enthält die Autorisierungsinformationen, die Ihre Anwendung benötigt, um auf den Azure Web PubSub-Dienst zuzugreifen. Der Zugangsschlüssel im Verbindungszeichenfolge fungiert wie ein Root-Passwort für deinen Dienst. Schützen Sie Ihre Zugriffsschlüssel in Produktionsumgebungen immer sorgfältig. Verwenden Sie Azure Key Vault zum sicheren Verwalten und Rotieren Ihrer Schlüssel und zum Schützen Ihrer Verbindung mit WebPubSubServiceClient.

Geben Sie Zugriffsschlüssel nicht an andere Benutzer weiter, vermeiden Sie das Hartcodieren, und speichern Sie die Schlüssel nicht als Klartext, auf den andere Benutzer Zugriff haben. Rotieren Sie die Schlüssel, wenn Sie glauben, dass sie möglicherweise gefährdet sind.

Erstellen einer Azure Web PubSub-Instanz

Erstellen einer Ressourcengruppe

Eine Ressourcengruppe ist ein logischer Container, in dem Azure-Ressourcen bereitgestellt und verwaltet werden. Erstellen Sie mithilfe des Befehls az group create eine Ressourcengruppe namens myResourceGroup in der Region eastus.

az group create --name myResourceGroup --location EastUS

Erstellen einer Web PubSub-Instanz

Führen Sie az extension add aus, um die Erweiterung webpubsub zu installieren bzw. auf die aktuelle Version zu aktualisieren.

az extension add --upgrade --name webpubsub

Verwenden Sie den Azure CLI-Befehl az webpubsub create, um eine Web PubSub-Instanz in der erstellten Ressourcengruppe zu erstellen. Mit dem folgenden Befehl wird eine Kostenlose Web-PubSub-Ressource unter der Ressourcengruppe myResourceGroup in USA, Osten erstellt:

Wichtig

Jede Web PubSub-Ressource muss einen eindeutigen Namen haben. Ersetzen Sie <your-unique-resource-name> in den folgenden Beispielen durch den Namen Ihrer Web PubSub.

az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1

In der Ausgabe dieses Befehls werden die Eigenschaften der neu erstellten Ressource angezeigt. Beachten Sie die beiden folgenden Eigenschaften:

  • Resource Name: Der Name, den Sie oben für den Parameter --name angegeben haben.
  • hostName: Im Beispiel lautet der Hostname <your-unique-resource-name>.webpubsub.azure.com/.

An diesem Punkt ist nur Ihr Azure-Konto zum Ausführen von Vorgängen für die neue Ressource autorisiert.

Rufen Sie die Verbindungszeichenfolge zur späteren Verwendung ab.

Unformatierte Verbindungszeichenfolgen werden in diesem Artikel nur zu Demonstrationszwecken angezeigt. Schützen Sie Ihre Zugriffsschlüssel in Produktionsumgebungen immer sorgfältig. Verwenden Sie Azure Key Vault zum sicheren Verwalten und Rotieren Ihrer Schlüssel und zum Schützen Ihrer Verbindung mit WebPubSubServiceClient.

Verwenden Sie den Azure CLI-Befehl az webpubsub key, um die Verbindungszeichenfolge (ConnectionString) des Diensts abzurufen. Ersetzen Sie den Platzhalter <your-unique-resource-name> durch den Namen Ihrer Azure Web PubSub-Instanz.

az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv

Kopieren Sie die Verbindungszeichenfolge zur späteren Verwendung.

Kopieren Sie die abgerufene ConnectionString und verwenden Sie sie später in diesem Tutorial als Wert von <connection_string>.

Einrichten des Projekts

Voraussetzungen

Verwenden eines Unterprotokolls

Der Client kann mithilfe eines bestimmten Unterprotokolls eine WebSocket-Verbindung starten. Der Azure Web PubSub-Dienst unterstützt ein Unterprotokoll namens json.webpubsub.azure.v1, um es Clients zu ermöglichen, Nachrichten direkt über den Web PubSub-Dienst zu veröffentlichen bzw. zu abonnieren – ohne Roundtrip zum Upstreamserver. Details zum Unterprotokoll finden Sie im Artikel zur Unterstützung des JSON WebSocket-Unterprotokolls für Azure Web PubSub.

Wenn Sie andere Protokollnamen verwenden, werden diese vom Dienst ignoriert und im Connect-Ereignishandler an den Server durchgelassen, sodass Sie eigene Protokolle erstellen können.

Lassen Sie uns jetzt eine Webanwendung mit dem Unterprotokoll json.webpubsub.azure.v1 erstellen.

  1. Abhängigkeiten installieren

    mkdir logstream
    cd logstream
    dotnet new web
    dotnet add package Microsoft.Extensions.Azure
    dotnet add package Azure.Messaging.WebPubSub
    
  2. Erstellen Sie die Serverseite zum Hosten der /negotiate-API und der Webseite.

    Aktualisieren Sie Program.cs mit dem folgenden Code.

    • Verwenden Sie AddAzureClients, um den Dienstclient hinzuzufügen, und lesen Sie die Verbindungszeichenfolge aus der Konfiguration.
    • Fügen Sie app.UseStaticFiles(); vor app.Run(); ein, um statische Dateien zu unterstützen.
    • Aktualisieren Sie außerdem app.MapGet, um das Client-Zugriffstoken mit /negotiate-Anfragen zu generieren.
    using Azure.Messaging.WebPubSub;
    using Microsoft.Extensions.Azure;
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddAzureClients(s =>
    {
        s.AddWebPubSubServiceClient(builder.Configuration["Azure:WebPubSub:ConnectionString"], "stream");
    });
    
    var app = builder.Build();
    app.UseStaticFiles();
    app.MapGet("/negotiate", async context =>
    {
        var service = context.RequestServices.GetRequiredService<WebPubSubServiceClient>();
        var response = new
        {
            url = service.GetClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
        };
        await context.Response.WriteAsJsonAsync(response);
    });
    
    app.Run();
    
  3. Erstellen der Webseite

    Erstellen Sie eine HTML-Seite mit folgendem Inhalt, und speichern Sie sie als wwwroot/index.html:

    <html>
      <body>
        <div id="output"></div>
        <script>
          (async function () {
            let res = await fetch('/negotiate')
            let data = await res.json();
            let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
            ws.onopen = () => {
              console.log('connected');
            };
    
            let output = document.querySelector('#output');
            ws.onmessage = event => {
              let d = document.createElement('p');
              d.innerText = event.data;
              output.appendChild(d);
            };
          })();
        </script>
      </body>
    </html>                                                                
    

    Der vorstehende Code stellt eine Verbindung mit dem Dienst her und gibt alle empfangenen Nachrichten auf der Seite aus. Die Hauptänderung besteht darin, dass wir das Unterprotokoll beim Erstellen der WebSocket-Verbindung angeben.

  4. Starten Sie den Server

    Wir verwenden das Tool Secret Manager für .NET Core, um die Verbindungszeichenfolge festzulegen. Führen Sie den folgenden Befehl aus, ersetzen Sie <connection_string> darin durch den Wert, den Sie im vorherigen Schritt abgerufen haben, und öffnen Sie http://localhost:5000/index.html im Browser:

    dotnet user-secrets init
    dotnet user-secrets set Azure:WebPubSub:ConnectionString "<connection-string>"
    dotnet run
    

    Wenn Sie Chrome verwenden, können Sie F12 drücken oder mit der rechten Maustaste –> Prüfen –>Entwicklertools klicken und die Registerkarte Netzwerk auswählen. Laden Sie die Website, und Sie können sehen, dass die WebSocket-Verbindung hergestellt wird. Wählen Sie diese Option aus, um die WebSocket-Verbindung zu überprüfen. Unten können Sie sehen, dass die folgende connected-Ereignismeldung beim Client empfangen wird. Sie sehen, dass Sie die für diesen Client generierte connectionId abrufen können.

    {"type":"system","event":"connected","userId":null,"connectionId":"<the_connection_id>"}
    

Sie sehen, dass Sie mithilfe des Unterprotokolls einige Metadaten der Verbindung abrufen können, wenn der Verbindungsstatus connected ist.

Der Client empfängt jetzt eine JSON-Nachricht anstelle eines Nur-Texts. JSON-Nachricht enthält weitere Informationen, z. B. Typ und Quelle der Nachricht. Sie können diese Informationen verwenden, um die Nachricht weiter zu verarbeiten. Sie können die Nachricht z. B. in einem anderen Format anzeigen, wenn sie von einer anderen Quelle stammt. Dies wird in späteren Abschnitten behandelt.

Veröffentlichen von Nachrichten vom Client

Wenn der Client im Tutorial zum Erstellen einer Chat-App eine Nachricht über eine WebSocket-Verbindung an den Web PubSub-Dienst sendet, löst der Dienst ein serverseitiges Benutzerereignis aus. Beim Unterprotokoll ist die Funktionalität des Clients größer, da eine JSON-Nachricht gesendet wird. So können beispielsweise Nachrichten über den Web PubSub-Dienst direkt vom Client aus für andere Clients veröffentlicht werden.

Dies ist nützlich, wenn Sie umfangreiche Daten in Echtzeit an andere Clients streamen möchten. Wir verwenden dieses Feature, um eine Protokollstreaminganwendung zu erstellen, die Konsolenprotokolle in Echtzeit an den Browser streamen kann.

  1. Erstellen des Streamingprogramms

    Erstellen Sie ein stream-Programm:

    mkdir stream
    cd stream
    dotnet new console
    

    Aktualisieren Sie Program.cs mit dem folgenden Inhalt:

    using System;
    using System.Net.Http;
    using System.Net.WebSockets;
    using System.Text;
    using System.Text.Json;
    using System.Threading.Tasks;
    
    namespace stream
    {
        class Program
        {
            private static readonly HttpClient http = new HttpClient();
            static async Task Main(string[] args)
            {
                // Get client url from remote
                var stream = await http.GetStreamAsync("http://localhost:5000/negotiate");
                var url = (await JsonSerializer.DeserializeAsync<ClientToken>(stream)).url;
                var client = new ClientWebSocket();
                client.Options.AddSubProtocol("json.webpubsub.azure.v1");
    
                await client.ConnectAsync(new Uri(url), default);
    
                Console.WriteLine("Connected.");
                var streaming = Console.ReadLine();
                while (streaming != null)
                {
                    if (!string.IsNullOrEmpty(streaming))
                    {
                        var message = JsonSerializer.Serialize(new
                        {
                            type = "sendToGroup",
                            group = "stream",
                            data = streaming + Environment.NewLine,
                        });
                        Console.WriteLine("Sending " + message);
                        await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, default);
                    }
    
                    streaming = Console.ReadLine();
                }
    
                await client.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default);
            }
    
            private sealed class ClientToken
            {
                public string url { get; set; }
            }
        }
    }
    
    

    Sie können sehen, dass es hier das neue Konzept einer „Gruppe“ gibt. Bei einer Gruppe handelt es sich um ein logisches Konzept in einem Hub, in dem Sie Nachrichten für eine Gruppe von Verbindungen veröffentlichen können. In einem Hub kann es mehrere Gruppen geben, und ein Client kann mehrere Gruppen gleichzeitig abonnieren. Bei Verwendung des Unterprotokolls können Sie die Veröffentlichung nur in einer Gruppe vornehmen, anstatt sie an den gesamten Hub zu übertragen. Weitere Informationen zu den Begriffen finden Sie in den Grundkonzepten.

  2. Da wir hier die Gruppe verwenden, müssen wir auch die Webseite index.html aktualisieren, um der Gruppe beizutreten, wenn die WebSocket-Verbindung im ws.onopen-Rückruf hergestellt wird.

    let ackId = 0;
    ws.onopen = () => {
      console.log('connected');
      ws.send(JSON.stringify({
        type: 'joinGroup',
        group: 'stream',
        ackId: ++ackId
      }));
    };
    

    Sie können sehen, dass der Client der Gruppe beitritt, indem eine Nachricht mit dem joinGroup-Typ gesendet wird.

  3. Aktualisieren Sie außerdem die ws.onmessage-Rückruflogik leicht, um die JSON-Antwort zu parsen und nur die Nachrichten aus der Gruppe stream auszugeben, sodass sie als Live-Stream-Ausgabe funktioniert.

    ws.onmessage = event => {
      let message = JSON.parse(event.data);
      if (message.type === 'message' && message.group === 'stream') {
        let d = document.createElement('span');
        d.innerText = message.data;
        output.appendChild(d);
        window.scrollTo(0, document.body.scrollHeight);
      }
    };
    
  4. Aus Sicherheitsgründen kann ein Client eine Gruppe standardmäßig nicht selbst veröffentlichen oder abonnieren. Sie haben also bemerkt, dass wir roles beim Generieren des Tokens für den Client festgelegt haben:

    Legen Sie roles wie unten beschrieben fest, wenn GenerateClientAccessUri in Startup.cs:

    service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" })
    
  5. Wenden Sie schließlich auch etwas Stil auf index.html an, damit es ansprechend dargestellt wird.

    <html>
    
      <head>
        <style>
          #output {
            white-space: pre;
            font-family: monospace;
          }
        </style>
      </head>
    

Führen Sie nun den folgenden Code aus, und geben Sie beliebigen Text ein. Dieser wird im Browser in Echtzeit angezeigt:

ls -R | dotnet run

# Or call `dir /s /b | dotnet run` when you are using CMD under Windows

Sie können die Anzeige auch verlangsamen, damit Sie sehen können, wie die Daten in Echtzeit an den Browser gestreamt werden:

for i in $(ls -R); do echo $i; sleep 0.1; done | dotnet run

Das vollständige Codebeispiel für dieses Tutorial finden Sie hier.

Nächste Schritte

In diesem Tutorial haben Sie grundlegende Informationen dazu erhalten, wie Sie über das Unterprotokoll eine Verbindung mit dem Web PubSub-Dienst herstellen und Nachrichten auf den verbundenen Clients veröffentlichen.

Sehen Sie sich weitere Tutorials an, um tiefer in die Nutzung des Diensts einzutauchen.