Sdílet prostřednictvím


Kurz: Vytvoření chatovací aplikace pomocí služby Azure Web PubSub

V kurzu Publikování a přihlášení k odběru zpráv se naučíte základy publikování a přihlášení k odběru zpráv pomocí azure Web PubSub. V tomto kurzu se seznámíte se systémem událostí Azure Web PubSub a použijete ho k vytvoření kompletní webové aplikace s funkcemi komunikace v reálném čase.

V tomto kurzu se naučíte:

  • Vytvoření instance služby Web PubSub
  • Konfigurace nastavení obslužné rutiny události pro Azure Web PubSub
  • Zpracování událostí na aplikačním serveru a vytvoření chatovací aplikace v reálném čase

Pokud ještě nemáte předplatné Azure, vytvořte si bezplatný účet Azure před tím, než začnete.

Požadavky

  • Tato instalace vyžaduje verzi 2.22.0 nebo vyšší rozhraní příkazového řádku Azure CLI. Pokud používáte Azure Cloud Shell, je už nainstalovaná nejnovější verze.

Vytvoření instance Azure Web PubSub

Vytvoření skupiny zdrojů

Skupina prostředků je logický kontejner, ve kterém se nasazují a spravují prostředky Azure. Pomocí příkazu az group create vytvořte skupinu prostředků s názvem myResourceGroup v eastus umístění.

az group create --name myResourceGroup --location EastUS

Vytvoření instance Web PubSub

Spuštěním příkazu az extension add nainstalujte nebo upgradujte rozšíření webpubsub na aktuální verzi.

az extension add --upgrade --name webpubsub

Pomocí příkazu az webpubsub az webpubsub vytvořte web pubSub ve skupině prostředků, kterou jste vytvořili. Následující příkaz vytvoří prostředek Free Web PubSub ve skupině prostředků myResourceGroup v eastUS:

Důležité

Každý prostředek Web PubSub musí mít jedinečný název. V následujících příkladech nahraďte <název_prostředku-unique-resource názvem> podsítě Web PubSub.

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

Výstup tohoto příkazu zobrazuje vlastnosti nově vytvořeného prostředku. Poznamenejte si hodnoty dvou vlastností uvedených níže:

  • Název prostředku: Název, který jste zadali výše uvedenému parametru --name .
  • hostName: V příkladu je <your-unique-resource-name>.webpubsub.azure.com/název hostitele .

V tuto chvíli je váš účet Azure jediným autorizovaným k provádění jakýchkoli operací s tímto novým prostředkem.

Získání připojovacího řetězce pro budoucí použití

Důležité

Nezpracované připojovací řetězec se v tomto článku zobrazují jenom pro demonstrační účely.

Připojovací řetězec obsahuje informace o autorizaci vyžadované pro vaši aplikaci pro přístup ke službě Azure Web PubSub. Přístupový klíč uvnitř připojovací řetězec je podobný kořenovému heslu pro vaši službu. V produkčních prostředích vždy chraňte přístupové klíče. Pomocí služby Azure Key Vault můžete bezpečně spravovat a obměňovat klíče a zabezpečit připojení WebPubSubServiceClient.

Vyhněte se distribuci přístupových klíčů ostatním uživatelům, jejich pevnému kódování nebo jejich uložení kdekoli ve formátu prostého textu, který je přístupný ostatním uživatelům. Otočte klíče, pokud se domníváte, že mohly být ohroženy.

K získání připojovacího řetězce služby použijte příkaz azure CLI az webpubsub key. <your-unique-resource-name> Zástupný symbol nahraďte názvem vaší instance Azure Web PubSub.

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

Zkopírujte připojovací řetězec pro pozdější použití.

Zkopírujte načtený ConnectionString a nastavte ho do proměnné WebPubSubConnectionStringprostředí, kterou si kurz později přečte. Nahraďte <connection-string> ho řetězcem ConnectionString , který jste načítáli.

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

Nastavení projektu

Požadavky

Vytvoření aplikace

Ve službě Azure Web PubSub existují dvě role, server a klient. Tento koncept se podobá rolím serveru a klienta ve webové aplikaci. Server zodpovídá za správu klientů, naslouchání a odpovídá na zprávy klientů. Klient zodpovídá za odesílání a přijímání zpráv uživatele ze serveru a jejich vizualizaci pro koncového uživatele.

V tomto kurzu vytvoříme webovou aplikaci chatu v reálném čase. V reálné webové aplikaci také odpovědnost serveru zahrnuje ověřování klientů a obsluhu statických webových stránek pro uživatelské rozhraní aplikace.

K hostování webových stránek a zpracování příchozích požadavků používáme ASP.NET Core 8 .

