Freigeben über


Tutorial: Erstellen einer Chat-App mit dem Azure Web PubSub-Dienst

Im Tutorial Veröffentlichen und Abonnieren von Nachrichten lernen Sie die Grundlagen des Veröffentlichen und Abonnieren von Nachrichten mit Azure Web PubSub. In diesem Tutorial lernen Sie das Ereignissystem von Azure Web PubSub kennen und verwenden es, um eine vollständige Webanwendung mit Echtzeit-Kommunikationsfunktionen zu erstellen.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen einer Web PubSub-Dienstinstanz
  • Konfigurieren von Ereignishandlereinstellungen für Azure Web PubSub
  • Hanlde-Ereignisse auf dem App-Server und Erstellen einer Echtzeit-Chat-App

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 den abgerufenen ConnectionString und legen Sie ihn in die Umgebungsvariable WebPubSubConnectionString fest, die das Tutorial später liest. Ersetzen Sie <connection-string>, unten, durch die ConnectionString, die Sie abgerufen haben.

export WebPubSubConnectionString="<connection-string>"
SET WebPubSubConnectionString=<connection-string>

Einrichten des Projekts

Voraussetzungen

Erstellen der Anwendung

In Azure Web PubSub gibt es zwei Rollen: Server und Client. Dieses Konzept ähnelt den Server- und Clientrollen in einer Webanwendung. Der Server ist dafür verantwortlich, die Clients zu verwalten, zuzuhören und auf Clientnachrichten zu reagieren. Der Client ist dafür verantwortlich, die Nachrichten des Benutzers vom Server zu senden und zu empfangen und für den Endbenutzer zu visualisieren.

In diesem Tutorial erstellen wir eine Echtzeit-Chat-Webanwendung. In einer echten Webanwendung umfasst die Verantwortung des Servers auch die Authentifizierung von Clients und die Bereitstellung statischer Webseiten für die Benutzeroberfläche der Anwendung.

Wir verwenden ASP.NET Core 8, um die Webseiten zu hosten und eingehende Anfragen zu bearbeiten.

Erstellen wir zunächst eine ASP.NET Core Web App in einem chatapp-Ordner.

  1. Erstellen Sie eine neue Web-App.

    mkdir chatapp
    cd chatapp
    dotnet new web
    
  2. Fügen Sie app.UseStaticFiles() Program.cs hinzu, um das Hosting statischer Webseiten zu unterstützen.

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.UseStaticFiles();
    
    app.Run();
    
  3. Erstellen Sie eine HTML-Datei und speichern Sie diese unter wwwroot/index.html, wir verwenden sie später für die Benutzeroberfläche der Chat-App.

    <html>
      <body>
        <h1>Azure Web PubSub Chat</h1>
      </body>
    </html>
    

Sie können den Server testen, indem Sie dotnet run --urls http://localhost:8080 ausführen und http://localhost:8080/index.html im Browser aufrufen.

Hinzufügen eines Aushandlungsendpunkts

Im Tutorial Nachricht veröffentlichen und abonnieren verwendet der Abonnent die Verbindungszeichenfolge direkt. In einer realen Anwendung ist es nicht sicher, die Verbindungszeichenfolge für einen beliebigen Client freizugeben, da Verbindungszeichenfolgen über hohe Berechtigungen verfügen, um einen Vorgang für den Dienst auszuführen. Lassen Sie uns nun festlegen, dass Ihr Server die Verbindungszeichenfolge verwendet und einen negotiate-Endpunkt für den Client verfügbar macht, um die vollständige URL mit Zugriffstoken abzurufen. Auf diese Weise kann der Server vor dem negotiate-Endpunkt Authentifizierungs-Middleware hinzufügen, um nicht autorisierten Zugriff zu verhindern.

Installieren Sie zunächst die Abhängigkeiten.

dotnet add package Microsoft.Azure.WebPubSub.AspNetCore

Nun fügen wir einen /negotiate-Endpunkt für den Client hinzu, um das Token zu generieren.

