Hosten und Bereitstellen von serverseitigen Blazor-Apps
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 7-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Informationen zum aktuellen Release finden Sie in der .NET 7-Version dieses Artikels.
In diesem Artikel wird erläutert, wie Sie serverseitige Blazor-Apps mit ASP.NET Core hosten und bereitstellen.
Hostkonfigurationswerte
Serverseitige Blazor-Apps können generische Hostkonfigurationswerte akzeptieren.
Bereitstellung
Mithilfe eines serverseitigen Hostingmodells wird Blazor innerhalb einer ASP.NET Core-App auf dem Server ausgeführt. Benutzeroberflächenupdates, Ereignisbehandlung und JavaScript-Aufrufe werden über eine SignalR-Verbindung verarbeitet.
Hierfür wird ein Webserver benötigt, der eine ASP.NET Core-App hosten kann. Visual Studio enthält eine Projektvorlage für serverseitige Apps. Weitere Informationen zu Blazor-Projektvorlagen finden Sie unter Blazor-Projektstruktur in ASP.NET Core.
Skalierbarkeit
Bei Betrachtung der Skalierbarkeit eines einzelnen Servers (zum Hochskalieren) ist der einer App zur Verfügung stehende Arbeitsspeicher wahrscheinlich die erste Ressource, die von der App bei steigenden Benutzeranforderungen ausgeschöpft wird. Der verfügbare Arbeitsspeicher auf dem Server wirkt sich auf Folgendes aus:
- Anzahl der aktiven Verbindungen, die ein Server unterstützen kann.
- Benutzeroberflächenlatenz auf dem Client.
Anleitungen zum Erstellen sicherer und skalierbarer serverseitiger Blazor-Apps finden Sie unter Leitfaden zur Bedrohungsabwehr für serverseitige ASP.NET CoreBlazor-Apps.
Jede Verbindung verwendet ungefähr 250 KB Arbeitsspeicher für eine minimale App im Hello World-Stil. Die Größe einer Verbindung hängt vom App-Code und den Zustandsverwaltungsanforderungen der einzelnen Komponenten ab. Sie sollten die Ressourcenanforderungen während der Entwicklung für Ihre App und die Infrastruktur messen, aber die folgende Baseline kann ein Ausgangspunkt zur Planung des Bereitstellungsziels sein: Wenn Sie davon ausgehen, dass Ihre App 5.000 gleichzeitige Benutzer unterstützt, sollten Sie erwägen, mindestens 1,3 GB Serverarbeitsspeicher (oder ~273 KB pro Benutzer) für die App einzukalkulieren.
SignalR-Konfiguration
Die Hosting- und Skalierungsbedingungen von SignalR gelten für Blazor-Apps, die SignalR verwenden.
Transportprotokolle
Blazor funktioniert am besten, wenn für den SignalR-Transport WebSockets verwendet werden, um die Latenzzeiten zu reduzieren und die Zuverlässigkeit und Sicherheit zu erhöhen. SignalR verwendet Long Polling, wenn WebSockets nicht verfügbar oder die App explizit für die Verwendung von Long Polling konfiguriert ist. Konfigurieren Sie die App bei Bereitstellung für Azure App Service in den Einstellungen für den Dienst im Azure-Portal für die Verwendung von WebSockets. Weitere Informationen zum Konfigurieren der App für Azure App Service finden Sie in den Richtlinien für die SignalR-Veröffentlichung.
Eine Konsolenwarnung wird angezeigt, wenn Long Polling verwendet wird:
Fehler beim Herstellen einer Verbindung über WebSockets mithilfe des Long Polling-Fallbacktransports. Möglicherweise wird die Verbindung durch ein VPN oder einen Proxy blockiert.
Globale Bereitstellungs- und Verbindungsfehler
Empfehlungen für globale Bereitstellungen in regionalen Rechenzentren:
- Stellen Sie die App in den Regionen bereit, in denen sich die meisten Benutzer befinden.
- Berücksichtigen Sie bei kontinentübergreifendem Datenverkehr die erhöhte Latenz.
- Verwenden Sie für Azure-Hosting den Azure-Dienst SignalR.
Wenn eine bereitgestellte App aufgrund von Timeouts beim Pingen, die durch Internetlatenz verursacht werden, häufig die Benutzeroberfläche für die Verbindungswiederherstellung anzeigt, verlängern Sie die Timeouts für Server und Client:
Server
Mindestens das Doppelte der maximal zu erwartenden Dauer des Roundtrips zwischen Client und Server. Testen, überwachen und ändern Sie die Timeouts bei Bedarf. Legen Sie für den SignalR-Hub ClientTimeoutInterval (Standard: 30 Sekunden) und HandshakeTimeout (Standard: 15 Sekunden) fest. Das folgende Beispiel geht davon aus, dass für KeepAliveInterval der Standardwert von 15 Sekunden gilt.
Wichtig
KeepAliveInterval steht nicht in direktem Zusammenhang mit der Anzeige der Benutzeroberfläche für die Wiederverbindung. Das Keep-Alive Intervall muss nicht unbedingt geändert werden. Wenn das Problem mit der Anzeige der Benutzeroberfläche für die Wiederverbindung auf Timeouts zurückzuführen ist, können ClientTimeoutInterval und HandshakeTimeout erhöht werden, und das Keep-Alive Intervall kann unverändert bleiben. Wichtig: Wenn Sie das Keep-Alive Intervall ändern, stellen Sie sicher, dass der Clienttimeoutwert mindestens doppelt so groß wie der Wert des Keep-Alive Intervalls ist und dass das Keep-Alive Intervall auf dem Client mit der Servereinstellung übereinstimmt.
Im folgenden Beispiel wird ClientTimeoutInterval auf 60 Sekunden und HandshakeTimeout auf 30 Sekunden erhöht.
In der
Program.cs
-Datei des Serverprojekts:builder.Services.AddRazorComponents().AddServerComponents() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(60); options.HandshakeTimeout = TimeSpan.FromSeconds(30); });
Weitere Informationen finden Sie in den Anleitungen zu ASP.NET Core BlazorSignalR.
Server
Mindestens das Doppelte der maximal zu erwartenden Dauer des Roundtrips zwischen Client und Server. Testen, überwachen und ändern Sie die Timeouts bei Bedarf. Legen Sie für den SignalR-Hub ClientTimeoutInterval (Standard: 30 Sekunden) und HandshakeTimeout (Standard: 15 Sekunden) fest. Das folgende Beispiel geht davon aus, dass für KeepAliveInterval der Standardwert von 15 Sekunden gilt.
Wichtig
KeepAliveInterval steht nicht in direktem Zusammenhang mit der Anzeige der Benutzeroberfläche für die Wiederverbindung. Das Keep-Alive Intervall muss nicht unbedingt geändert werden. Wenn das Problem mit der Anzeige der Benutzeroberfläche für die Wiederverbindung auf Timeouts zurückzuführen ist, können ClientTimeoutInterval und HandshakeTimeout erhöht werden, und das Keep-Alive Intervall kann unverändert bleiben. Wichtig: Wenn Sie das Keep-Alive Intervall ändern, stellen Sie sicher, dass der Clienttimeoutwert mindestens doppelt so groß wie der Wert des Keep-Alive Intervalls ist und dass das Keep-Alive Intervall auf dem Client mit der Servereinstellung übereinstimmt.
Im folgenden Beispiel wird ClientTimeoutInterval auf 60 Sekunden und HandshakeTimeout auf 30 Sekunden erhöht.
In
Program.cs
:builder.Services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(60); options.HandshakeTimeout = TimeSpan.FromSeconds(30); });
Weitere Informationen finden Sie in den Anleitungen zu ASP.NET Core BlazorSignalR.
- Client
Üblicherweise verdoppeln Sie den Wert, der für KeepAliveInterval des Servers verwendet wird, um das Servertimeout des Clients festzulegen (withServerTimeout
oder ServerTimeout, Standardwert: 30 Sekunden).
Wichtig
Das Keep-Alive-Intervall (withKeepAliveInterval
oder KeepAliveInterval) steht nicht in direktem Zusammenhang mit der Anzeige der Benutzeroberfläche für eine erneute Verbindung. Das Keep-Alive Intervall muss nicht unbedingt geändert werden. Wenn das Problem mit der Anzeige der Benutzeroberfläche für die Wiederverbindung auf Timeouts zurückzuführen ist, kann das Servertimeout erhöht werden, und das Keep-Alive Intervall kann unverändert bleiben. Wichtig: Wenn Sie das Keep-Alive Intervall ändern, stellen Sie sicher, dass der Timeoutwert mindestens doppelt so groß wie der Wert des Keep-Alive Intervalls ist und dass das Keep-Alive Intervall auf dem Server mit der Clienteinstellung übereinstimmt.
Im folgenden Beispiel wird ein benutzerdefinierter Wert von 60 Sekunden für das Servertimeout verwendet.
In der Startkonfiguration einer serverseitigen Blazor-App nach dem <script>
-Tag im Blazor-Skript (blazor.*.js
):
<script>
Blazor.start({
configureSignalR: function (builder) {
builder.withServerTimeout(60000);
}
});
</script>
Wenn Sie eine Hubverbindung in einer Komponente erstellen, legen Sie ServerTimeout (Standardwert 30 Sekunden) für das HubConnectionBuilder fest. Legen Sie die HandshakeTimeout (Standardeinstellung 15 Sekunden) für die erstellte HubConnection fest.
Das folgende Beispiel basiert auf der Index
-Komponente in SignalR mit dem Blazor-Tutorial. Das Servertimeout wird auf 60 Sekunden erhöht, das Handshaketimeout auf 30 Sekunden:
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.WithServerTimeout(TimeSpan.FromSeconds(60))
.Build();
hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);
hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...
await hubConnection.StartAsync();
}
Üblicherweise verdoppeln Sie den Wert, der für KeepAliveInterval des Servers verwendet wird, um das Servertimeout des Clients festzulegen (serverTimeoutInMilliseconds
oder ServerTimeout, Standardwert: 30 Sekunden).
Wichtig
Das Keep-Alive-Intervall (keepAliveIntervalInMilliseconds
oder KeepAliveInterval) steht nicht in direktem Zusammenhang mit der Anzeige der Benutzeroberfläche für eine erneute Verbindung. Das Keep-Alive Intervall muss nicht unbedingt geändert werden. Wenn das Problem mit der Anzeige der Benutzeroberfläche für die Wiederverbindung auf Timeouts zurückzuführen ist, kann das Servertimeout erhöht werden, und das Keep-Alive Intervall kann unverändert bleiben. Wichtig: Wenn Sie das Keep-Alive Intervall ändern, stellen Sie sicher, dass der Timeoutwert mindestens doppelt so groß wie der Wert des Keep-Alive Intervalls ist und dass das Keep-Alive Intervall auf dem Server mit der Clienteinstellung übereinstimmt.
Im folgenden Beispiel wird ein benutzerdefinierter Wert von 60 Sekunden für das Servertimeout verwendet.
In Pages/_Host.cshtml
:
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
Blazor.start({
configureSignalR: function (builder) {
let c = builder.build();
c.serverTimeoutInMilliseconds = 60000;
builder.build = () => {
return c;
};
}
});
</script>
Wenn Sie eine Hubverbindung in einer Komponente erstellen, legen Sie ServerTimeout (Standardwert: 30 Sekunden) und HandshakeTimeout (Standardwert: 15 Sekunden) für die erstellte HubConnection fest.
Das folgende Beispiel basiert auf der Index
-Komponente in SignalR mit dem Blazor-Tutorial. Das Servertimeout wird auf 60 Sekunden erhöht, das Handshaketimeout auf 30 Sekunden:
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.Build();
hubConnection.ServerTimeout = TimeSpan.FromSeconds(60);
hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);
hubConnection.On<string, string>("ReceiveMessage", (user, message) => ...
await hubConnection.StartAsync();
}
Beim Ändern der Werte für das Servertimeout (ServerTimeout) oder das Keep-Alive-Intervall (KeepAliveInterval):
- Das Servertimeout sollte mindestens doppelt so groß sein wie der dem Keep-Alive-Intervall zugewiesene Wert.
- Das Keep-Alive-Intervall sollte kleiner oder gleich der Hälfte des Werts sein, der dem Servertimeout zugewiesen ist.
Weitere Informationen finden Sie in den Anleitungen zu ASP.NET Core BlazorSignalR.
Serverseitige Apps verwenden ASP.NET Core SignalR für die Kommunikation mit dem Browser. Die Hosting- und Skalierungsbedingungen von SignalR gelten für serverseitige Apps.
Blazor funktioniert am besten, wenn WebSockets aufgrund geringerer Latenz und wegen Zuverlässigkeit und Sicherheit zum SignalR-Transport verwendet wird. SignalR verwendet Long Polling, wenn WebSockets nicht verfügbar oder die App explizit für die Verwendung von Long Polling konfiguriert ist. Konfigurieren Sie die App bei Bereitstellung für Azure App Service in den Einstellungen für den Dienst im Azure-Portal für die Verwendung von WebSockets. Weitere Informationen zum Konfigurieren der App für Azure App Service finden Sie in den Richtlinien für die SignalR-Veröffentlichung.
Azure SignalR Service
Sie sollten Azure SignalR Service für serverseitige Blazor-Apps verwenden. Der Dienst arbeitet mit dem Blazor-Hub der App zusammen, um eine serverseitige Blazor-App für eine große Anzahl gleichzeitiger SignalR-Verbindungen hochskalieren zu können. Außerdem tragen die globale Reichweite und die Hochleistungsrechenzentren von SignalR Service erheblich zur Verringerung der geografiebedingten Latenz bei.
Wichtig
Wenn WebSockets deaktiviert sind, simuliert Azure App Service eine Echtzeitverbindung mithilfe von langen HTTP-Abrufen. Das lange Abrufen über HTTP ist deutlich langsamer als die Ausführung mit aktiviertem WebSockets, das keinen Abruf verwendet, um eine Clientserververbindung zu simulieren. Für den Fall, dass Long Polling erforderlich ist, müssen Sie eventuell das maximale Abfrageintervall (MaxPollIntervalInSeconds
) konfigurieren. Es legt das maximal zulässige Abfrageintervall für Long Polling-Verbindungen in Azure SignalR Service fest, falls der Dienst jemals von WebSockets auf Long Polling zurückwechselt. Wenn die nächste Abfrageanforderung nicht innerhalb von MaxPollIntervalInSeconds
eingeht, bereinigt Azure SignalR Service die Clientverbindung. Beachten Sie, dass Azure SignalR Service Verbindungen auch bereinigt, wenn die Größe des zwischengespeicherten Schreibpuffers größer als 1 MB ist, um die Leistung des Diensts sicherzustellen. Der Standardwert für MaxPollIntervalInSeconds
ist 5 Sekunden. Die Einstellung ist auf 1–300 Sekunden begrenzt.
Es wird empfohlen, Websockets für serverseitige Blazor-Apps zu verwenden, die in Azure App Service bereitgestellt werden. In Azure SignalR Service werden Websockets standardmäßig verwendet. Wenn die App den SignalR-Dienst von Azure nicht verwendet, finden Sie weitere Informationen unter Veröffentlichen einer ASP.NET Core-SignalR-App bei Azure App Service.
Weitere Informationen finden Sie in folgenden Quellen:
Konfiguration
Wenn Sie eine App für Azure SignalR Service konfigurieren, muss die App persistente Sitzungen unterstützen, in denen Clients beim Prerendering wieder zurück zum gleichen Server geleitet werden. Die ServerStickyMode
-Option oder der Konfigurationswert ist auf Required
festgelegt. In der Regel erstellt eine App die Konfiguration mithilfe von einem der folgenden Ansätze:
Program.cs
:builder.Services.AddSignalR().AddAzureSignalR(options => { options.ServerStickyMode = Microsoft.Azure.SignalR.ServerStickyMode.Required; });
Konfiguration (verwenden Sie einen der folgenden Ansätze):
In
appsettings.json
:"Azure:SignalR:ServerStickyMode": "Required"
Konfiguration>Anwendungseinstellungen des App-Diensts im Azure-Portal (Name:
Azure__SignalR__ServerStickyMode
, Wert:Required
). Dieser Ansatz wird für die App automatisch übernommen, wenn Sie Azure SignalR Service bereitstellen.
Hinweis
Der folgende Fehler wird von einer App ausgelöst, die keine persistenten Sitzungen für Azure SignalR Service aktiviert hat:
blazor.server.js:1 Uncaught (in promise) Error: Invocation canceled due to the underlying connection being closed. (Nicht abgefangen (in Zusage) Fehler: Der Aufruf wurde abgebrochen, weil die zugrunde liegende Verbindung beendet wurde.)
Bereitstellen von Azure SignalR Service
So stellen Sie Azure SignalR Service für eine App in Visual Studio bereit:
- Erstellen Sie ein Veröffentlichungsprofil für Azure-Apps in Visual Studio für die -App.
- Fügen Sie dem Profil die Azure SignalR Service-Abhängigkeit hinzu. Wenn das Azure-Abonnement nicht über eine bereits vorhandene Azure SignalR Service-Instanz verfügt, die der App zugewiesen werden soll, wählen Sie Neue Azure SignalR Service-Instanz erstellen aus, um eine neue Dienstinstanz bereitzustellen.
- Veröffentlichen Sie die App in Azure.
Durch die Bereitstellung von Azure SignalR Service in Visual Studio werden automatisch persistente Sitzungen aktiviert, und die SignalR-Verbindungszeichenfolge wird der Konfiguration des App-Diensts hinzugefügt.
Skalierbarkeit für Azure Container Apps
Die Skalierung von serverseitigen Blazor-Apps in Azure Container Apps erfordert besondere Überlegungen zusätzlich zur Verwendung von Azure SignalR Service. Aufgrund der Art und Weise, wie das Routing von Anforderungen gehandhabt wird, muss der ASP.NET Core-Datenschutzdienst so konfiguriert werden, dass Schlüssel an einem zentralen Ort aufbewahrt werden, auf den alle Containerinstanzen zugreifen können. Die Schlüssel können in Azure Blob Storage gespeichert und mit Azure Key Vault geschützt werden. Der Datenschutzdienst verwendet die Schlüssel zum Deserialisieren von Razor-Komponenten.
Hinweis
Eine eingehendere Erkundung dieses Szenarios und der Skalierung von Container-Apps finden Sie unter Skalieren von ASP.NET Core-Apps in Azure. In diesem Tutorial wird erklärt, wie Sie die Dienste erstellen und integrieren, die für das Hosten von Apps in Azure Container Apps erforderlich sind. In diesem Abschnitt werden auch die grundlegenden Schritte beschrieben.
Wenn Sie den Datenschutzdienst für Azure Blob Storage und Azure Key Vault konfigurieren möchten, verweisen Sie auf die folgenden NuGet-Pakete:
Azure.Identity
: stellt Klassen für das Arbeiten mit den Identitäts- und Zugriffsverwaltungsdiensten von Azure bereit.Microsoft.Extensions.Azure
: Stellt hilfreiche Erweiterungsmethoden bereit, mit denen wichtige Azure-Konfigurationen durchgeführt werden könnenAzure.Extensions.AspNetCore.DataProtection.Blobs
: ermöglicht das Speichern von ASP.NET Core-Datenschutzschlüsseln in Azure Blob Storage, damit Schlüssel für mehrere Instanzen einer Web-App freigegeben werden können.Azure.Extensions.AspNetCore.DataProtection.Keys
: Ermöglicht das Schützen ruhender Schlüssel mithilfe der Schlüsselverschlüsselung bzw. dem Umbrechen-Feature von Azure Key Vault
Hinweis
Einen Leitfaden zum Hinzufügen von Paketen zu .NET-Apps finden Sie in Installieren und Verwalten von Paketen unter Workflow der Nutzung von Paketen (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.
Aktualisieren Sie
Program.cs
mit dem folgenden hervorgehobenen Code: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();
Dank der vorherigen Änderungen kann die App den Datenschutz mithilfe einer zentralen, skalierbaren Architektur verwalten. DefaultAzureCredential ermittelt die verwaltete Identität der Container-App, nachdem der Code in Azure bereitgestellt wurde, und nutzt sie zum Herstellen einer Verbindung mit Blobspeicher und dem Schlüsseltresor der App.
Führen Sie die folgenden Schritte aus, um die verwaltete Identität der Container-App zu erstellen und ihr Zugriff auf Blobspeicher und einen Schlüsseltresor zu gewähren:
- Navigieren Sie im Azure-Portal zur Übersichtsseite der Container-App.
- Wählen Sie im linken Navigationsbereich Dienstconnector aus.
- Wählen Sie im oberen Navigationsbereich + Erstellen aus.
- Geben Sie im Flyoutmenü Verbindung erstellen die folgenden Werte ein:
- Container: Wählen Sie die Container-App aus, die Sie erstellt haben, um Ihre App zu hosten.
- Diensttyp: Wählen Sie Blob Storage aus.
- Abonnement: Wählen Sie das Abonnement aus, das als Besitzer der Container-App fungiert.
- Verbindungsname: Geben Sie den Namen
scalablerazorstorage
ein. - Clienttyp: Wählen Sie .NET und anschließend Weiter aus.
- Wählen Sie Systemseitig zugewiesene verwaltete Identität und dann Weiter aus.
- Übernehmen Sie die Standardnetzwerkeinstellungen, und wählen Sie Weiter aus.
- Wählen Sie Erstellen aus, nachdem Azure die Einstellungen überprüft hat.
Wiederholen Sie die vorherigen Einstellungen für den Schlüsseltresor. Wählen Sie den entsprechenden Schlüsseltresordienst und Schlüssel auf der Registerkarte Grundlagen aus.
Azure App Service ohne Azure SignalR Service
Wenn Azure SignalR Service nicht verwendet wird, muss für App Service die ARR-Affinität (Application Request Routing) und WebSocket konfiguriert werden. Clients verbinden ihre WebSockets direkt mit der App, nicht über Azure SignalR Service.
Berücksichtigen Sie beim Konfigurieren der App Folgendes:
IIS
Aktivieren Sie bei Verwendung von IIS Folgendes:
Kubernetes
Erstellen Sie eine Eingangsdefinition mithilfe der folgenden Kubernetes-Anmerkungen für persistente Sitzungen:
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"
Linux mit Nginx
Folgen Sie der Anleitung für eine SignalR-App in ASP.NET Core mit den folgenden Änderungen:
- Ändern Sie den
location
-Pfad von/hubroute
(location /hubroute { ... }
) in den Stammpfad/
(location / { ... }
). - Entfernen Sie die Konfiguration für die Proxypufferung (
proxy_buffering off;
), da die Einstellung nur für vom Server gesendete Ereignisse (Server-Sent Events, SSE) gilt, die für die Interaktion zwischen Blazor-App-Client und -Server nicht relevant sind.
Weitere Informationen und einen Leitfaden zur Konfiguration finden Sie in den folgenden Ressourcen:
- ASP.NET Core: Hosten in der Produktion und Skalieren vonSignalR
- Hosten von ASP.NET Core unter Linux mit Nginx
- Konfigurieren von ASP.NET Core zur Verwendung mit Proxyservern und Lastenausgleich
- NGINX als WebSocket-Proxy
- WebSocket-Proxyfunktion
- Wenden Sie sich an Entwickler*innen in Nicht-Microsoft-Supportforen:
Linux mit Apache
Konfigurieren Sie ProxyPass
für den HTTP- und WebSockets-Datenverkehr, um eine Blazor-App hinter Apache unter Linux zu hosten.
Im folgenden Beispiel:
- Der Kestrel-Server wird auf dem Hostcomputer ausgeführt.
- Die App lauscht an Port 5000 auf Datenverkehr.
ProxyPreserveHost On
ProxyPassMatch ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass /_blazor ws://localhost:5000/_blazor
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
Aktivieren Sie die folgenden Module:
a2enmod proxy
a2enmod proxy_wstunnel
Überprüfen Sie die Browserkonsole auf WebSockets-Fehler. Fehlerbeispiele:
- Firefox kann unter ws://the-domain-name.tld/_blazor?id=XXX keine Verbindung mit dem Server herstellen.
- Fehler: "Failed to start the transport 'WebSockets'" (Beim Starten des Transports „Websockets“ ist ein Fehler aufgetreten): Fehler: "There was an error with the transport." (Beim Transport ist ein Fehler aufgetreten.)
- Fehler: "Failed to start the transport 'LongPolling'" (Beim Starten des Transports „LongPolling“ ist ein Fehler aufgetreten): "TypeError: this.transport is undefined" (TypeError: Dieser Transport ist nicht definiert)
- Fehler: "Unable to connect to the server with any of the available transports." (Es kann mit keinem der verfügbaren Transporte eine Verbindung mit dem Server hergestellt werden.) "WebSockets failed" (WebSockets-Fehler)
- Fehler: "Cannot send data if the connection is not in the 'Connected' State." (Es können keine Daten gesendet werden, wenn die Verbindung nicht den Zustand „Verbunden“ aufweist.)
Weitere Informationen und einen Leitfaden zur Konfiguration finden Sie in den folgenden Ressourcen:
- Hosten von ASP.NET Core unter Linux mit Apache
- Konfigurieren von ASP.NET Core zur Verwendung mit Proxyservern und Lastenausgleich
- Apache-Dokumentation
- Wenden Sie sich an Entwickler*innen in Nicht-Microsoft-Supportforen:
Messen der Netzwerklatenz
Mit JS-Interop kann die Netzwerklatenz gemessen werden, wie im folgenden Beispiel veranschaulicht.
Shared/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
@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();
}
}
}
Für eine angemessene Benutzeroberflächenerfahrung wird eine dauerhafte Benutzeroberflächenlatenz von höchstens 250 ms empfohlen.
Speicherverwaltung
Auf dem Server wird für jede Benutzersitzung eine neue Verbindung erstellt. Jede Benutzersitzung entspricht dem Rendern eines einzelnen Dokuments im Browser. Sie erstellen mehrere Registerkarten beispielsweise mehrere Sitzungen.
Blazor unterhält eine konstante Verbindung (als Leitung bezeichnet) mit dem Browser, der die Sitzung initiiert hat. Verbindungen können jederzeit aus verschiedenen Gründen unterbrochen werden, z. B. wenn die Netzwerkkonnektivität von Benutzer*innen verloren geht oder diese den Browser abrupt schließen. Wenn eine Verbindung unterbrochen wird, verfügt Blazor über einen Wiederherstellungsmechanismus, der eine begrenzte Anzahl von Leitungen in einem „getrennten“ Pool platziert, sodass Clients eine begrenzte Zeit haben, um die Verbindung und die Sitzung wiederherzustellen (Standard: 3 Minuten).
Nach diesem Zeitpunkt gibt Blazor die Verbindung frei und verwirft die Sitzung. Ab diesem Zeitpunkt ist die Leitung für die Garbage Collection (GC) freigegeben und kann beansprucht werden, wenn eine Sammlung für die GC-Generierung der Leitung ausgelöst wird. Ein wichtiger Aspekt dabei ist, dass Leitungen eine lange Lebensdauer haben, sodass die meisten Objekte, die aus der Leitung stammen, schließlich Gen2 erreichen. Daher werden diese Objekte möglicherweise erst freigegeben, wenn eine Gen2-Sammlung erfolgt.
Messen des allgemeinen Speicherverbrauchs
Voraussetzungen:
- Die App muss mit der Releasekonfiguration veröffentlicht werden. Messungen der Debugkonfiguration sind nicht relevant, da der generierte Code nicht repräsentativ für den Code ist, der für eine Produktionsbereitstellung verwendet wird.
- Die App muss ohne angefügten Debugger ausgeführt werden, da sich dieser ebenfalls auf das Verhalten der App auswirken und die Ergebnisse beeinträchtigen kann. Starten Sie die App in Visual Studio ohne Debugging, indem Sie auf der Menüleiste Debuggen>Ohne Debuggen starten auswählen oder die Tastenkombination STRG+F5 drücken.
- Betrachten Sie die verschiedenen Speichertypen, um zu verstehen, wie viel Arbeitsspeicher tatsächlich von .NET verwendet wird. Im Allgemeinen überprüfen Entwickler*innen die Nutzung des App-Arbeitsspeichers unter Windows-Betriebssystemen im Task-Manager. Dort wird aber in der Regel die Obergrenze des tatsächlich verwendeten Arbeitsspeichers angezeigt. Weitere Informationen finden Sie in den folgenden Artikeln:
- .NET-Leistungsanalyse für Speicher: Lesen Sie insbesondere den Abschnitt zu Arbeitsspeichergrundlagen.
- Workflow zur Diagnose von Problemen mit der Speicherleistung (dreiteilige Reihe): Links zu den drei Artikeln der Reihe finden Sie ganz oben in jedem Artikel der Reihe.
Speicherverbrauch angewandt auf Blazor
Der von Blazor verwendete Speicher wird wie folgt berechnet:
(Aktive Leitungen × Speicher pro Leitung) + (Getrennte Leitungen × Speicher pro Leitung)
Die Menge des Arbeitsspeichers, den eine Leitung nutzt, und die maximale Anzahl potenziell aktiver Leitungen, die eine App verwalten kann, hängen sehr stark davon ab, wie die App geschrieben ist. Die maximale Anzahl möglicher aktiver Leitungen wird grob wie folgt beschrieben:
Maximal verfügbarer Speicher / Speicher pro Leitung = Maximale Anzahl potenziell aktive Leitungen
Damit in Blazor ein Arbeitsspeicherverlust auftritt, muss Folgendes zutreffen:
- Der Speicher muss vom Framework und nicht von der App zugewiesen werden. Wenn Sie ein Array mit 1 GB in der App zuweisen, muss die App die Bereinigung des Arrays verwalten.
- Der Speicher darf nicht aktiv genutzt werden. Das bedeutet, dass die Leitung nicht aktiv ist und aus dem Cache für getrennte Leitungen entfernt wurde. Wenn die maximale Anzahl aktiver Leitungen ausgeführt wird, ist Arbeitsspeichermangel ein Skalierungsproblem, kein Arbeitsspeicherverlust.
- Eine Garbage Collection (GC) für die GC-Generation der Leitung wurde ausgeführt, aber der Garbage Collector konnte die Leitung nicht beanspruchen, da ein anderes Objekt im Framework einen starken Verweis auf die Leitung enthält.
In anderen Fällen tritt kein Arbeitsspeicherverlust auf. Wenn die Leitung aktiv ist (verbunden oder getrennt), wird sie weiterhin verwendet.
Wenn eine Sammlung für die GC-Generation der Leitung nicht ausgeführt wurde, wird der Speicher nicht freigegeben, da der Garbage Collector den Speicher zu diesem Zeitpunkt nicht freigeben muss.
Wenn eine Sammlung für eine GC-Generation ausgeführt wird und die Leitung freigibt, müssen Sie den Arbeitsspeicher mit den GC-Statistiken und nicht anhand des Prozesses überprüfen, da .NET möglicherweise entscheidet, den virtuellen Arbeitsspeicher aktiv zu halten.
Wenn der Arbeitsspeicher nicht freigegeben wird, müssen Sie eine Leitung finden, die weder aktiv noch getrennt ist und die von einem anderen Objekt im Framework stammt. In jedem anderen Fall besteht ein App-Problem im Entwicklungscode, wenn kein Speicher freigegeben werden kann.
Reduzieren des Arbeitsspeicherverbrauchs
Wenden Sie eine der folgenden Strategien an, um den Arbeitsspeicherverbrauch einer App zu reduzieren:
- Begrenzen Sie den gesamte vom .NET-Prozess genutzten Arbeitsspeicher. Weitere Informationen finden Sie unter Runtimekonfigurationsoptionen für Garbage Collection.
- Reduzieren Sie die Anzahl der getrennten Leitungen.
- Reduzieren Sie die Zeit, die sich eine Leitung im getrennten Zustand befinden darf.
- Lösen Sie manuell eine Garbage Collection aus, um während einer Downtime eine Sammlung auszuführen.
- Konfigurieren Sie die Garbage Collection nicht im anstelle des Servermodus, sondern im Arbeitsstationsmodus, der die Garbage Collection aggressiv auslöst.
Zusätzliche Aktionen
- Erfassen Sie ein Speicherabbild des Prozesses, wenn der Arbeitsspeicherbedarf hoch ist, und identifizieren Sie die Objekte, die den meisten Arbeitsspeicher beanspruchen, und ihren Ursprung (von wo aus darauf verwiesen wird).
- .NET gibt den Arbeitsspeicher im Servermodus nur dann sofort für das Betriebssystem frei, wenn dies erzwungen wird. Weitere Informationen zu Einstellungen in der Projektdatei (
.csproj
) zum Steuern dieses Verhaltens finden Sie unter Runtimekonfigurationsoptionen für Garbage Collection. - Bei der Garbage Collection im Servermodus wird davon ausgegangen, dass Ihre App die einzige ist, die auf dem System ausgeführt wird, und alle Ressourcen des Systems verwenden kann. Wenn das System über 50 GB verfügt, versucht der Garbage Collector, die vollen 50 GB des verfügbaren Arbeitsspeichers zu verwenden, bevor er eine Gen2-Sammlung auslöst.
Weitere Informationen zur Konfiguration der Aufbewahrung von getrennten Leitungen finden Sie im Leitfaden zu ASP.NET Core BlazorSignalR.