Nejprve vytvoříme webovou aplikaci ASP.NET Core ve chatapp složce.

  1. Vytvořte novou webovou aplikaci.

    mkdir chatapp
    cd chatapp
    dotnet new web
    
  2. Přidejte app.UseStaticFiles() Program.cs pro podporu hostování statických webových stránek.

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.UseStaticFiles();
    
    app.Run();
    
  3. Vytvořte soubor HTML a uložte ho jako wwwroot/index.html, použijeme ho pro uživatelské rozhraní chatovací aplikace později.

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

Server můžete otestovat spuštěním dotnet run --urls http://localhost:8080 a přístupem http://localhost:8080/index.html v prohlížeči.

Přidání koncového bodu negotiate

V kurzu Publikovat a přihlásit se k odběru zprávy, odběratel využívá připojovací řetězec přímo. V reálné aplikaci není bezpečné sdílet připojovací řetězec s žádným klientem, protože připojovací řetězec má vysoké oprávnění k provedení jakékoli operace se službou. Teď vezměme server, který využívá připojovací řetězec, a vystavení koncového negotiate bodu pro klienta, aby získal úplnou adresu URL s přístupovým tokenem. Server tak může před koncový bod přidat ověřovací middleware negotiate , aby se zabránilo neoprávněnému přístupu.

Nejprve nainstalujte závislosti.

dotnet add package Microsoft.Azure.WebPubSub.AspNetCore

Teď přidáme /negotiate koncový bod pro volání klienta pro vygenerování tokenu.

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>() se používá k vložení klienta WebPubSubServiceClient<THub>služby, se kterým můžeme v kroku vyjednávání vygenerovat token připojení klienta a v metodách centra k vyvolání rozhraní REST API služby při aktivaci událostí centra. Tento kód generování tokenu je podobný kódu, který jsme použili v kurzu k publikování a odběru zpráv, s výjimkou toho, že při generování tokenu předáme jeden další argument (userId). ID uživatele lze použít k identifikaci identity klienta, takže když obdržíte zprávu, ze které víte, odkud zpráva pochází.

Kód čte připojovací řetězec z proměnné WebPubSubConnectionString prostředí, kterou jsme nastavili v předchozím kroku.

Znovu spusťte server pomocí dotnet run --urls http://localhost:8080.

Toto rozhraní API můžete otestovat tak, že ho otevřete http://localhost:8080/negotiate?id=user1 a získáte úplnou adresu URL podsítě Azure Web PubSub s přístupovým tokenem.

Zpracování událostí

Pokud na straně klienta dojde k určitým aktivitám v podsítě Azure Web PubSub (například klient se připojuje, připojuje, odpojí nebo odesílá zprávy), služba odesílá oznámení na server, aby na tyto události reagovala.

Události se doručují na server ve formě Webhooku. Webhook obsluhuje a vystavuje aplikační server a je zaregistrovaný na straně služby Azure Web PubSub. Služba vyvolá webhooky vždy, když dojde k události.

Azure Web PubSub sleduje CloudEvents a popisuje data událostí.

Níže zpracováváme connected systémové události při připojení klienta a zpracování message uživatelských událostí, když klient odesílá zprávy pro sestavení chatovací aplikace.

Sada Web PubSub SDK pro AspNetCore Microsoft.Azure.WebPubSub.AspNetCore , která jsme nainstalovali v předchozím kroku, může také pomoct analyzovat a zpracovávat požadavky CloudEvents.

Nejprve přidejte obslužné rutiny událostí před app.Run(). Zadejte cestu koncového bodu pro události, řekněme /eventhandler.

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

Teď do třídy Sample_ChatApp , kterou jsme vytvořili v předchozím kroku, přidejte konstruktor pro práci s WebPubSubServiceClient<Sample_ChatApp> tím, který používáme k vyvolání služby Web PubSub. A OnConnectedAsync() reagovat, když connected se událost aktivuje, OnMessageReceivedAsync() aby se zpracovávaly zprávy z klienta.

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();
    }
}

Ve výše uvedeném kódu používáme klienta služby k vysílání zprávy s oznámením ve formátu JSON všem, s kým je připojen SendToAllAsync.

Aktualizace webové stránky

Teď aktualizujeme index.html , abychom přidali logiku pro připojení, odeslání zprávy a zobrazení přijatých zpráv na stránce.

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

Ve výše uvedeném kódu se připojujeme pomocí nativního rozhraní WebSocket API v prohlížeči a používáme WebSocket.send() k odesílání zpráv a WebSocket.onmessage naslouchání přijatým zprávám.

Klientské sady SDK můžete také použít k připojení ke službě, což vám umožní automatické opětovné připojení, zpracování chyb a další možnosti.

Teď zbývá ještě jeden krok, aby chat fungoval. Pojďme nakonfigurovat, na jakých událostech záleží a kam se mají události odesílat ve službě Web PubSub.

Nastavení obslužné rutiny události

Obslužnou rutinu události ve službě Web PubSub nastavíme tak, aby službě řekla, kam se mají události odesílat.

