Share via


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

In build a chat app tutorial, you learn how to use WebSocket APIs to send and receive data with Azure Web PubSub. Sie sehen, dass kein Protokoll erforderlich ist, wenn der Client mit dem Dienst kommuniziert. Sie können z. B. einen beliebigen Datentyp senden WebSocket.send(), 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. den Ereignisnamen nicht angeben, wenn Sie das Ereignis an Ihren Server senden oder eine Nachricht an andere Clients veröffentlichen, anstatt sie an Ihren Server zu senden. In diesem Lernprogramm erfahren Sie, wie Sie unterprotocol 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 kein Azure-Abonnement haben, erstellen Sie ein kostenloses Azure-Konto, bevor Sie beginnen.

Voraussetzungen

  • Verwenden Sie die Bash-Umgebung in Azure Cloud Shell. Weitere Informationen finden Sie unter Schnellstart für Bash in Azure Cloud Shell.

  • Wenn Sie CLI-Referenzbefehle lieber lokal ausführen, installieren Sie die Azure CLI. Wenn Sie Windows oder macOS ausführen, sollten Sie die Azure CLI in einem Docker-Container ausführen. Weitere Informationen finden Sie unter Ausführen der Azure CLI in einem Docker-Container.

    • Wenn Sie eine lokale Installation verwenden, melden Sie sich mithilfe des Befehls az login bei der Azure CLI an. Führen Sie die in Ihrem Terminal angezeigten Schritte aus, um den Authentifizierungsprozess abzuschließen. Informationen zu anderen Anmeldeoptionen finden Sie unter Anmelden mit der Azure CLI.

    • Installieren Sie die Azure CLI-Erweiterung beim ersten Einsatz, wenn Sie dazu aufgefordert werden. Weitere Informationen zu Erweiterungen finden Sie unter Verwenden von Erweiterungen mit der Azure CLI.

    • Führen Sie az version aus, um die installierte Version und die abhängigen Bibliotheken zu ermitteln. Führen Sie az upgrade aus, um das Upgrade auf die aktuelle Version durchzuführen.

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

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 in den folgenden Beispielen <your-unique-resource-name> durch den Namen Ihrer Web PubSub-Instanz.

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.

Abrufen der Verbindungszeichenfolge zur späteren Verwendung

Wichtig

Eine Verbindungszeichenfolge enthält die Autorisierungsinformationen, die Ihre Anwendung für den Zugriff auf den Azure Web PubSub-Dienst benötigt. Der Zugriffsschlüssel in der Verbindungszeichenfolge ähnelt einem Stammkennwort für Ihren Dienst. Achten Sie in Produktionsumgebungen immer gut darauf, Ihre Zugriffsschlüssel zu schützen. Verwenden Sie Azure Key Vault zum sicheren Verwalten und Rotieren Ihrer Schlüssel. 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.

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 Verbinden ionString, und verwenden Sie später in diesem Lernprogramm 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. Installieren von Abhängigkeiten

    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 zum Generieren des Clientzugriffstokens mit /negotiate-Anforderungen.
    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. Ausführen des Servers

    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 auf ">-Inspect ->Developer Tools" klicken und die Registerkarte "Netzwerk " auswählen. Laden Sie die Webseite, und Sie können sehen, dass die WebSocket-Verbindung hergestellt wird. Wählen Sie diese Option aus, um die WebSocket-Verbindung zu überprüfen. Die folgende connected Ereignismeldung wird im Client empfangen. 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. Bei subprotocol verfügt der Client über mehr Funktionen, indem 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 eine große Datenmenge 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 hier ein neues Konzept "Gruppe" vorhanden ist. 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. Details zu den Begriffen finden Sie in des grundlegenden Konzepten.

  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 weiterhin die ws.onmessage-Rückruflogik geringfügig, um die JSON-Antwort zu analysieren und lediglich Nachrichten der stream-Gruppe auszugeben, sodass sie als Livestreamausgabe fungiert.

    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 beim Generieren des Tokens auf den Client festgelegt roles haben:

    Legen Sie ungefähr wie folgt roles in Startup.cs mit GenerateClientAccessUri fest:

    service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" })
    
  5. Wenden Sie schließlich eine Formatierung in index.html an, damit die Seite ansprechend angezeigt wird.

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

Führen Sie nun den folgenden Code aus, und geben Sie text ein, und sie werden 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 Lernprogramm erhalten Sie eine grundlegende Vorstellung davon, wie Sie eine Verbindung mit dem Web PubSub-Dienst herstellen und wie Sie Nachrichten mithilfe von Unterprotocol für die verbundenen Clients veröffentlichen.

Bearbeiten Sie weitere Tutorials, um mehr über die Nutzung des Diensts zu erfahren.