Samouczek: tworzenie aplikacji do czatu za pomocą usługi Azure Web PubSub
W samouczku Publikowanie i subskrybowanie komunikatów poznasz podstawy publikowania i subskrybowania komunikatów za pomocą usługi Azure Web PubSub. W tym samouczku poznasz system zdarzeń usługi Azure Web PubSub i użyjesz go do utworzenia kompletnej aplikacji internetowej z funkcją komunikacji w czasie rzeczywistym.
Z tego samouczka dowiesz się, jak wykonywać następujące czynności:
- Tworzenie wystąpienia usługi Web PubSub
- Konfigurowanie ustawień programu obsługi zdarzeń dla usługi Azure Web PubSub
- Zdarzenia Hanlde na serwerze aplikacji i tworzenie aplikacji czatu w czasie rzeczywistym
Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto platformy Azure.
Wymagania wstępne
Użyj środowiska powłoki Bash w usłudze Azure Cloud Shell. Aby uzyskać więcej informacji, zobacz Szybki start dotyczący powłoki Bash w usłudze Azure Cloud Shell.
Jeśli wolisz uruchamiać polecenia referencyjne interfejsu wiersza polecenia lokalnie, zainstaluj interfejs wiersza polecenia platformy Azure. Jeśli korzystasz z systemu Windows lub macOS, rozważ uruchomienie interfejsu wiersza polecenia platformy Azure w kontenerze Docker. Aby uzyskać więcej informacji, zobacz Jak uruchomić interfejs wiersza polecenia platformy Azure w kontenerze platformy Docker.
Jeśli korzystasz z instalacji lokalnej, zaloguj się do interfejsu wiersza polecenia platformy Azure za pomocą polecenia az login. Aby ukończyć proces uwierzytelniania, wykonaj kroki wyświetlane w terminalu. Aby uzyskać inne opcje logowania, zobacz Logowanie się przy użyciu interfejsu wiersza polecenia platformy Azure.
Po wyświetleniu monitu zainstaluj rozszerzenie interfejsu wiersza polecenia platformy Azure podczas pierwszego użycia. Aby uzyskać więcej informacji na temat rozszerzeń, zobacz Korzystanie z rozszerzeń w interfejsie wiersza polecenia platformy Azure.
Uruchom polecenie az version, aby znaleźć zainstalowane wersje i biblioteki zależne. Aby uaktualnić do najnowszej wersji, uruchom polecenie az upgrade.
- Ta konfiguracja wymaga wersji 2.22.0 lub nowszej interfejsu wiersza polecenia platformy Azure. W przypadku korzystania z usługi Azure Cloud Shell najnowsza wersja jest już zainstalowana.
Tworzenie wystąpienia usługi Azure Web PubSub
Tworzenie grupy zasobów
Grupa zasobów to logiczny kontener przeznaczony do wdrażania zasobów platformy Azure i zarządzania nimi. Użyj polecenia az group create, aby utworzyć grupę zasobów o nazwie myResourceGroup
w eastus
lokalizacji.
az group create --name myResourceGroup --location EastUS
Tworzenie wystąpienia usługi Web PubSub
Uruchom polecenie az extension add , aby zainstalować lub uaktualnić rozszerzenie webpubsub do bieżącej wersji.
az extension add --upgrade --name webpubsub
Użyj polecenia az webpubsub create interfejsu wiersza polecenia platformy Azure, aby utworzyć internetowy pubSub w utworzonej grupie zasobów. Następujące polecenie tworzy zasób Free Web PubSub w grupie zasobów myResourceGroup w regionie EastUS:
Ważne
Każdy zasób Web PubSub musi mieć unikatową nazwę. Zastąp <ciąg your-unique-resource-name> nazwą usługi Web PubSub w poniższych przykładach.
az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1
Dane wyjściowe tego polecenia pokazują właściwości nowo utworzonego zasobu. Zanotuj dwie poniższe właściwości:
- Nazwa zasobu: nazwa podana powyżej parametru
--name
. - hostName: w przykładzie nazwa hosta to
<your-unique-resource-name>.webpubsub.azure.com/
.
W tym momencie Twoje konto platformy Azure jest jedynym autoryzowanym do wykonywania jakichkolwiek operacji na tym nowym zasobie.
Pobieranie Połączenie ionString do użycia w przyszłości
Ważne
Parametry połączenia zawiera informacje o autoryzacji wymagane przez aplikację w celu uzyskania dostępu do usługi Azure Web PubSub. Klucz dostępu wewnątrz parametry połączenia jest podobny do hasła głównego usługi. W środowiskach produkcyjnych należy zawsze zachować ostrożność w celu ochrony kluczy dostępu. Usługa Azure Key Vault umożliwia bezpieczne zarządzanie kluczami i obracanie ich. Unikaj dystrybuowania kluczy dostępu do innych użytkowników, kodowania ich lub zapisywania ich w dowolnym miejscu w postaci zwykłego tekstu, który jest dostępny dla innych użytkowników. Obracanie kluczy, jeśli uważasz, że mogły one zostać naruszone.
Użyj polecenia az webpubsub key interfejsu wiersza polecenia platformy Azure, aby uzyskać Połączenie ionString usługi. Zastąp <your-unique-resource-name>
symbol zastępczy nazwą wystąpienia usługi Azure Web PubSub.
az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv
Skopiuj parametry połączenia do późniejszego użycia.
Skopiuj pobrany Połączenie ionString i ustaw go w zmiennej środowiskowej WebPubSubConnectionString
, którą później odczytuje samouczek. Zastąp <connection-string>
poniżej pobranym ciągiem Połączenie ionString.
export WebPubSubConnectionString="<connection-string>"
SET WebPubSubConnectionString=<connection-string>
Konfigurowanie projektu
Wymagania wstępne
Tworzenie aplikacji
W usłudze Azure Web PubSub istnieją dwie role, serwer i klient. Ta koncepcja jest podobna do ról serwera i klienta w aplikacji internetowej. Serwer jest odpowiedzialny za zarządzanie klientami, nasłuchiwanie i odpowiadanie na komunikaty klienta. Klient jest odpowiedzialny za wysyłanie i odbieranie komunikatów użytkownika z serwera i wizualizowanie ich dla użytkownika końcowego.
W tym samouczku utworzymy aplikację internetową do czatu w czasie rzeczywistym. W prawdziwej aplikacji internetowej odpowiedzialność serwera obejmuje również uwierzytelnianie klientów i obsługę statycznych stron internetowych dla interfejsu użytkownika aplikacji.
Używamy ASP.NET Core 8 do hostowania stron internetowych i obsługi żądań przychodzących.
Najpierw utwórzmy aplikację internetową ASP.NET Core w folderze chatapp
.
Utwórz nową aplikację internetową.
mkdir chatapp cd chatapp dotnet new web
Dodaj
app.UseStaticFiles()
Program.cs do obsługi hostowania statycznych stron internetowych.var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseStaticFiles(); app.Run();
Utwórz plik HTML i zapisz go jako
wwwroot/index.html
, użyjemy go do interfejsu użytkownika aplikacji czatu później.<html> <body> <h1>Azure Web PubSub Chat</h1> </body> </html>
Serwer można przetestować, uruchamiając polecenie dotnet run --urls http://localhost:8080
i dostęp http://localhost:8080/index.html
w przeglądarce.
Dodawanie negocjowanego punktu końcowego
W samouczku Publikowanie i subskrybowanie subskrybent korzysta bezpośrednio z parametry połączenia. W rzeczywistej aplikacji nie można bezpiecznie udostępniać parametry połączenia żadnemu klientowi, ponieważ parametry połączenia ma wysokie uprawnienia do wykonywania dowolnej operacji w usłudze. Teraz serwer korzysta z parametry połączenia i uwidacznia negotiate
punkt końcowy dla klienta, aby uzyskać pełny adres URL z tokenem dostępu. W taki sposób serwer może dodać oprogramowanie pośredniczące uwierzytelniania przed negotiate
punktem końcowym, aby zapobiec nieautoryzowanemu dostępowi.
Najpierw zainstaluj zależności.
dotnet add package Microsoft.Azure.WebPubSub.AspNetCore
Teraz dodajmy /negotiate
punkt końcowy dla klienta w celu wywołania metody w celu wygenerowania 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>()
Służy do wstrzykiwania klienta WebPubSubServiceClient<THub>
usługi , za pomocą którego możemy użyć w kroku negocjacji do generowania tokenu połączenia klienta i w metodach centrum do wywoływania interfejsów API REST usługi po wyzwoleniu zdarzeń centrum. Ten kod generowania tokenu jest podobny do kodu użytego w samouczku dotyczącym publikowania i subskrybowania komunikatów, z wyjątkiem przekazywania jeszcze jednego argumentu (userId
) podczas generowania tokenu. Identyfikator użytkownika może służyć do identyfikowania tożsamości klienta, więc po otrzymaniu komunikatu wiadomo, skąd pochodzi komunikat.
Kod odczytuje parametry połączenia ze zmiennej środowiskowej WebPubSubConnectionString
ustawionej w poprzednim kroku.
Uruchom ponownie serwer przy użyciu polecenia dotnet run --urls http://localhost:8080
.
Możesz przetestować ten interfejs API, korzystając http://localhost:8080/negotiate?id=user1
z dostępu i podając pełny adres URL usługi Azure Web PubSub z tokenem dostępu.
Obsługa zdarzeń
W usłudze Azure Web PubSub, gdy po stronie klienta występują pewne działania (na przykład klient łączy się, łączy, rozłącza lub wysyła komunikaty), usługa wysyła powiadomienia do serwera, aby mogła reagować na te zdarzenia.
Zdarzenia są dostarczane do serwera w postaci elementu webhook. Element webhook jest obsługiwany i udostępniany przez serwer aplikacji i zarejestrowany po stronie usługi Azure Web PubSub. Usługa wywołuje elementy webhook za każdym razem, gdy wystąpi zdarzenie.
Usługa Azure Web PubSub jest zgodna z usługą CloudEvents , aby opisać dane zdarzenia.
Poniżej obsługujemy connected
zdarzenia systemowe, gdy klient jest połączony i obsługuje message
zdarzenia użytkownika, gdy klient wysyła komunikaty w celu skompilowania aplikacji do czatu.
Zestaw WEB PubSub SDK dla aplikacji AspNetCore Microsoft.Azure.WebPubSub.AspNetCore
zainstalowany w poprzednim kroku może również pomóc w analizowaniu i przetwarzaniu żądań CloudEvents.
Najpierw dodaj programy obsługi zdarzeń przed .app.Run()
Określ ścieżkę punktu końcowego dla zdarzeń, powiedzmy /eventhandler
.
app.MapWebPubSubHub<Sample_ChatApp>("/eventhandler/{*path}");
app.Run();
Teraz wewnątrz klasy Sample_ChatApp
utworzonej w poprzednim kroku dodaj konstruktor do pracy, WebPubSubServiceClient<Sample_ChatApp>
którego używamy do wywoływania usługi Web PubSub. Aby OnConnectedAsync()
reagować, gdy connected
zdarzenie jest wyzwalane, OnMessageReceivedAsync()
aby obsługiwać komunikaty 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();
}
}
W powyższym kodzie używamy klienta usługi do emisji komunikatu powiadomienia w formacie JSON do wszystkich, do których jest przyłączony SendToAllAsync
.
Aktualizowanie strony internetowej
Teraz zaktualizujmy index.html
logikę w celu nawiązania połączenia, wysyłania komunikatów i wyświetlania odebranych komunikatów na stronie.
<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>
W powyższym kodzie można zobaczyć, że używamy natywnego interfejsu API protokołu WebSocket w przeglądarce i używamy WebSocket.send()
go do wysyłania komunikatów i WebSocket.onmessage
nasłuchiwania odebranych komunikatów.
Możesz również użyć zestawów SDK klienta, aby nawiązać połączenie z usługą, co umożliwia automatyczne ponowne nawiązywanie połączenia, obsługę błędów i nie tylko.
Teraz pozostało jeszcze jeden krok, aby czat działał. Skonfigurujmy zdarzenia, których dotyczymy, i gdzie mają być wysyłane zdarzenia w usłudze Web PubSub.
Konfigurowanie programu obsługi zdarzeń
Ustawiamy program obsługi zdarzeń w usłudze Web PubSub, aby poinformować usługę, do której mają być wysyłane zdarzenia.
Kiedy serwer internetowy działa lokalnie, jak usługa Web PubSub wywołuje hosta lokalnego, jeśli nie ma punktu końcowego dostępnego dla Internetu? Zwykle istnieją dwa sposoby. Jednym z nich jest uwidocznienie hosta lokalnego publicznie przy użyciu ogólnego narzędzia tunelu, a drugi jest użycie tunelu awps-tunnel do tunelowania ruchu z usługi Web PubSub za pośrednictwem narzędzia do serwera lokalnego.
W tej sekcji użyjemy interfejsu wiersza polecenia platformy Azure, aby ustawić programy obsługi zdarzeń i użyć narzędzia awps-tunnel do kierowania ruchu do hosta lokalnego.
Konfigurowanie ustawień centrum
Ustawiliśmy szablon adresu URL tak, aby usługa tunnel
Web PubSub kieruje komunikaty za pośrednictwem połączenia tunelu awps-tunnel
. Procedury obsługi zdarzeń można ustawić z poziomu portalu lub interfejsu wiersza polecenia zgodnie z opisem w tym artykule. W tym miejscu ustawiliśmy je za pomocą interfejsu wiersza polecenia. Ponieważ nasłuchujemy zdarzeń w ścieżce /eventhandler
jako poprzednie zestawy kroków, ustawiliśmy szablon adresu URL na tunnel:///eventhandler
wartość .
Użyj polecenia az webpubsub hub create interfejsu wiersza polecenia platformy Azure, aby utworzyć ustawienia programu obsługi zdarzeń dla Sample_ChatApp
centrum.
Ważne
Zastąp <ciąg your-unique-resource-name> nazwą zasobu Web PubSub utworzonego na podstawie poprzednich kroków.
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"
Uruchamianie aplikacji awps-tunnel lokalnie
Pobieranie i instalowanie aplikacji awps-tunnel
Narzędzie działa w Node.js w wersji 16 lub nowszej.
npm install -g @azure/web-pubsub-tunnel-tool
Używanie parametry połączenia usługi i uruchamianie
export WebPubSubConnectionString="<your connection string>"
awps-tunnel run --hub Sample_ChatApp --upstream http://localhost:8080
Uruchamianie serwera internetowego
Teraz wszystko jest ustawione. Uruchommy serwer internetowy i odtwórzmy działanie aplikacji do czatu.
Teraz uruchom serwer przy użyciu polecenia dotnet run --urls http://localhost:8080
.
Kompletny przykład kodu tego samouczka można znaleźć tutaj.
Otwórz http://localhost:8080/index.html
. Możesz wprowadzić nazwę użytkownika i rozpocząć rozmowę.
Uwierzytelnianie z opóźnieniem z procedurą obsługi zdarzeń connect
W poprzednich sekcjach pokazano, jak używać punktu końcowego negocjowania w celu zwrócenia adresu URL usługi Web PubSub i tokenu dostępu JWT dla klientów w celu nawiązania połączenia z usługą Web PubSub. W niektórych przypadkach na przykład urządzenia brzegowe, które mają ograniczone zasoby, klienci mogą preferować bezpośrednie połączenie z zasobami Web PubSub. W takich przypadkach można skonfigurować connect
procedurę obsługi zdarzeń w celu uwierzytelnienia klientów z opóźnieniem, przypisania identyfikatora użytkownika do klientów, określenia grup, które klienci dołączają po nawiązaniu połączenia, skonfigurowania uprawnień, które klienci mają, oraz podprotocol protokołu WebSocket jako odpowiedzi protokołu WebSocket na klienta itp. Szczegółowe informacje można znaleźć w celu nawiązania połączenia ze specyfikacją programu obsługi zdarzeń.
Teraz użyjemy connect
programu obsługi zdarzeń, aby osiągnąć to, co robi sekcja negocjowania.
Aktualizowanie ustawień centrum
Najpierw zaktualizujmy ustawienia centrum, aby uwzględnić connect
również procedurę obsługi zdarzeń, musimy również zezwolić na anonimowe łączenie, aby klienci bez tokenu dostępu JWT mogli łączyć się z usługą.
Użyj polecenia az webpubsub hub update interfejsu wiersza polecenia platformy Azure, aby utworzyć ustawienia programu obsługi zdarzeń dla Sample_ChatApp
centrum.
Ważne
Zastąp <ciąg your-unique-resource-name> nazwą zasobu Web PubSub utworzonego na podstawie poprzednich kroków.
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"
Aktualizowanie logiki nadrzędnej w celu obsługi zdarzenia połączenia
Teraz zaktualizujmy logikę nadrzędną, aby obsłużyć zdarzenie połączenia. Możemy również usunąć teraz punkt końcowy negocjatowania.
Podobnie jak w przypadku negocjowania punktu końcowego jako celu demonstracyjnego, odczytamy również identyfikator z parametrów zapytania. W przypadku połączenia oryginalne zapytanie klienta jest zachowywane w treści requet zdarzenia połączenia.
Wewnątrz klasy Sample_ChatApp
zastąpij OnConnectAsync()
, aby obsłużyć connect
zdarzenie:
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();
}
}
Aktualizowanie index.html do bezpośredniego połączenia
Teraz zaktualizujmy stronę internetową, aby bezpośrednio nawiązać połączenie z usługą Web PubSub. Jedną z rzeczy, o których należy wspomnieć, jest to, że teraz w celu demonstracyjnego punktu końcowego usługi PubSub jest zakodowany w kodzie klienta, zaktualizuj nazwę <the host name of your service>
hosta usługi w poniższym kodzie HTML przy użyciu wartości z własnej usługi. Nadal przydatne może być pobranie wartości punktu końcowego usługi Web PubSub z serwera, co zapewnia większą elastyczność i możliwość kontrolowania lokalizacji, z którą klient nawiązuje połączenie.
<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>
Ponowne uruchamianie serwera
Teraz ponownie uruchom serwer i odwiedź stronę internetową zgodnie z instrukcjami przed. Jeśli zatrzymano awps-tunnel
program , uruchom ponownie narzędzie tunelu.
Następne kroki
Ten samouczek zawiera podstawowe informacje na temat działania systemu zdarzeń w usłudze Azure Web PubSub.
Zapoznaj się z innymi samouczkami, aby dowiedzieć się więcej na temat korzystania z usługi.