Když se webový server spustí místně, jak služba Web PubSub vyvolá localhost, pokud nemá žádný koncový bod přístupný z internetu? Existují obvykle dva způsoby. Jedním z nich je zveřejnění místního hostitele pro veřejnost pomocí některého obecného tunelového nástroje a druhý je použít tunel upws-tunnel k tunelování provozu ze služby Web PubSub prostřednictvím nástroje na místní server.

V této části pomocí Azure CLI nastavíme obslužné rutiny událostí a pomocí tunelu awps-tunnel směrujeme provoz do místního hostitele.

Konfigurace nastavení centra

Šablonu adresy URL jsme nastavili tak, aby používala tunnel schéma, aby web PubSub směruje zprávy prostřednictvím tunelového awps-tunnelpřipojení. Obslužné rutiny událostí je možné nastavit z portálu nebo rozhraní příkazového řádku, jak je popsáno v tomto článku. Tady je nastavíme prostřednictvím rozhraní příkazového řádku. Vzhledem k tomu, že nasloucháme událostem v cestě /eventhandler jako předchozí sady kroků, nastavíme šablonu url na tunnel:///eventhandler.

Pomocí příkazu az webpubsub hub az webpubsub hub vytvořte nastavení obslužné rutiny události pro Sample_ChatApp centrum.

Důležité

Nahraďte <název-jedinečný-prostředek> názvem prostředku Web PubSub vytvořeným z předchozích kroků.

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"

Místní spuštění tunelu awps

Stažení a instalace tunelu awps-tunnel

Nástroj běží na Node.js verze 16 nebo vyšší.

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

Použití připojovací řetězec služby a spuštění

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

Spuštění webového serveru

Teď je všechno nastavené. Pojďme spustit webový server a hrát s chatovací aplikací v akci.

Nyní spusťte server pomocí dotnet run --urls http://localhost:8080příkazu .

Kompletní vzorový kód tohoto kurzu najdete tady.

Otevře záznam typu http://localhost:8080/index.html. Můžete zadat svoje uživatelské jméno a začít chatovat.

Opožděné ověřování s obslužnou rutinou connect události

V předchozích částech si ukážeme, jak pomocí koncového bodu vyjednat vrátit adresu URL služby Web PubSub a přístupový token JWT pro klienty pro připojení ke službě Web PubSub. V některých případech můžou například hraniční zařízení s omezenými prostředky upřednostňovat přímé připojení k prostředkům Web PubSub. V takových případech můžete nakonfigurovat connect obslužnou rutinu události tak, aby opožděně ověřovali klienty, přiřaďte klientům ID uživatele, určete skupiny, ke kterým se klienti připojují, nakonfigurujte oprávnění, která mají klienti, a subprotocol protokolu WebSocket jako odpověď protokolu WebSocket na klienta atd. Podrobnosti najdete v části o připojení specifikace obslužné rutiny události.

Teď použijeme connect obslužnou rutinu události k dosažení podobného oddílu negotiate .

Aktualizace nastavení centra

Nejprve aktualizujeme nastavení centra tak, aby zahrnovala connect také obslužnou rutinu událostí, musíme také povolit anonymní připojení, aby se klienti bez přístupového tokenu JWT mohli připojit ke službě.

Pomocí příkazu Azure CLI az webpubsub hub update vytvořte nastavení obslužné rutiny události pro Sample_ChatApp centrum.

Důležité

Nahraďte <název-jedinečný-prostředek> názvem prostředku Web PubSub vytvořeným z předchozích kroků.

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"

Aktualizace upstreamové logiky pro zpracování události připojení

Teď aktualizujeme upstreamovou logiku pro zpracování události připojení. Teď bychom mohli koncový bod vyjednat také odebrat.

Podobně jako vyjednání koncového bodu jako ukázkového účelu čteme ID také z parametrů dotazu. V případě připojení se původní dotaz klienta zachová v textu žádosti o událost připojení.

Uvnitř třídy Sample_ChatApppřepsání OnConnectAsync() pro zpracování connect události:

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();
    }
}

Aktualizace index.html pro přímé připojení

Teď aktualizujeme webovou stránku tak, aby se přímo připojila ke službě Web PubSub. Jednou z věcí, kterou je třeba zmínit, je, že teď pro účely ukázky je koncový bod služby Web PubSub pevně zakódovaný do klientského kódu, aktualizujte název <the host name of your service> hostitele služby v následujícím html s hodnotou z vlastní služby. Může být stále užitečné načíst hodnotu koncového bodu služby Web PubSub z vašeho serveru. To vám dává větší flexibilitu a možnosti kontroly, ke které se klient připojuje.

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

Opětovné spuštění serveru

Teď znovu spusťte server a přejděte na webovou stránku podle pokynů před. Pokud jste zastavili awps-tunnel, spusťte prosím znovu nástroj tunelu.

Další kroky

V tomto kurzu získáte základní představu o fungování systému událostí ve službě Azure Web PubSub.

Projděte si další kurzy, ve které se dozvíte, jak službu používat.