Programowanie i konfigurowanie w usłudze Azure Functions za pomocą usługi Azure SignalR Service
Aplikacje usługi Azure Functions mogą używać powiązań usługi Azure SignalR Service do dodawania możliwości w czasie rzeczywistym. Aplikacje klienckie używają zestawów SDK klienta dostępnych w kilku językach do nawiązywania połączenia z usługą Azure SignalR Service i odbierania komunikatów w czasie rzeczywistym.
W tym artykule opisano pojęcia dotyczące tworzenia i konfigurowania aplikacji funkcji platformy Azure zintegrowanej z usługą SignalR Service.
Ważne
Nieprzetworzone parametry połączenia są wyświetlane tylko w tym artykule w celach demonstracyjnych.
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 zawsze chroń klucze dostępu. Usługa Azure Key Vault umożliwia bezpieczne zarządzanie kluczami i obracanie ich oraz zabezpieczanie parametry połączenia przy użyciu identyfikatora Entra firmy Microsoft.
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.
Konfiguracja usługi SignalR Service
Usługę Azure SignalR Service można skonfigurować w różnych trybach. W przypadku korzystania z usługi Azure Functions usługa musi być skonfigurowana w trybie bezserwerowym .
W witrynie Azure Portal znajdź stronę Ustawienia zasobu usługi SignalR Service. Ustaw tryb usługi na bezserwerowy.
Opracowywanie usługi Azure Functions
Bezserwerowa aplikacja w czasie rzeczywistym utworzona za pomocą usług Azure Functions i Azure SignalR Service wymaga co najmniej dwóch funkcji platformy Azure:
- Funkcja wywoływana
negotiate
przez klienta w celu uzyskania prawidłowego tokenu dostępu usługi SignalR Service i adresu URL punktu końcowego. - Co najmniej jedna funkcja, która obsługuje komunikaty wysyłane z usługi SignalR Service do klientów.
Funkcja negocjacji
Aplikacja kliencka wymaga prawidłowego tokenu dostępu w celu nawiązania połączenia z usługą Azure SignalR Service. Token dostępu może być anonimowy lub uwierzytelniony w identyfikatorze użytkownika. Aplikacje usługi SignalR Service bezserwerowe wymagają punktu końcowego HTTP o nazwie negotiate
w celu uzyskania tokenu i innych informacji o połączeniu, takich jak adres URL punktu końcowego usługi SignalR Service.
Użyj funkcji platformy Azure wyzwalanej przez protokół HTTP i powiązania wejściowego SignalRConnectionInfo
, aby wygenerować obiekt informacji o połączeniu. Funkcja musi mieć trasę HTTP kończącą się na ./negotiate
W przypadku modelu opartego na klasach w języku C#nie potrzebujesz SignalRConnectionInfo
powiązania danych wejściowych i możesz znacznie łatwiej dodawać oświadczenia niestandardowe. Aby uzyskać więcej informacji, zobacz Środowisko negocjacji w modelu opartym na klasach.
Aby uzyskać więcej informacji na temat negotiate
funkcji, zobacz Programowanie w usłudze Azure Functions.
Aby dowiedzieć się, jak utworzyć uwierzytelniony token, zobacz Korzystanie z uwierzytelniania usługi App Service.
Obsługa komunikatów wysyłanych z usługi SignalR Service
SignalRTrigger
Użyj powiązania do obsługi komunikatów wysyłanych z usługi SignalR Service. Powiadomienia można otrzymywać, gdy klienci wysyłają komunikaty lub klienci są połączeni lub rozłączeni.
Aby uzyskać więcej informacji, zobacz dokumentację powiązania wyzwalacza usługi SignalR Service.
Należy również skonfigurować punkt końcowy funkcji jako nadrzędny punkt końcowy, aby usługa wyzwalała funkcję w przypadku wystąpienia komunikatu od klienta. Aby uzyskać więcej informacji na temat konfigurowania nadrzędnych punktów końcowych, zobacz Upstream endpoints (Nadrzędne punkty końcowe).
Uwaga
Usługa SignalR Service nie obsługuje komunikatu StreamInvocation
z klienta w trybie bezserwerowym.
Wysyłanie komunikatów i zarządzanie członkostwem w grupie
Użyj powiązania wyjściowego SignalR
, aby wysyłać komunikaty do klientów połączonych z usługą Azure SignalR Service. Komunikaty można emitować do wszystkich klientów lub wysyłać je do podzbioru klientów. Na przykład wysyłaj komunikaty tylko do klientów uwierzytelnionych przy użyciu określonego identyfikatora użytkownika lub tylko do określonej grupy.
Użytkownicy mogą być dodawani do co najmniej jednej grupy. Możesz również użyć powiązania danych wyjściowych SignalR
, aby dodać lub usunąć użytkowników do/z grup.
Aby uzyskać więcej informacji, zobacz dokumentację powiązania wyjściowego.SignalR
Koncentratory SignalR
Usługa SignalR ma koncepcję koncentratorów. Każde połączenie klienta i każdy komunikat wysyłany z usługi Azure Functions ma zakres do określonego centrum. Koncentratory mogą służyć jako sposób oddzielania połączeń i komunikatów do logicznych przestrzeni nazw.
Model oparty na klasach
Model oparty na klasach jest przeznaczony dla języka C#.
Model oparty na klasach zapewnia lepsze środowisko programowania, które może zastąpić powiązania wejściowe i wyjściowe usługi SignalR następującymi funkcjami:
- Bardziej elastyczne negocjacje, wysyłanie komunikatów i zarządzanie środowiskami grup.
- Obsługiwane są więcej funkcji zarządzania, w tym zamykanie połączeń, sprawdzanie, czy istnieje połączenie, użytkownik lub grupa.
- Silnie typizowane centrum
- Ujednolicona nazwa centrum i ustawienie parametry połączenia w jednym miejscu.
Poniższy kod przedstawia sposób pisania powiązań usługi SignalR w modelu opartym na klasach:
Najpierw zdefiniuj centrum pochodzące z klasy ServerlessHub
:
[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub
{
private const string HubName = nameof(Functions); // Used by SignalR trigger only
public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
[Function("negotiate")]
public async Task<HttpResponseData> Negotiate([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req)
{
var negotiateResponse = await NegotiateAsync(new() { UserId = req.Headers.GetValues("userId").FirstOrDefault() });
var response = req.CreateResponse();
response.WriteBytes(negotiateResponse.ToArray());
return response;
}
[Function("Broadcast")]
public Task Broadcast(
[SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
{
return Clients.All.SendAsync("newMessage", new NewMessage(invocationContext, message));
}
[Function("JoinGroup")]
public Task JoinGroup([SignalRTrigger(HubName, "messages", "JoinGroup", "connectionId", "groupName")] SignalRInvocationContext invocationContext, string connectionId, string groupName)
{
return Groups.AddToGroupAsync(connectionId, groupName);
}
}
W pliku Program.cs zarejestruj centrum bezserwerowe:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(b => b.Services
.AddServerlessHub<Functions>())
.Build();
Doświadczenie negocjacji w modelu opartym na klasach
Zamiast używać powiązania [SignalRConnectionInfoInput]
wejściowego usługi SignalR, negocjacje w modelu opartym na klasach mogą być bardziej elastyczne. Klasa ServerlessHub
podstawowa ma metodę NegotiateAsync
, która umożliwia użytkownikom dostosowywanie opcji negocjacji, takich jak userId
, claims
itp.
Task<BinaryData> NegotiateAsync(NegotiationOptions? options = null)
Wysyłanie komunikatów i zarządzanie środowiskiem w modelu opartym na klasach
Możesz wysyłać komunikaty, zarządzać grupami lub zarządzać klientami, korzystając z elementów członkowskich dostarczonych przez klasę ServerlessHub
bazową .
ServerlessHub.Clients
do wysyłania komunikatów do klientów.ServerlessHub.Groups
do zarządzania połączeniami z grupami, takimi jak dodawanie połączeń do grup, usuwanie połączeń z grup.ServerlessHub.UserGroups
do zarządzania użytkownikami przy użyciu grup, takich jak dodawanie użytkowników do grup, usuwanie użytkowników z grup.ServerlessHub.ClientManager
do sprawdzania istnienia połączeń, zamykania połączeń itp.
Centrum silnie typizowane
Silnie typizowane centrum umożliwia używanie silnie typiowanych metod podczas wysyłania komunikatów do klientów. Aby użyć silnie typizowanego centrum w modelu opartym na klasach, wyodrębnij metody klienta do interfejsu T
i utwórz klasę centrum pochodzącą z ServerlessHub<T>
klasy .
Poniższy kod jest przykładem interfejsu dla metod klienta.
public interface IChatClient
{
Task newMessage(NewMessage message);
}
Następnie można użyć silnie typiowanych metod w następujący sposób.
Nieprzetworzone parametry połączenia są wyświetlane tylko w tym artykule w celach demonstracyjnych. W środowiskach produkcyjnych zawsze chroń klucze dostępu. Usługa Azure Key Vault umożliwia bezpieczne zarządzanie kluczami i obracanie ich oraz zabezpieczanie parametry połączenia przy użyciu identyfikatora Entra firmy Microsoft.
[SignalRConnection("AzureSignalRConnectionString")]
public class Functions : ServerlessHub<IChatClient>
{
private const string HubName = nameof(Functions); // Used by SignalR trigger only
public Functions(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
[Function("Broadcast")]
public Task Broadcast(
[SignalRTrigger(HubName, "messages", "broadcast", "message")] SignalRInvocationContext invocationContext, string message)
{
return Clients.All.newMessage(new NewMessage(invocationContext, message));
}
}
Uwaga
Kompletny przykład projektu można pobrać z usługi GitHub.
Ujednolicona nazwa centrum i ustawienie parametry połączenia w jednym miejscu
- Nazwa klasy centrum bezserwerowego jest automatycznie używana jako
HubName
. - Być może atrybut
SignalRConnection
używany w klasach koncentratora bezserwerowego wygląda następująco:
Umożliwia dostosowanie miejsca, w którym znajduje się parametry połączenia dla koncentratora bezserwerowego. Jeśli jest nieobecny, zostanie użyta wartość[SignalRConnection("AzureSignalRConnectionString")] public class Functions : ServerlessHub<IChatClient>
AzureSignalRConnectionString
domyślna.
Ważne
Wyzwalacze usługi SignalR i koncentratory bezserwerowe są niezależne. W związku z tym nazwa klasy bezserwerowego centrum i SignalRConnection
atrybutu nie zmienia ustawień wyzwalaczy usługi SignalR, mimo że używasz wyzwalaczy SignalR wewnątrz bezserwerowego koncentratora.
Programowanie klientów
Aplikacje klienckie usługi SignalR mogą używać zestawu SDK klienta SignalR w jednym z kilku języków, aby łatwo łączyć się z usługą Azure SignalR Service i odbierać komunikaty z usługi Azure SignalR Service.
Konfigurowanie połączenia klienta
Aby nawiązać połączenie z usługą SignalR Service, klient musi wykonać pomyślne negocjacje połączenia, które składają się z następujących kroków:
- Prześlij żądanie do punktu końcowego HTTP omówionego powyżej,
negotiate
aby uzyskać prawidłowe informacje o połączeniu - Nawiązywanie połączenia z usługą SignalR Service przy użyciu adresu URL punktu końcowego usługi i tokenu dostępu uzyskanego z punktu końcowego
negotiate
Zestawy SDK klienta usługi SignalR zawierają już logikę wymaganą do wykonania uzgadniania negocjacji. Przekaż adres URL punktu końcowego negocjacji, minus negotiate
segment, do zestawu HubConnectionBuilder
SDK . Oto przykład w języku JavaScript:
const connection = new signalR.HubConnectionBuilder()
.withUrl("https://my-signalr-function-app.azurewebsites.net/api")
.build();
Zgodnie z konwencją zestaw SDK automatycznie dołącza /negotiate
do adresu URL i używa go do rozpoczęcia negocjacji.
Uwaga
Jeśli używasz zestawu JAVAScript/TypeScript SDK w przeglądarce, musisz włączyć współużytkowanie zasobów między źródłami (CORS) w aplikacji funkcji.
Aby uzyskać więcej informacji na temat korzystania z zestawu SDK klienta usługi SignalR, zobacz dokumentację dotyczącą języka:
Wysyłanie komunikatów z klienta do usługi
Jeśli skonfigurowano nadrzędny zasób usługi SignalR, możesz wysyłać komunikaty z klienta do usługi Azure Functions przy użyciu dowolnego klienta usługi SignalR. Oto przykład w języku JavaScript:
connection.send("method1", "arg1", "arg2");
Konfiguracja usługi Azure Functions
Aplikacje funkcji platformy Azure, które integrują się z usługą Azure SignalR Service, można wdrażać jak każda typowa aplikacja funkcji platformy Azure, korzystając z technik, takich jak ciągłe wdrażanie, wdrażanie zip i uruchamianie z pakietu.
Istnieje jednak kilka szczególnych zagadnień dotyczących aplikacji korzystających z powiązań usługi SignalR Service. Jeśli klient działa w przeglądarce, należy włączyć mechanizm CORS. Jeśli aplikacja wymaga uwierzytelniania, możesz zintegrować punkt końcowy negocjacji z uwierzytelnianiem usługi App Service.
Włączanie mechanizmu CORS
Klient JavaScript/TypeScript wysyła żądanie HTTP do funkcji negocjacji w celu zainicjowania negocjacji połączenia. Jeśli aplikacja kliencka jest hostowana w innej domenie niż aplikacja funkcji platformy Azure, udostępnianie zasobów między źródłami (CORS) musi być włączone w aplikacji funkcji lub przeglądarka zablokuje żądania.
Host lokalny
Podczas uruchamiania aplikacji funkcji na komputerze lokalnym można dodać sekcję Host
do local.settings.json , aby włączyć mechanizm CORS. Host
W sekcji dodaj dwie właściwości:
CORS
— wprowadź podstawowy adres URL, który jest źródłem aplikacji klienckiejCORSCredentials
— ustaw ją tak, abytrue
zezwalała na żądania "withCredentials"
Przykład:
{
"IsEncrypted": false,
"Values": {
// values
},
"Host": {
"CORS": "http://localhost:8080",
"CORSCredentials": true
}
}
Chmura — mechanizm CORS usługi Azure Functions
Aby włączyć mechanizm CORS w aplikacji funkcji platformy Azure, przejdź do ekranu konfiguracji mechanizmu CORS na karcie Funkcje platformy aplikacji funkcji w witrynie Azure Portal.
Uwaga
Konfiguracja mechanizmu CORS nie jest jeszcze dostępna w planie użycia systemu Linux usługi Azure Functions. Użyj usługi Azure API Management , aby włączyć mechanizm CORS.
Mechanizm CORS z poświadczeniami Access-Control-Allow-Credentials musi być włączony, aby klient usługi SignalR mógł wywołać funkcję negocjacji. Aby ją włączyć, zaznacz pole wyboru.
W sekcji Dozwolone źródła dodaj wpis z podstawowym adresem URL aplikacji internetowej.
Chmura — Azure API Management
Usługa Azure API Management udostępnia bramę interfejsu API, która dodaje możliwości do istniejących usług zaplecza. Można go użyć do dodawania mechanizmu CORS do aplikacji funkcji. Oferuje warstwę zużycia z cenami płatności za akcję i miesięcznym bezpłatnym przyznaniem.
Zapoznaj się z dokumentacją usługi API Management, aby uzyskać informacje na temat importowania aplikacji funkcji platformy Azure. Po zaimportowaniu można dodać zasady ruchu przychodzącego, aby włączyć mechanizm CORS z obsługą mechanizmu ACCESS-Control-Allow-Credentials.
<cors allow-credentials="true">
<allowed-origins>
<origin>https://azure-samples.github.io</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
<method>POST</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
Skonfiguruj klientów usługi SignalR tak, aby używali adresu URL usługi API Management.
Korzystanie z uwierzytelniania usługi App Service
Usługa Azure Functions ma wbudowane uwierzytelnianie, które obsługuje popularnych dostawców, takich jak Facebook, X, Konto Microsoft, Google i Microsoft Entra ID. Tę funkcję można zintegrować z powiązaniem SignalRConnectionInfo
, aby utworzyć połączenia z usługą Azure SignalR Service uwierzytelnioną w identyfikatorze użytkownika. Aplikacja może wysyłać komunikaty przy użyciu SignalR
powiązania danych wyjściowych, które są przeznaczone dla tego identyfikatora użytkownika.
W witrynie Azure Portal na karcie Funkcje platformy aplikacji funkcji otwórz okno Ustawienia uwierzytelniania/autoryzacji. Postępuj zgodnie z dokumentacją uwierzytelniania usługi App Service, aby skonfigurować uwierzytelnianie przy użyciu wybranego dostawcy tożsamości.
Po skonfigurowaniu uwierzytelnione żądania HTTP zawierają x-ms-client-principal-name
odpowiednio x-ms-client-principal-id
i nagłówki zawierające nazwę użytkownika i identyfikator użytkownika tożsamości uwierzytelnionej.
Te nagłówki można użyć w konfiguracji powiązania, SignalRConnectionInfo
aby utworzyć uwierzytelnione połączenia. Oto przykładowa funkcja negocjacji języka C#, która używa nagłówka x-ms-client-principal-id
.
[FunctionName("negotiate")]
public static 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 user
return connectionInfo;
}
Następnie możesz wysyłać komunikaty do tego użytkownika, ustawiając UserId
właściwość komunikatu usługi SignalR.
[FunctionName("SendMessage")]
public static 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 }
});
}
Aby uzyskać informacje na temat innych języków, zobacz dokumentację powiązań usługi Azure SignalR Service dla usługi Azure Functions.
Następne kroki
Z tego artykułu dowiesz się, jak opracowywać i konfigurować bezserwerowe aplikacje usługi SignalR Service przy użyciu usługi Azure Functions. Spróbuj samodzielnie utworzyć aplikację przy użyciu jednego z przewodników Szybki start lub samouczków na stronie przeglądu usługi SignalR Service.