Esercitazione: Pubblicare e sottoscrivere messaggi tra client WebSocket tramite protocollo secondario
Nell'esercitazione Creare un'app di chat si è appreso come usare le API WebSocket per inviare e ricevere dati con Web PubSub di Azure. Quando il client comunica con il servizio, non è necessario alcun protocollo. Ad esempio, è possibile inviare qualsiasi tipo di dati usando WebSocket.send()
e il server lo riceve esattamente come è. Il processo delle API WebSocket è facile da usare, ma la funzionalità è limitata. Ad esempio, non è possibile specificare il nome dell'evento quando si invia l'evento al server o si pubblica il messaggio ad altri client anziché inviarlo al server. In questa esercitazione si apprenderà come usare il sottoprotocolo per estendere la funzionalità del client.
In questa esercitazione apprenderai a:
- Creare un'istanza del servizio Web PubSub
- Generare l'URL completo per stabilire la connessione WebSocket
- Pubblicare messaggi tra client WebSocket usando il sottoprotocolo
Se non si ha una sottoscrizione di Azure, creare un account Azure gratuito prima di iniziare.
Prerequisiti
Usare l'ambiente Bash in Azure Cloud Shell. Per altre informazioni, vedere Avvio rapido per Bash in Azure Cloud Shell.
Se si preferisce eseguire i comandi di riferimento dell'interfaccia della riga di comando in locale, installare l'interfaccia della riga di comando di Azure. Per l'esecuzione in Windows o macOS, è consigliabile eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker. Per altre informazioni, vedere Come eseguire l'interfaccia della riga di comando di Azure in un contenitore Docker.
Se si usa un'installazione locale, accedere all'interfaccia della riga di comando di Azure con il comando az login. Per completare il processo di autenticazione, seguire la procedura visualizzata nel terminale. Per altre opzioni di accesso, vedere Accedere con l'interfaccia della riga di comando di Azure.
Quando richiesto, installare l'estensione dell'interfaccia della riga di comando di Azure al primo uso. Per altre informazioni sulle estensioni, vedere Usare le estensioni con l'interfaccia della riga di comando di Azure.
Eseguire az version per trovare la versione e le librerie dipendenti installate. Per eseguire l'aggiornamento alla versione più recente, eseguire az upgrade.
- Questa configurazione richiede la versione 2.22.0 o successiva dell'interfaccia della riga di comando di Azure. Se si usa Azure Cloud Shell, la versione più recente è già installata.
Creare un'istanza di PubSub Di Azure
Creare un gruppo di risorse
Un gruppo di risorse è un contenitore logico in cui vengono distribuite e gestite le risorse di Azure. Usare il comando az group create per creare un gruppo di risorse denominato myResourceGroup
nel eastus
percorso.
az group create --name myResourceGroup --location EastUS
Creare un'istanza di Web PubSub
Eseguire az extension add per installare o aggiornare l'estensione webpubsub alla versione corrente.
az extension add --upgrade --name webpubsub
Usare il comando az webpubsub create dell'interfaccia della riga di comando di Azure per creare un Web PubSub nel gruppo di risorse creato. Il comando seguente crea una risorsa Web PubSub gratuita nel gruppo di risorse myResourceGroup in EastUS:
Importante
Ogni risorsa Web PubSub deve avere un nome univoco. Sostituire <your-unique-resource-name> con il nome di Web PubSub negli esempi seguenti.
az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1
L'output di questo comando mostra le proprietà della risorsa appena creata. Prendere nota delle due proprietà elencate di seguito:
- Nome risorsa: nome specificato al
--name
parametro precedente. - hostName: nell'esempio il nome host è
<your-unique-resource-name>.webpubsub.azure.com/
.
A questo punto, l'account Azure è l'unico autorizzato a eseguire qualsiasi operazione su questa nuova risorsa.
Ottenere il Connessione ionString per un uso futuro
Importante
Un stringa di connessione include le informazioni di autorizzazione necessarie per l'applicazione per accedere al servizio Web PubSub di Azure. La chiave di accesso all'interno del stringa di connessione è simile a una password radice per il servizio. Negli ambienti di produzione, prestare sempre attenzione a proteggere le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro. Evitare di distribuire chiavi di accesso ad altri utenti, hardcodedarli o salvarli in qualsiasi punto del testo normale accessibile ad altri utenti. Ruotare le chiavi se si ritiene che siano state compromesse.
Usare il comando az webpubsub key dell'interfaccia della riga di comando di Azure per ottenere il Connessione ionString del servizio. Sostituire il <your-unique-resource-name>
segnaposto con il nome dell'istanza di PubSub Web di Azure.
az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv
Copiare il stringa di connessione da usare in un secondo momento.
Copiare il Connessione ionString recuperato e usarlo più avanti in questa esercitazione come valore di <connection_string>
.
Configurare il progetto
Prerequisiti
Uso di un sottoprotocolo
Il client può avviare una connessione WebSocket usando un sottoprotocolo specifico. Il servizio Web PubSub di Azure supporta un sottoprotocolo chiamato json.webpubsub.azure.v1
per consentire ai client di pubblicare/sottoscrivere direttamente tramite il servizio Web PubSub anziché un round trip al server upstream. Per informazioni dettagliate sul sottoprotocolo del sottoprotocolo JSON WebSocket supportato, vedere Web PubSub di Azure.
Se si usano altri nomi di protocollo, questi verranno ignorati dal servizio e dal pass-through al server nel gestore eventi di connessione, in modo da poter creare protocolli personalizzati.
A questo punto si creerà un'applicazione Web usando il json.webpubsub.azure.v1
sottoprotocolo.
Installare le dipendenze
mkdir logstream cd logstream dotnet new web dotnet add package Microsoft.Extensions.Azure dotnet add package Azure.Messaging.WebPubSub
Creare il lato server per ospitare l'API e la
/negotiate
pagina Web.Eseguire l'aggiornamento
Program.cs
con il codice seguente.- Usare
AddAzureClients
per aggiungere il client del servizio e leggere il stringa di connessione dalla configurazione. - Aggiungere
app.UseStaticFiles();
primaapp.Run();
per supportare i file statici. - E aggiornare
app.MapGet
per generare il token di accesso client con/negotiate
le richieste.
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();
- Usare
Creare la pagina Web
Creare una pagina HTML con il contenuto seguente e salvarla come
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>
Il codice precedente si connette al servizio e stampa qualsiasi messaggio ricevuto nella pagina. La modifica principale consiste nel specificare il sottoprotocolo durante la creazione della connessione WebSocket.
Eseguire il server
Lo strumento Secret Manager per .NET Core viene usato per impostare il stringa di connessione. Eseguire il comando seguente, sostituendo
<connection_string>
con quello recuperato nel passaggio precedente e aperto http://localhost:5000/index.html nel browser:dotnet user-secrets init dotnet user-secrets set Azure:WebPubSub:ConnectionString "<connection-string>" dotnet run
Se si usa Chrome, è possibile premere F12 o fare clic con il pulsante destro del mouse su ->Inspect ->Developer Tools e selezionare la scheda Rete . Caricare la pagina Web ed è possibile visualizzare che viene stabilita la connessione WebSocket. Selezionare questa opzione per esaminare la connessione WebSocket. È possibile visualizzare il messaggio di evento seguente
connected
ricevuto nel client. È possibile vedere che è possibile ottenere ilconnectionId
generato per questo client.{"type":"system","event":"connected","userId":null,"connectionId":"<the_connection_id>"}
È possibile osservare che con l'aiuto del sottoprotocolo è possibile ottenere alcuni metadati della connessione quando la connessione è connected
.
Il client riceve ora un messaggio JSON anziché un testo normale. Il messaggio JSON contiene altre informazioni, ad esempio il tipo e l'origine del messaggio. È quindi possibile usare queste informazioni per eseguire un'elaborazione maggiore al messaggio (ad esempio, visualizzare il messaggio in uno stile diverso se proviene da un'origine diversa), che è possibile trovare nelle sezioni successive.
Pubblicare messaggi dal client
Nell'esercitazione Creare un'app di chat, quando il client invia un messaggio tramite connessione WebSocket al servizio Web PubSub, il servizio attiva un evento utente sul lato server. Con il sottoprotocolo, il client ha più funzionalità inviando un messaggio JSON. Ad esempio, è possibile pubblicare messaggi direttamente dal client tramite il servizio Web PubSub ad altri client.
Ciò è utile se si vuole trasmettere una grande quantità di dati ad altri client in tempo reale. Si userà questa funzionalità per creare un'applicazione di streaming di log, che può trasmettere i log della console al browser in tempo reale.
Creazione del programma di streaming
Creare un
stream
programma:mkdir stream cd stream dotnet new console
Aggiornare
Program.cs
con il contenuto seguente: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; } } } }
Qui è disponibile un nuovo concetto "gruppo". Il gruppo è un concetto logico in un hub in cui è possibile pubblicare messaggi in un gruppo di connessioni. In un hub è possibile avere più gruppi e un client può sottoscrivere più gruppi contemporaneamente. Quando si usa il sottoprotocolo, è possibile pubblicare solo in un gruppo anziché trasmettere all'intero hub. Per informazioni dettagliate sui termini, vedere i concetti di base.
Poiché in questo caso viene usato il gruppo, è anche necessario aggiornare la pagina
index.html
Web per partecipare al gruppo quando viene stabilita la connessione WebSocket all'internows.onopen
del callback.let ackId = 0; ws.onopen = () => { console.log('connected'); ws.send(JSON.stringify({ type: 'joinGroup', group: 'stream', ackId: ++ackId })); };
È possibile visualizzare l'aggiunta del client al gruppo inviando un messaggio di
joinGroup
tipo .Aggiornare anche leggermente la
ws.onmessage
logica di callback per analizzare la risposta JSON e stampare i messaggi solo dalstream
gruppo in modo che funzioni come stampante di flusso live.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); } };
Per considerazioni sulla sicurezza, per impostazione predefinita un client non può pubblicare o sottoscrivere un gruppo da solo. Si è quindi notato che è stato impostato
roles
sul client durante la generazione del token:Impostare quando
roles
GenerateClientAccessUri
in, come illustrato diStartup.cs
seguito:service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" })
Infine applicare anche uno stile a
index.html
in modo che venga visualizzato bene.<html> <head> <style> #output { white-space: pre; font-family: monospace; } </style> </head>
Eseguire ora il codice seguente e digitare qualsiasi testo e visualizzato nel browser in tempo reale:
ls -R | dotnet run
# Or call `dir /s /b | dotnet run` when you are using CMD under Windows
In alternativa, è più lento in modo da poter vedere che i dati vengono trasmessi al browser in tempo reale:
for i in $(ls -R); do echo $i; sleep 0.1; done | dotnet run
L'esempio di codice completo di questa esercitazione è disponibile qui.
Passaggi successivi
Questa esercitazione offre un'idea di base su come connettersi al servizio Web PubSub e su come pubblicare messaggi nei client connessi usando il sottoprotocolo.
Vedere altre esercitazioni per approfondire l'uso del servizio.