using Azure.Core;
using Microsoft.Azure.WebPubSub.AspNetCore;
using Microsoft.Azure.WebPubSub.Common;
using Microsoft.Extensions.Primitives;

// Read connection string from environment
var connectionString = Environment.GetEnvironmentVariable("WebPubSubConnectionString");
if (connectionString == null)
{
    throw new ArgumentNullException(nameof(connectionString));
}

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddWebPubSub(o => o.ServiceEndpoint = new WebPubSubServiceEndpoint(connectionString))
    .AddWebPubSubServiceClient<Sample_ChatApp>();
var app = builder.Build();

app.UseStaticFiles();

// return the Client Access URL with negotiate endpoint
app.MapGet("/negotiate", (WebPubSubServiceClient<Sample_ChatApp> service, HttpContext context) =>
{
    var id = context.Request.Query["id"];
    if (StringValues.IsNullOrEmpty(id))
    {
        context.Response.StatusCode = 400;
        return null;
    }
    return new
    {
        url = service.GetClientAccessUri(userId: id).AbsoluteUri
    };
});
app.Run();

sealed class Sample_ChatApp : WebPubSubHub
{
}

AddWebPubSubServiceClient<THub>() wird verwendet, um den Dienstclient WebPubSubServiceClient<THub> einzufügen, mit dem im Aushandlungsschritt eine Clientverbindung generiert und in Hubmethoden verwendet werden kann, um Dienst-REST-APIs aufzurufen, wenn Hubereignisse ausgelöst werden. Dieser Code zum Generieren des Tokens ähnelt dem Code, den wir im Tutorial zum Veröffentlichen und Abonnieren von Nachrichten verwendet haben – abgesehen davon, dass wir beim Generieren des Tokens ein weiteres Argument (userId) übergeben. Mithilfe der Benutzer-ID kann der Client identifiziert werden, damit Sie beim Empfang einer Nachricht wissen, woher die Nachricht stammt.

Der Code liest die Verbindungszeichenfolge aus der Umgebungsvariable WebPubSubConnectionString, die wir im vorherigen Schritt festgelegt haben.

Führen Sie den Server erneut mit dotnet run --urls http://localhost:8080 aus.

Sie können diese API testen, indem Sie auf http://localhost:8080/negotiate?id=user1 zugreifen. Sie erhalten dann die vollständige URL des Azure Web PubSub mit einem Zugriffstoken.

Behandeln von Ereignissen

Wenn in Azure Web PubSub bestimmte Aktivitäten auf clientseitiger Seite auftreten (z. B. ein Client verbindet, verbunden, getrennt oder ein Client Nachrichten sendet), sendet der Dienst Benachrichtigungen an den Server, damit er auf diese Ereignisse reagieren kann.

Ereignisse werden in Form eines Webhooks an den Server übermittelt. Der Webhook wird vom Anwendungsserver verarbeitet und verfügbar gemacht und auf der Dienstseite von Azure Web PubSub registriert. Der Dienst ruft die Webhooks immer dann auf, wenn ein Ereignis eintritt.

Azure Web PubSub beschreibt die Ereignisdaten gemäß CloudEvents.

Nachfolgend behandeln wir connected-Systemereignisse, wenn ein Client verbunden ist und Benutzerereignisse verarbeitet message, wenn ein Client Nachrichten sendet, um die Chat-App zu erstellen.

Das Web PubSub SDK für AspNetCore Microsoft.Azure.WebPubSub.AspNetCore, das wir im vorherigen Schritt installiert haben, kann auch dazu beitragen, die CloudEvents-Anforderungen zu analysieren und zu verarbeiten.

Fügen Sie zunächst Ereignishandler vor app.Run() ein. Geben Sie den Endpunktpfad für die Ereignisse an, beispielsweise /eventhandler.

app.MapWebPubSubHub<Sample_ChatApp>("/eventhandler/{*path}");
app.Run();

