Sviluppo e configurazione di Funzioni di Azure e con il Servizio Azure SignalR
Articolo
Le applicazioni di Funzioni di Azure possono usare le associazioni del Servizio Azure SignalR per aggiungere funzionalità in tempo reale. Le applicazioni client usano gli SDK client disponibili in diverse lingue per connettersi al Servizio Azure SignalR e ricevere messaggi in tempo reale.
Questo articolo descrive i concetti per lo sviluppo e la configurazione di un'app per le funzioni di Azure integrata con il servizio SignalR.
Importante
Le stringa di connessione non elaborate vengono visualizzate in questo articolo solo a scopo dimostrativo.
Un stringa di connessione include le informazioni di autorizzazione necessarie per consentire all'applicazione di accedere alle Servizio Azure SignalR. La chiave di accesso all'interno della stringa di connessione è simile a una password radice per il servizio. Negli ambienti di produzione proteggere sempre le chiavi di accesso. Usare Azure Key Vault per gestire e ruotare le chiavi in modo sicuro e proteggere i stringa di connessione usando Microsoft Entra ID e autorizzare l'accesso con Microsoft Entra ID.
Evitare di distribuire le chiavi di accesso ad altri utenti, impostarle come hardcoded o salvarle in un file di testo normale accessibile ad altri. Ruotare le chiavi se si ritiene che siano state compromesse.
Configurazione del servizio SignalR
Il Servizio Azure SignalR può essere configurato in modalità diverse. Se usato con Funzioni di Azure, il servizio deve essere configurato in modalità serverless.
Nel portale di Azure individuare la pagina Impostazioni della risorsa del servizio SignalR. Impostare Modalità servizio su Serverless.
Sviluppo di Funzioni di Azure
Un'applicazione serverless in tempo reale compilata con Funzioni di Azure e con il servizio Azure SignalR richiede almeno due istanze di Funzioni di Azure:
Una funzione negotiate che il client chiama per ottenere un token di accesso valido del servizio SignalR e un URL dell'endpoint.
Una o più funzioni che gestiscono i messaggi inviati dal servizio SignalR ai client.
Funzione di negoziazione
Un'applicazione client richiede un token di accesso valido per connettersi al Servizio Azure SignalR. Un token di accesso può essere anonimo o autenticato in un ID utente. Le applicazioni del servizio SignalR serverless richiedono un endpoint HTTP denominato negotiate per ottenere un token e altre informazioni di connessione, ad esempio l'URL dell'endpoint del servizio SignalR.
Usare una funzione di Azure attivata da HTTP e l'associazione di input SignalRConnectionInfo per generare l'oggetto con le informazioni di connessione. La funzione deve avere un percorso HTTP che termina in /negotiate.
Usare l'associazione SignalRTrigger per gestire i messaggi inviati dal servizio SignalR. È possibile ricevere una notifica quando i client inviano messaggi o i client vengono connessi o disconnessi.
È anche necessario configurare l'endpoint della funzione come endpoint upstream in modo che il servizio attivi la funzione quando viene visualizzato un messaggio da un client. Per altre informazioni su come configurare gli endpoint upstream, vedere Endpoint upstream.
Nota
Il servizio SignalR non supporta il messaggio StreamInvocation da un client in modalità serverless.
Invio di messaggi e gestione dell'appartenenza ai gruppi
Usare l'associazione di output SignalR per inviare messaggi ai client connessi al Servizio Azure SignalR. È possibile trasmettere messaggi a tutti i client oppure inviarli a un subset di client. Ad esempio, inviare messaggi solo ai client autenticati con un ID utente specifico o solo a un gruppo specifico.
Gli utenti possono essere aggiunti a uno o più gruppi. È anche possibile usare l'associazione di output SignalR per aggiungere o rimuovere utenti da/verso i gruppi.
SignalR ha un concetto di hub. Ogni connessione client e ogni messaggio inviato da Funzioni di Azure ha come ambito un hub specifico. È possibile usare hub come modo per separare le connessioni e i messaggi in spazi dei nomi logici.
Il modello basato su classi offre un'esperienza di programmazione migliore, che può sostituire le associazioni di input e output SignalR, con le funzionalità seguenti:
Negoziazione più flessibile, invio di messaggi e gestione dei gruppi.
Sono supportate altre funzionalità di gestione, tra cui la chiusura delle connessioni, la verifica dell'esistenza di una connessione, di un utente o di un gruppo.
Hub tipizzati in modo sicuro
Nome dell'hub unificato e impostazione della stringa di connessione in un'unica posizione.
Il codice seguente illustra come scrivere associazioni SignalR nel modello basato su classi:
In primo luogo, definire l'hub derivato da una classe ServerlessHub:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(b => b.Services
.AddServerlessHub<Functions>())
.Build();
Esperienza di negoziazione nel modello basato su classi
Anziché usare l'associazione di input [SignalRConnectionInfoInput] SignalR, la negoziazione nel modello basato su classi può essere più flessibile. La classe base ServerlessHub ha un metodo NegotiateAsync che consente agli utenti di personalizzare le opzioni di negoziazione, ad esempio userId, claims e così via.
Invio di messaggi e gestione dell'esperienza nel modello basato su classi
È possibile inviare messaggi, gestire gruppi o gestire i client accedendo ai membri forniti dalla classe base ServerlessHub.
ServerlessHub.Clients per l'invio di messaggi ai client.
ServerlessHub.Groups per la gestione delle connessioni con gruppi, ad esempio l'aggiunta di connessioni ai gruppi, la rimozione di connessioni dai gruppi.
ServerlessHub.UserGroups per la gestione degli utenti con gruppi, ad esempio l'aggiunta di utenti a gruppi, la rimozione di utenti dai gruppi.
ServerlessHub.ClientManager per verificare l'esistenza delle connessioni, la chiusura di connessioni e così via.
Hub tipizzati in modo sicuro
L'hub fortemente tipizzato consente di usare metodi fortemente tipizzati quando si inviano messaggi ai client. Per usare un hub fortemente tipizzato nel modello basato su classi, estrarre i metodi client in un'interfaccia T e rendere la classe hub derivata da ServerlessHub<T>.
Il codice seguente è un esempio di interfaccia per i metodi client.
Consente di personalizzare la posizione in cui si trova la stringa di connessione per l'hub serverless. Se è assente, viene usato il valore predefinito AzureSignalRConnectionString.
Importante
I trigger SignalR e gli hub serverless sono indipendenti. Pertanto, il nome della classe dell'hub serverless e dell'attributo SignalRConnection non modifica le impostazioni dei trigger SignalR, anche se si usano trigger SignalR all'interno dell'hub serverless.
Il modello basato su classi offre un'esperienza di programmazione lato server SignalR coerente, con le funzionalità seguenti:
Meno lavoro di configurazione: il nome della classe viene usato come HubName, il nome del metodo viene usato come Event e Category viene stabilito automaticamente in base al nome del metodo.
Associazione automatica dei parametri: ParameterNames e l'attributo [SignalRParameter] non sono necessari. I parametri vengono associati automaticamente agli argomenti dei metodi di Funzione di Azure in ordine.
Tutte le funzioni per cui si intende usare il modello basato su classi devono essere un metodo della classe che eredita da ServerlessHub. Il nome della classe HubName1 nell'esempio è il nome dell'hub.
Definire il metodo hub
Tutti i metodi hub devono avere un argomento di InvocationContext decorato per l'attributo [SignalRTrigger] e usare un costruttore senza parametri. Il nome del metodo viene quindi considerato come un evento di parametro.
Per impostazione predefinita, category=messages ad eccezione del nome del metodo, è uno dei nomi seguenti:
OnConnected: considerato come category=connections, event=connected
OnDisconnected: considerato come category=connections, event=disconnected
Esperienza di associazione dei parametri
Nel modello basato su classi [SignalRParameter] non è necessario perché tutti gli argomenti sono contrassegnati come [SignalRParameter] per impostazione predefinita tranne in una delle situazioni seguenti:
L'argomento è decorato da un attributo di associazione
Il tipo dell'argomento è ILogger o CancellationToken
L'argomento è decorato dall'attributo [SignalRIgnore]
Esperienza di negoziazione nel modello basato su classi
Anziché usare l'associazione di input [SignalR] SignalR, la negoziazione nel modello basato su classi può essere più flessibile. La classe base ServerlessHub ha un metodo:
Questa funzionalità consente all'utente di personalizzare userId o claims durante l'esecuzione della funzione.
Utilizzare SignalRFilterAttribute.
L'utente può ereditare e implementare la classe astratta SignalRFilterAttribute. Se le eccezioni vengono generate in FilterAsync, 403 Forbidden verrà restituito ai client.
Nell'esempio seguente viene illustrato come implementare un filtro cliente che consente solo all'oggetto admin di richiamare broadcast.
Le applicazioni client SignalR possono usare l'SDK client SignalR in uno dei diversi linguaggi per connettersi e ricevere facilmente messaggi dal Servizio Azure SignalR.
Configurazione di una connessione client
Per connettersi al servizio SignalR, un client deve completare una negoziazione di connessione riuscita costituita da questi passaggi:
Effettuare una richiesta all'endpoint HTTP negotiate descritto in precedenza per ottenere informazioni di connessione valide
Connettersi al servizio SignalR usando l'URL dell'endpoint di servizio e il token di accesso ottenuti dall'endpoint negotiate
Gli SDK del client SignalR contengono già la logica necessaria per eseguire l'handshake di negoziazione. Passare l'URL dell'endpoint di negoziazione, meno il segmento negotiate a HubConnectionBuilder dell'SDK. Ecco un esempio in JavaScript:
JavaScript
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://my-signalr-function-app.azurewebsites.net/api")
.build();
Per convenzione, l'SDK aggiunge automaticamente /negotiate all'URL e lo usa per avviare la negoziazione.
Se è stato configurato upstream per la risorsa SignalR, è possibile inviare messaggi da un client a Funzioni di Azure usando qualsiasi client SignalR. Ecco un esempio in JavaScript:
JavaScript
connection.send("method1", "arg1", "arg2");
Configurazione di Funzioni di Azure
Le app per le funzioni di Azure che si integrano con il Servizio Azure SignalR possono essere distribuite come qualsiasi tipica app per le funzioni di Azure usando tecniche come la distribuzione continua, la distribuzione zip e l'esecuzione dal pacchetto.
Esistono tuttavia alcune considerazioni speciali per le app che usano le associazioni del servizio SignalR. Se il client viene eseguito in un browser, è necessario abilitare CORS. Se l'app richiede l'autenticazione, è possibile integrare l'endpoint di negoziazione con l'autenticazione del servizio app.
Abilitazione della condivisione CORS
Il client JavaScript/TypeScript effettua una richiesta HTTP alla funzione di negoziazione per avviare la negoziazione della connessione. Quando l'applicazione client è ospitata in un dominio diverso rispetto all'app per le funzioni di Azure, è necessario abilitare la condivisione di risorse tra le origini (CORS) nell'app per le funzioni oppure il browser bloccherà le richieste.
Localhost
Quando si esegue l'app per le funzioni nel computer locale, è possibile aggiungere una sezione Host a local.settings.json per abilitare CORS. Nella sezione Host aggiungere due proprietà:
CORS: immettere l'URL di base che rappresenta l'origine dell'applicazione client
CORSCredentials: impostarlo su true per consentire le richieste "withCredentials"
Per abilitare CORS in un'app per le funzioni di Azure, passare alla schermata di configurazione CORS nella scheda Funzionalità della piattaforma dell'app per le funzioni nel portale di Azure.
Nota
La configurazione CORS non è ancora disponibile nel piano a consumo per Linux di Funzioni di Azure. Usare Gestione API di Azure per abilitare CORS.
CORS con Access-Control-Allow-Credentials deve essere abilitato per consentire al client SignalR di chiamare la funzione di negoziazione. Per abilitarla, selezionare la casella di controllo.
Nella sezione Origini consentite aggiungere una voce con l'URL di base di origine dell'applicazione Web.
Cloud - Gestione API di Azure
Gestione API di Azure offre un gateway API che aggiunge funzionalità ai servizi back-end esistenti. È possibile usarlo per aggiungere CORS all'app per le funzioni. Offre un piano a consumo con prezzi con pagamento in base all'azione e una concessione gratuita mensile.
Per informazioni su come importare un'app per le funzioni di Azure, vedere la documentazione di Gestione API. Dopo l'importazione, è possibile aggiungere un criterio in ingresso per abilitare CORS con il supporto di Access-Control-Allow-Credentials.
Configurare i client SignalR per l'uso dell'URL di Gestione API.
Utilizzo di Autenticazione servizio app
Funzioni di Azure include l'autenticazione predefinita, supportando provider diffusi come Facebook, X, Account Microsoft, Google e Microsoft Entra ID. Questa funzionalità può essere integrata con l'associazione SignalRConnectionInfo per creare connessioni al Servizio Azure SignalR autenticato in un ID utente. L'applicazione può inviare messaggi usando l'associazione di output SignalR destinata a tale ID utente.
Nella scheda Funzionalità della piattaforma dell'app per le funzioni del portale di Azure aprire la finestra delle impostazioni di Autenticazione/autorizzazione. Seguire la documentazione relativa all'autenticazione del servizio app per configurare l'autenticazione usando un provider di identità di propria scelta.
Dopo la configurazione, le richieste HTTP autenticate includono le intestazioni x-ms-client-principal-name e x-ms-client-principal-id contenenti rispettivamente il nome utente e l'ID utente dell'identità autenticata.
È possibile usare queste intestazioni nella configurazione dell'associazione SignalRConnectionInfo per creare connessioni autenticate. Ecco un esempio di funzione di negoziazione C# che usa l'intestazione x-ms-client-principal-id.
C#
[FunctionName("negotiate")]
publicstatic SignalRConnectionInfo Negotiate(
[HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
[SignalRConnectionInfo
(HubName = "chat", UserId = "{headers.x-ms-client-principal-id}")]
SignalRConnectionInfo connectionInfo)
{
// connectionInfo contains an access key token with a name identifier claim set to the authenticated userreturn connectionInfo;
}
È quindi possibile inviare messaggi all'utente impostando la proprietà UserId di un messaggio SignalR.
C#
[FunctionName("SendMessage")]
publicstatic Task SendMessage(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")]object message,
[SignalR(HubName = "chat")]IAsyncCollector<SignalRMessage> signalRMessages)
{
return signalRMessages.AddAsync(
new SignalRMessage
{
// the message will only be sent to these user IDs
UserId = "userId1",
Target = "newMessage",
Arguments = new [] { message }
});
}
Questo articolo illustra come sviluppare e configurare applicazioni del servizio SignalR serverless usando Funzioni di Azure. Provare a creare manualmente un'applicazione usando una delle guide introduttive o le esercitazioni nella pagina di panoramica del servizio SignalR.
Cambiare un meccanismo di aggiornamento di un'app Web JavaScript da un'architettura di polling a una basata su push in tempo reale con il Servizio SignalR, Azure Cosmos DB e Funzioni di Azure. Usare Vue.js e JavaScript per usare SignalR con Visual Studio Code.
Progettare soluzioni end-to-end in Microsoft Azure per creare Funzioni di Azure, implementare e gestire app Web, sviluppare soluzioni che usano Archiviazione di Azure e altro ancora.