Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Uwaga / Notatka
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.
W tym artykule wyjaśniono, jak hostować i wdrażać aplikacje po stronie Blazor serwera (Blazor Web Appi Blazor Server aplikacje) przy użyciu platformy ASP.NET Core.
Wartości konfiguracji hosta
Aplikacje po stronie Blazor serwera mogą akceptować ogólne wartości konfiguracji hosta.
Wdrożenie
Użycie modelu Blazor hostingu po stronie serwera jest wykonywane na serwerze z poziomu aplikacji ASP.NET Core. Aktualizacje interfejsu użytkownika, obsługa zdarzeń i wywołania języka JavaScript są obsługiwane za pośrednictwem SignalR połączenia.
Wymagany jest serwer internetowy obsługujący aplikację ASP.NET Core. Program Visual Studio zawiera szablon projektu aplikacji po stronie serwera. Aby uzyskać więcej informacji na Blazor temat szablonów projektów, zobacz Blazor projektu ASP.NET Core).
Opublikuj aplikację w konfiguracji wydania i wdróż zawartość bin/Release/{TARGET FRAMEWORK}/publish folderu, w {TARGET FRAMEWORK} którym symbol zastępczy jest platformą docelową.
Skalowalność
Biorąc pod uwagę skalowalność pojedynczego serwera (skalowanie w górę), pamięć dostępna dla aplikacji jest prawdopodobnie pierwszym zasobem, który aplikacja wyczerpała w miarę wzrostu zapotrzebowania użytkownika. Dostępna pamięć na serwerze ma wpływ na:
- Liczba aktywnych obwodów, które może obsługiwać serwer.
- Opóźnienie interfejsu użytkownika na kliencie.
Aby uzyskać wskazówki dotyczące tworzenia bezpiecznych i skalowalnych aplikacji po stronie Blazor serwera, zobacz następujące zasoby:
- Wskazówki dotyczące ograniczania zagrożeń na potrzeby renderowania statycznego po stronie serwera ASP.NET Core Blazor
- Wskazówki dotyczące ograniczania zagrożeń na potrzeby interaktywnego renderowania po stronie serwera ASP.NET Core Blazor
Każdy obwód używa około 250 KB pamięci dla minimalnej aplikacji hello world stylu. Rozmiar obwodu zależy od kodu aplikacji i wymagań dotyczących konserwacji stanu skojarzonych z każdym składnikiem. Zalecamy mierzenie zapotrzebowania na zasoby podczas opracowywania aplikacji i infrastruktury, ale następujący punkt odniesienia może stanowić punkt początkowy planowania celu wdrożenia: Jeśli oczekujesz, że aplikacja będzie obsługiwać 5000 współbieżnych użytkowników, rozważ budżetowanie co najmniej 1,3 GB pamięci serwera do aplikacji (lub ok. 273 KB na użytkownika).
Blazor WebAssembly wstępne ładowanie zasobów statycznych
Składnik ResourcePreloader w zawartości head składnika App (App.razor) jest używany do odwołania do statycznych zasobów Blazor. Składnik jest umieszczany po tagu podstawowego adresu URL (<base>):
<ResourcePreloader />
Składnik Razor jest używany zamiast elementów, <link> ponieważ:
- Składnik umożliwia bazowemu adresowi URL (wartości atrybutu
<base>taguhref) poprawne zidentyfikowanie korzenia aplikacji Blazor w aplikacji ASP.NET Core. - Tę funkcję można usunąć, usuwając
ResourcePreloadertag składnika zeAppskładnika. Jest to przydatne w przypadkach, gdy aplikacja używa wywołania zwrotnegoloadBootResourcedo modyfikowania adresów URL.
SignalR konfiguracja
SignalRWarunki hostingu i skalowania mają zastosowanie do Blazor aplikacji korzystających z programu SignalR.
Aby uzyskać więcej informacji na SignalR temat aplikacji, w Blazor tym wskazówek dotyczących konfiguracji, zobacz Blazor dotyczące platformy ASP.NET CoreSignalR.
Transport
Blazor działa najlepiej w przypadku korzystania z obiektów WebSocket jako SignalR transportu ze względu na mniejsze opóźnienia, lepszą niezawodność i lepsze zabezpieczenia. Długie sondowanie jest używane, SignalR gdy zestawy WebSocket nie są dostępne lub gdy aplikacja jest jawnie skonfigurowana do korzystania z długiego sondowania.
Jeśli jest używane długie sondowanie, zostanie wyświetlone ostrzeżenie konsoli:
Nie można nawiązać połączenia za pośrednictwem obiektów WebSocket przy użyciu transportu rezerwowego Long Polling. Może to być spowodowane blokowaniem połączenia przez sieć VPN lub serwer proxy.
Globalne błędy wdrażania i połączenia
Zalecenia dotyczące wdrożeń globalnych w centrach danych geograficznych:
Azure App Service
Hosting w usłudze aplikacja systemu Azure wymaga konfiguracji obiektów WebSocket i koligacji sesji, nazywanej również koligacją routingu żądań aplikacji (ARR).
Uwaga / Notatka
Blazor Aplikacja w usłudze aplikacja systemu Azure nie wymaga SignalR platformy Azure.
Włącz następujące informacje dotyczące rejestracji aplikacji w usłudze aplikacja systemu Azure Service:
- Protokoły WebSocket umożliwiające działanie transportu obiektów WebSocket. Domyślne ustawienie to Wyłączone.
- Koligacja sesji w celu kierowania żądań od użytkownika z powrotem do tego samego wystąpienia usługi App Service. Ustawienie domyślne to Włączone.
- W witrynie Azure Portal przejdź do aplikacji internetowej w usłudze App Services.
- Otwórz pozycję Konfiguracja ustawień>.
- Ustaw pozycję Gniazda internetowe na wartość Włączone.
- Sprawdź, czy koligacja sesji jest ustawiona na włączone.
Usługa platformy Azure SignalR
Opcjonalna Usługa SignalR Azure działa w połączeniu z SignalR hubem aplikacji, aby skalować aplikację po stronie serwera do dużej liczby współbieżnych połączeń. Ponadto globalne zasięg usługi i centra danych o wysokiej wydajności znacznie pomagają zmniejszyć opóźnienia ze względu na lokalizację geograficzną.
Usługa nie jest wymagana w przypadku Blazor aplikacji hostowanych w usłudze aplikacja systemu Azure Lub Azure Container Apps, ale może być przydatna w innych środowiskach hostingu:
- Aby ułatwić skalowanie połączeń w poziomie.
- Obsługa dystrybucji globalnej.
Usługa Azure SignalR z SDK w wersji 1.26.1 lub nowszej obsługuje SignalR łączenie z zachowaniem stanu (WithStatefulReconnect).
W przypadku, gdy aplikacja używa długiego sondowania lub wraca do długiego sondowania zamiast obiektów WebSocket, może być konieczne skonfigurowanie maksymalnego interwału sondowania (MaxPollIntervalInSecondsdomyślnie: 5 sekund, limit: 1–300 sekund), który definiuje maksymalny interwał sondowania dozwolony dla połączeń długich sondowania w usłudze Platformy Azure SignalR . Jeśli następne żądanie sondowania nie zostanie dostarczone w maksymalnym interwale sondowania, usługa zamknie połączenie klienta.
Aby uzyskać wskazówki dotyczące dodawania usługi jako zależności do wdrożenia produkcyjnego, zobacz Publikowanie aplikacji ASP.NET Core SignalR w usłudze aplikacja systemu Azure Service.
Aby uzyskać więcej informacji, zobacz:
- Usługa platformy Azure SignalR
- Co to jest usługa platformy Azure SignalR ?
- ASP.NET Core SignalR hosting i skalowanie produkcyjne
- Publikowanie aplikacji ASP.NET Core SignalR w usłudze aplikacja systemu Azure
Azure Container Apps
Aby dowiedzieć się więcej na temat skalowania aplikacji po stronie Blazor serwera w usłudze Azure Container Apps, zobacz Scaling ASP.NET Core Apps on Azure (Skalowanie aplikacji ASP.NET Core Apps na platformie Azure). W tym samouczku wyjaśniono, jak tworzyć i integrować usługi wymagane do hostowania aplikacji w usłudze Azure Container Apps. Podstawowe kroki są również dostępne w tej sekcji.
Skonfiguruj usługę Azure Container Apps pod kątem koligacji sesji, postępując zgodnie ze wskazówkami w temacie Koligacja sesji w usłudze Azure Container Apps (dokumentacja platformy Azure).
Usługa ASP.NET Core Data Protection (DP) musi być skonfigurowana do utrwalania kluczy w scentralizowanej lokalizacji, do których mogą uzyskiwać dostęp wszystkie wystąpienia kontenerów. Klucze mogą być przechowywane w usłudze Azure Blob Storage i chronione za pomocą usługi Azure Key Vault. Usługa DP używa kluczy do deserializacji Razor składników. Aby skonfigurować usługę DP do korzystania z usług Azure Blob Storage i Azure Key Vault, zapoznaj się z następującymi pakietami NuGet:
-
Azure.Identity: udostępnia klasy do pracy z usługami zarządzania tożsamościami i dostępem platformy Azure. -
Microsoft.Extensions.Azure: Udostępnia przydatne metody rozszerzenia do wykonywania podstawowych konfiguracji platformy Azure. -
Azure.Extensions.AspNetCore.DataProtection.Blobs: umożliwia przechowywanie ASP.NET podstawowych kluczy ochrony danych w usłudze Azure Blob Storage, dzięki czemu klucze mogą być współużytkowane przez kilka wystąpień aplikacji internetowej. -
Azure.Extensions.AspNetCore.DataProtection.Keys: umożliwia ochronę kluczy magazynowanych przy użyciu funkcji szyfrowania/opakowowania kluczy usługi Azure Key Vault.
Uwaga / Notatka
Aby uzyskać wskazówki dotyczące dodawania pakietów do aplikacji .NET, zobacz artykuły w Instalowanie i zarządzanie pakietami oraz w proces korzystania z pakietów (dokumentacja NuGet). Sprawdź prawidłowe wersje pakietów pod adresem NuGet.org.
-
Zaktualizuj
Program.csza pomocą następującego wyróżnionego kodu:using Azure.Identity; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Azure; var builder = WebApplication.CreateBuilder(args); var BlobStorageUri = builder.Configuration["AzureURIs:BlobStorage"]; var KeyVaultURI = builder.Configuration["AzureURIs:KeyVault"]; builder.Services.AddRazorPages(); builder.Services.AddHttpClient(); builder.Services.AddServerSideBlazor(); builder.Services.AddAzureClientsCore(); builder.Services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri(BlobStorageUri), new DefaultAzureCredential()) .ProtectKeysWithAzureKeyVault(new Uri(KeyVaultURI), new DefaultAzureCredential()); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();Powyższe zmiany umożliwiają aplikacji zarządzanie usługą DP przy użyciu scentralizowanej, skalowalnej architektury. DefaultAzureCredential odkrywa zarządzaną tożsamość aplikacji kontenera po wdrożeniu kodu na platformie Azure i wykorzystuje ją do połączenia się z magazynem obiektów blob oraz skarbcem kluczy aplikacji.
Aby utworzyć zarządzaną tożsamość aplikacji kontenerowej i przyznać jej dostęp do magazynu obiektów Blob oraz magazynu Key Vault, wykonaj następujące kroki:
- W witrynie Azure Portal przejdź do strony przeglądu aplikacji kontenera.
- Wybierz pozycję Łącznik usługi w obszarze nawigacji po lewej stronie.
- Wybierz pozycję + Utwórz z górnej nawigacji.
-
W menu wysuwany Tworzenie połączenia wprowadź następujące wartości:
- Kontener: wybierz utworzoną aplikację kontenera do hostowania aplikacji.
- Typ usługi: wybierz pozycję Blob Storage.
- Subskrypcja: wybierz subskrypcję, która jest właścicielem aplikacji kontenera.
-
Nazwa połączenia: wprowadź nazwę
scalablerazorstorage. - Typ klienta: wybierz pozycję .NET , a następnie wybierz przycisk Dalej.
- Wybierz pozycję Tożsamość zarządzana przypisana przez system i wybierz pozycję Dalej.
- Użyj domyślnych ustawień sieciowych i wybierz pozycję Dalej.
- Po zweryfikowaniu ustawień przez platformę Azure wybierz pozycję Utwórz.
Powtórz powyższe ustawienia dla magazynu kluczy. Wybierz odpowiednią usługę i klucz magazynu kluczy na karcie Podstawy .
Uwaga / Notatka
W poprzednim przykładzie użyto DefaultAzureCredential metody upraszczania uwierzytelniania podczas opracowywania aplikacji wdrażanych na platformie Azure przez połączenie poświadczeń używanych w środowiskach hostingu platformy Azure z poświadczeniami używanymi podczas programowania lokalnego. Podczas przechodzenia do środowiska produkcyjnego lepszym wyborem jest skorzystanie z alternatywy, takiej jak ManagedIdentityCredential. Aby uzyskać więcej informacji, zobacz Uwierzytelnianie aplikacji platformy .NET hostowanych na platformie Azure do zasobów platformy Azure przy użyciu tożsamości zarządzanej przypisanej przez system.
IIS
W przypadku korzystania z usług IIS włącz:
- Obiekty WebSocket w usługach IIS.
- Koligacja sesji z routingiem żądań aplikacji.
Aby uzyskać więcej informacji, zobacz wskazówki i zewnętrzne linki do zasobów usług IIS w temacie Publikowanie aplikacji ASP.NET Core w usługach IIS.
Kubernetes
Utwórz definicję ruchu przychodzącego z następującymi adnotacjami Kubernetes dla koligacji sesji:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: <ingress-name>
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "affinity"
nginx.ingress.kubernetes.io/session-cookie-expires: "14400"
nginx.ingress.kubernetes.io/session-cookie-max-age: "14400"
System Linux z serwerem Nginx
Postępuj zgodnie ze wskazówkami dotyczącymi SignalR z następującymi zmianami:
- Zmień ścieżkę
locationz/hubroute(location /hubroute { ... }) na ścieżkę/główną (location / { ... }). - Usuń konfigurację buforowania serwera proxy (
proxy_buffering off;), ponieważ ustawienie ma zastosowanie tylko do zdarzeń wysłanych przez serwer (SSE), które nie są istotne dla Blazor interakcji między klientem aplikacji a serwerem.
Aby uzyskać więcej informacji i wskazówek dotyczących konfiguracji, zapoznaj się z następującymi zasobami:
- ASP.NET Core SignalR hosting i skalowanie produkcyjne
- Hostowanie aplikacji ASP.NET Core w systemie Linux z serwerem Nginx
- Konfigurowanie platformy ASP.NET Core pod kątem pracy z serwerami proxy i modułami równoważenia obciążenia
- NGINX jako serwer proxy dla WebSocket
- Proxy WebSocket
- Zapoznaj się z deweloperami na forach pomocy technicznej innych niż Microsoft:
System Linux z serwerem Apache
Aby hostować aplikację za platformą Blazor Apache w systemie Linux, skonfiguruj ProxyPass ruch HTTP i WebSocket.
W poniższym przykładzie:
- Kestrel serwer jest uruchomiony na maszynie hosta.
- Aplikacja nasłuchuje ruchu na porcie 5000.
ProxyPreserveHost On
ProxyPassMatch ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass /_blazor ws://localhost:5000/_blazor
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
Włącz następujące moduły:
a2enmod proxy
a2enmod proxy_wstunnel
Sprawdź konsolę przeglądarki pod kątem błędów obiektów WebSocket. Przykładowe błędy:
- Firefox nie może nawiązać połączenia z serwerem pod adresem ws://the-domain-name.tld/_blazor?id=XXX
- Błąd: Nie można uruchomić transportu "WebSockets": Błąd: Wystąpił błąd podczas transportu.
- Błąd: Nie można uruchomić transportu "LongPolling": TypeError: this.transport jest niezdefiniowany
- Błąd: Nie można nawiązać połączenia z serwerem z żadnym z dostępnych transportów. Nie można uruchomić obiektów WebSocket
- Błąd: Nie można wysłać danych, jeśli połączenie nie znajduje się w stanie "Połączono".
Aby uzyskać więcej informacji i wskazówek dotyczących konfiguracji, zapoznaj się z następującymi zasobami:
- Konfigurowanie platformy ASP.NET Core pod kątem pracy z serwerami proxy i modułami równoważenia obciążenia
- Dokumentacja platformy Apache
- Zapoznaj się z deweloperami na forach pomocy technicznej innych niż Microsoft:
Mierzenie opóźnienia sieci
JS Interop może służyć do mierzenia opóźnienia sieci, jak pokazano w poniższym przykładzie.
MeasureLatency.razor:
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
<h2>Measure Latency</h2>
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
@inject IJSRuntime JS
@if (latency is null)
{
<span>Calculating...</span>
}
else
{
<span>@(latency.Value.TotalMilliseconds)ms</span>
}
@code {
private DateTime startTime;
private TimeSpan? latency;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
startTime = DateTime.UtcNow;
var _ = await JS.InvokeAsync<string>("toString");
latency = DateTime.UtcNow - startTime;
StateHasChanged();
}
}
}
W przypadku rozsądnego środowiska interfejsu użytkownika zalecamy trwałe opóźnienie interfejsu użytkownika 250 ms lub mniej.
ASP.NET Core