Fügen Sie nun innerhalb der Klasse Sample_ChatApp, die wir im vorherigen Schritt erstellt haben, einen Konstruktor hinzu, mit WebPubSubServiceClient<Sample_ChatApp> dem wir den Web PubSub-Dienst aufrufen. Und OnConnectedAsync(), um zu reagieren, wenn das connected-Ereignis ausgelöst wird, OnMessageReceivedAsync() um Nachrichten vom Client zu behandeln.

sealed class Sample_ChatApp : WebPubSubHub
{
    private readonly WebPubSubServiceClient<Sample_ChatApp> _serviceClient;

    public Sample_ChatApp(WebPubSubServiceClient<Sample_ChatApp> serviceClient)
    {
        _serviceClient = serviceClient;
    }

    public override async Task OnConnectedAsync(ConnectedEventRequest request)
    {
        Console.WriteLine($"[SYSTEM] {request.ConnectionContext.UserId} joined.");
    }

    public override async ValueTask<UserEventResponse> OnMessageReceivedAsync(UserEventRequest request, CancellationToken cancellationToken)
    {
        await _serviceClient.SendToAllAsync(RequestContent.Create(
        new
        {
            from = request.ConnectionContext.UserId,
            message = request.Data.ToString()
        }),
        ContentType.ApplicationJson);

        return new UserEventResponse();
    }
}

In dem obigen Code verwenden wir den Service-Client, um eine Benachrichtigung im JSON-Format an alle zu senden, die sich mit SendToAllAsync verknüpfen.

Aktualisieren Sie die Webseite

Nun aktualisieren wir index.html, um die Logik zum Verbinden, Senden von Nachrichten und Anzeigen empfangener Nachrichten auf der Seite hinzuzufügen.

<html>
  <body>
    <h1>Azure Web PubSub Chat</h1>
    <input id="message" placeholder="Type to chat...">
    <div id="messages"></div>
    <script>
      (async function () {
        let id = prompt('Please input your user name');
        let res = await fetch(`/negotiate?id=${id}`);
        let data = await res.json();
        let ws = new WebSocket(data.url);
        ws.onopen = () => console.log('connected');

        let messages = document.querySelector('#messages');
        
        ws.onmessage = event => {
          let m = document.createElement('p');
          let data = JSON.parse(event.data);
          m.innerText = `[${data.type || ''}${data.from || ''}] ${data.message}`;
          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>

Sie können im obigen Code sehen, den wir verbinden, die systemeigene WebSocket-API im Browser verwenden WebSocket.send() und zum Senden von Nachrichten und WebSocket.onmessage zum Abhören empfangener Nachrichten verwendet werden.

Sie können auch Client-SDKs verwenden, um eine Verbindung mit dem Dienst herzustellen, was Ihnen die automatische Wiederherstellung, Fehlerbehandlung und vieles mehr ermöglicht.

Es gibt jetzt einen Schritt, damit der Chat funktioniert. Lassen Sie uns konfigurieren, welche Ereignisse uns wichtig sind und an welche Ereignisse im Web PubSub-Dienst gesendet werden sollen.

Einrichten des Ereignishandlers

Wir legen den Ereignishandler im Web PubSub-Dienst fest, um dem Dienst mitzuteilen, an welchen Ort die Ereignisse gesendet werden sollen.

Wenn der Webserver lokal ausgeführt wird, wie der Web PubSub-Dienst den Localhost aufruft, wenn er keinen Endpunkt mit Internetzugriff hat? In der Regel gibt es zwei Möglichkeiten. Eine besteht darin, localhost über ein allgemeines Tunneltool für die Öffentlichkeit verfügbar zu machen, und die andere besteht darin , AWP-Tunnel zum Tunneln des Datenverkehrs vom Web PubSub-Dienst über das Tool zu Ihrem lokalen Server zu verwenden.

In diesem Abschnitt verwenden wir Azure CLI, um die Ereignishandler festzulegen und AWP-Tunnel zum Weiterleiten von Datenverkehr an Localhost zu verwenden.

Konfigurieren von Hubeinstellungen

Wir legen die URL-Vorlage so fest, dass das Schema verwendet tunnel wird, sodass Web PubSub Nachrichten über die awps-tunnelTunnelverbindung leitet. Ereignishandler können entweder über das Portal oder über die CLI festgelegt werden, wie in diesem Artikel beschrieben. Hier wird die CLI verwendet. Da Ereignisse im Pfad /eventhandler als vorherige Schrittsätze überwacht werden, legen wir die URL-Vorlage auf tunnel:///eventhandler.

Verwenden Sie den Azure CLI-Befehl az webpubsub hub create, um die Ereignishandlereinstellungen für den Sample_ChatApp-Hub zu erstellen.

Wichtig

Ersetzen Sie <your-unique-resource-name> durch den Namen Ihrer Web PubSub-Instanz, die in den vorherigen Schritten erstellt wurde.

az webpubsub hub create -n "<your-unique-resource-name>" -g "myResourceGroup" --hub-name "Sample_ChatApp" --event-handler url-template="tunnel:///eventhandler" user-event-pattern="*" system-event="connected"

Lokales Ausführen eines AWP-Tunnels

Herunterladen und Installieren des AWP-Tunnels

Das Tool wird auf Node.js Version 16 oder höher ausgeführt.

npm install -g @azure/web-pubsub-tunnel-tool

Verwenden der Dienstverbindungszeichenfolge und Ausführen

export WebPubSubConnectionString="<your connection string>"
awps-tunnel run --hub Sample_ChatApp --upstream http://localhost:8080

Ausführen des Webservers

Jetzt ist alles festgelegt. Lassen Sie uns den Webserver ausführen und mit der Chat-App in Aktion spielen.

Führen Sie nun den Server mit dotnet run --urls http://localhost:8080.

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

Öffnen Sie http://localhost:8080/index.html. Sie können Ihren Benutzernamen eingeben und mit dem Chatten beginnen.

Verzögerte Authentifizierung mit dem connect-Ereignishandler

In vorherigen Abschnitten wurde veranschaulicht, wie der Aushandlungsendpunkt zum Zurückgeben der Web PubSub-Dienst-URL und des JWT-Zugriffstokens für die Clients zum Herstellen einer Verbindung mit dem Web PubSub-Dienst verwendet wird. In einigen Fällen, z. B. bei Edgegeräten mit eingeschränkten Ressourcen, bevorzugen Clients möglicherweise eine direkte Verbindung mit Web PubSub-Ressourcen. In solchen Fällen können Sie den connect-Ereignishandler konfigurieren, um eine verzögerte Authentifizierung für die Clients auszuführen, den Clients eine Benutzer-ID zuzuweisen, die Gruppen anzugeben, denen Clients nach der Verbindungsherstellung beitreten, die Berechtigungen der Clients zu konfigurieren und das WebSocket-Unterprotokoll als WebSocket-Antwort für den Client zu konfigurieren usw. Details finden Sie in der Spezifikation zum connect-Ereignishandler.

Verwenden Sie nun den connect-Ereignishandler, um ein ähnliches Ergebnis wie mit dem Abschnitt negotiate zu erzielen.

Aktualisieren der Hubeinstellungen

Zunächst aktualisieren Sie Hubeinstellungen, um auch den connect-Ereignishandler einzuschließen. Darüber hinaus müssen Sie anonyme Verbindungen zulassen, damit Clients ohne JWT-Zugriffstoken eine Verbindung mit dem Dienst herstellen können.

Verwenden Sie den Azure CLI-Befehl az webpubsub hub update, um die Ereignishandlereinstellungen für den Sample_ChatApp-Hub zu erstellen.

Wichtig

Ersetzen Sie <your-unique-resource-name> durch den Namen Ihrer Web PubSub-Instanz, die in den vorherigen Schritten erstellt wurde.

az webpubsub hub update -n "<your-unique-resource-name>" -g "myResourceGroup" --hub-name "Sample_ChatApp" --allow-anonymous true --event-handler url-template="tunnel:///eventhandler" user-event-pattern="*" system-event="connected" system-event="connect"

Aktualisieren der Upstreamlogik zum Behandeln des connect-Ereignisses

Aktualisieren Sie nun die Upstreamlogik zum Behandeln des connect-Ereignisses. Sie können jetzt auch den Aushandlungsendpunkt entfernen.

Ähnlich wie beim Aushandlungsendpunkt zu Demozwecken lesen Sie auch die ID aus den Abfrageparametern. Beim connect-Ereignis wird die ursprüngliche Clientabfrage im Anforderungstext des connect-Ereignisses beibehalten.

Überschreiben Sie in der Klasse Sample_ChatApp das OnConnectAsync()-Element, um das connect-Ereignis zu behandeln:

sealed class Sample_ChatApp : WebPubSubHub
{
    private readonly WebPubSubServiceClient<Sample_ChatApp> _serviceClient;

    public Sample_ChatApp(WebPubSubServiceClient<Sample_ChatApp> serviceClient)
    {
        _serviceClient = serviceClient;
    }

    public override ValueTask<ConnectEventResponse> OnConnectAsync(ConnectEventRequest request, CancellationToken cancellationToken)
    {
        if (request.Query.TryGetValue("id", out var id))
        {
            return new ValueTask<ConnectEventResponse>(request.CreateResponse(userId: id.FirstOrDefault(), null, null, null));
        }

        // The SDK catches this exception and returns 401 to the caller
        throw new UnauthorizedAccessException("Request missing id");
    }

    public override async Task OnConnectedAsync(ConnectedEventRequest request)
    {
        Console.WriteLine($"[SYSTEM] {request.ConnectionContext.UserId} joined.");
    }

    public override async ValueTask<UserEventResponse> OnMessageReceivedAsync(UserEventRequest request, CancellationToken cancellationToken)
    {
        await _serviceClient.SendToAllAsync(RequestContent.Create(
        new
        {
            from = request.ConnectionContext.UserId,
            message = request.Data.ToString()
        }),
        ContentType.ApplicationJson);

        return new UserEventResponse();
    }
}

Aktualisieren von „index.html“ zur Nutzung der direkten Verbindung

Aktualisieren Sie nun die Webseite so, dass eine direkte Verbindung mit dem Web PubSub-Dienst hergestellt wird. Zu erwähnen ist, dass der Web PubSub-Dienstendpunkt zu Demozwecken jetzt im Clientcode hartcodiert ist. Aktualisieren Sie den Diensthostnamen <the host name of your service> im folgenden HTML-Code mit dem Wert aus Ihrem eigenen Dienst. Möglicherweise ist es dennoch hilfreich, den Wert des Web PubSub-Dienstendpunkts von Ihrem Server abzurufen. Dadurch erhalten Sie mehr Flexibilität und Kontrolle darüber, wo der Client eine Verbindung herstellt.

<html>
  <body>
    <h1>Azure Web PubSub Chat</h1>
    <input id="message" placeholder="Type to chat...">
    <div id="messages"></div>
    <script>
      (async function () {
        // sample host: mock.webpubsub.azure.com
        let hostname = "<the host name of your service>";
        let id = prompt('Please input your user name');
        let ws = new WebSocket(`wss://${hostname}/client/hubs/Sample_ChatApp?id=${id}`);
        ws.onopen = () => console.log('connected');

        let messages = document.querySelector('#messages');
        
        ws.onmessage = event => {
          let m = document.createElement('p');
          let data = JSON.parse(event.data);
          m.innerText = `[${data.type || ''}${data.from || ''}] ${data.message}`;
          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>

Erneutes Ausführen des Servers

Führen Sie jetzt den Server erneut aus, und rufen Sie die Webseite gemäß den vorherigen Anweisungen auf. Wenn Sie awps-tunnel beendet haben, führen Sie auch das Tunneltool erneut aus.

Nächste Schritte

Dieses Tutorial vermittelt Ihnen eine grundlegende Vorstellung davon, wie das Ereignissystem im Azure Web PubSub Service funktioniert.

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