Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Opmerking
Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.
Waarschuwing
Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 9-versie van dit artikelvoor de huidige release.
Belangrijk
Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.
Zie de .NET 9-versie van dit artikelvoor de huidige release.
Dit artikel legt uit hoe u server-side Blazor apps (Blazor Web Apps en Blazor Server apps) host en implementeert met behulp van ASP.NET Core.
Hostconfiguratiewaarden
Apps aan de serverzijde Blazor kunnen algemene hostconfiguratiewaarden accepteren.
Implementatie
Bij gebruik van een server-side hostingmodel wordt Blazor binnen een ASP.NET Core-app op de server uitgevoerd. Ui-updates, gebeurtenisafhandeling en JavaScript-aanroepen worden verwerkt via een SignalR verbinding.
Een webserver die een ASP.NET Core-app kan hosten, is vereist. Visual Studio bevat een app-projectsjabloon aan de serverzijde. Zie Blazorvoor meer informatie over Blazor projectsjablonen.
Publiceer een app in de Release-configuratie en implementeer de inhoud van de bin/Release/{TARGET FRAMEWORK}/publish map, waarbij de {TARGET FRAMEWORK} tijdelijke aanduiding op het doelframework doelt.
Schaalbaarheid
Wanneer u rekening houdt met de schaalbaarheid van één server (omhoog schalen), is het geheugen dat beschikbaar is voor een app waarschijnlijk de eerste resource die door de app wordt uitgeput naarmate de vraag van de gebruiker toeneemt. Het beschikbare geheugen op de server is van invloed op het volgende:
- Aantal actieve circuits dat een server kan ondersteunen.
 - UI-latentie aan de clientkant.
 
Zie de volgende bronnen voor hulp bij het bouwen van beveiligde en schaalbare apps aan de serverzijde Blazor :
- Richtlijnen voor dreigingsmitigatie voor statische server-side rendering in ASP.NET CoreBlazor
 - Richtlijnen voor bedreigingsbeperking voor ASP.NET Core Blazor interactieve rendering aan de serverzijde
 
Elk circuit gebruikt ongeveer 250 KB geheugen voor een minimale Hello World-app. De grootte van een circuit is afhankelijk van de code van de app en de onderhoudsvereisten voor de status die aan elk onderdeel zijn gekoppeld. We raden u aan om de resourcevereisten tijdens de ontwikkeling voor uw app en infrastructuur te meten, maar de volgende basislijn kan een uitgangspunt zijn bij het plannen van uw implementatiedoel: als u verwacht dat uw app ondersteuning biedt voor 5000 gelijktijdige gebruikers, kunt u overwegen om ten minste 1,3 GB servergeheugen te budgetteren voor de app (of ongeveer 273 KB per gebruiker).
Blazor WebAssembly statische asset vooraf laden
Het ResourcePreloader onderdeel in de hoofdinhoud van het App onderdeel (App.razor) wordt gebruikt om te verwijzen naar Blazor statische assets. Het onderdeel wordt geplaatst na de basis-URL-tag (<base>):
<ResourcePreloader />
Een Razor onderdeel wordt gebruikt in plaats van <link> elementen omdat:
- Met het onderdeel kan de basis-URL (de kenmerkwaarde 
<base>van de tag) de hoofdmap van dehrefapp binnen een ASP.NET Core-app correct herkennen. - De functie kan worden verwijderd door de 
ResourcePreloaderonderdeeltag uit hetApponderdeel te verwijderen. Dit is handig in gevallen waarin de app eenloadBootResourcecallback gebruikt om URL's te wijzigen. 
configuratie van SignalR
SignalRDe hosting- en schaalvoorwaarden zijn van toepassing op Blazor apps die gebruikmaken van SignalR.
Zie SignalRvoor meer informatie over Blazor appsBlazor, inclusief configuratierichtlijnen.
Transporten
Blazor werkt het beste bij het gebruik van WebSockets als transport SignalR vanwege een lagere latentie, betere betrouwbaarheid en verbeterde beveiliging. Long Polling wordt gebruikt SignalR wanneer WebSockets niet beschikbaar is of wanneer de app expliciet is geconfigureerd voor het gebruik van Long Polling.
Er wordt een consolewaarschuwing weergegeven als Long Polling wordt gebruikt:
Aansluiting via WebSockets is mislukt, wordt gebruik gemaakt van long polling als back-uptransport. Dit kan het gevolg zijn van een VPN of proxy die de verbinding blokkeert.
Algemene implementatie- en verbindingsfouten
Aanbevelingen voor wereldwijde implementaties naar geografische datacenters:
- Implementeer de app in de regio's waar de meeste gebruikers zich bevinden.
 - Let op de toegenomen latentie voor verkeer over continenten. Zie ASP.NET Core-richtlijnen BlazorSignalRvoor het beheren van het uiterlijk van de gebruikersinterface voor opnieuw verbinden.
 - Overweeg het gebruik van de Azure-serviceSignalR.
 
Azure App Service
Hosting in Azure App Service vereist configuratie voor WebSockets en sessieaffiniteit, ook wel ARR-affiniteit (Application Request Routing) genoemd.
Opmerking
Voor een Blazor app in Azure App Service is geen Azure SignalR Service vereist.
Schakel het volgende in voor de registratie van de app in Azure App Service:
- WebSockets om het WebSockets-transport mogelijk te maken. De standaardinstelling is uitgeschakeld.
 - Sessieaffiniteit om aanvragen van een gebruiker terug te sturen naar hetzelfde App Service-exemplaar. De standaardinstelling is Aan.
 
- Navigeer in Azure Portal naar de web-app in App Services.
 - Open Instellingenconfiguratie>.
 - Stel websockets in op Aan.
 - Controleer of sessieaffiniteit is ingesteld op Aan.
 
Azure SignalR Dienst
De optionele Azure SignalR Service- werkt in combinatie met de SignalR hub van de app voor het omhoog schalen van een app aan de serverzijde naar een groot aantal gelijktijdige verbindingen. Bovendien helpen het wereldwijde bereik en de hoogwaardige prestatiedatacenters van de service aanzienlijk om de latentie te verminderen vanwege geografische factoren.
De service is niet vereist voor Blazor apps die worden gehost in Azure App Service of Azure Container Apps, maar kan nuttig zijn in andere hostingomgevingen:
- Om het uitschalen van verbindingen te vergemakkelijken.
 - Globale distributie beheren.
 
De Azure SignalR-service met SDK v1.26.1 of hoger ondersteunt SignalR opnieuw verbinden met toestandsbehoud (WithStatefulReconnect).
In het geval dat de app gebruikmaakt van Long Polling of terugvalt op Long Polling in plaats van WebSockets, moet u mogelijk het maximale poll-interval configureren (MaxPollIntervalInSecondsstandaard: 5 seconden, limiet: 1-300 seconden), waarmee het maximale poll-interval wordt gedefinieerd dat is toegestaan voor Long Polling-verbindingen in de Azure-service SignalR . Als de volgende poll-aanvraag niet binnen het maximale poll-interval binnenkomt, sluit de service de clientverbinding.
Zie Een ASP.NET Core-app SignalR publiceren naar Azure App Service voor hulp bij het toevoegen van de service als een afhankelijkheid aan een productie-implementatie.
Zie voor meer informatie:
- Azure SignalR Service
 - Wat is Azure SignalR Service?
 - ASP.NET Core SignalR productiehosting en schaalbaarheid
 - Een ASP.NET Core SignalR-app publiceren naar Azure App Service-
 
Azure Container Apps - een dienst van Microsoft waarmee je containers kunt uitvoeren en beheren in de cloud.
Zie Blazor voor meer informatie over het schalen van apps aan de serverzijde in de Azure Container Apps-service. In de zelfstudie wordt uitgelegd hoe u de services maakt en integreert die nodig zijn voor het hosten van apps in Azure Container Apps. In deze sectie vindt u ook basisstappen.
Configureer de Azure Container Apps-service voor sessieaffiniteit door de richtlijnen in sessieaffiniteit in Azure Container Apps (Azure-documentatie) te volgen.
De service ASP.NET Core Data Protection (DP) moet worden geconfigureerd om sleutels te behouden op een centrale locatie waartoe alle containerinstanties toegang hebben. De sleutels kunnen worden opgeslagen in Azure Blob Storage en worden beveiligd met Azure Key Vault. De DP-service gebruikt de sleutels om Razor-onderdelen te deserialiseren. Raadpleeg de volgende NuGet-pakketten om de DP-service te configureren voor het gebruik van Azure Blob Storage en Azure Key Vault:
- 
              
Azure.Identity: biedt klassen om te werken met de Azure-services voor identiteits- en toegangsbeheer. - 
              
Microsoft.Extensions.Azure: Biedt nuttige uitbreidingsmethoden voor het uitvoeren van kernconfiguraties van Azure. - 
              
Azure.Extensions.AspNetCore.DataProtection.Blobs: Hiermee kunt u ASP.NET Core Data Protection-sleutels opslaan in Azure Blob Storage, zodat sleutels kunnen worden gedeeld in verschillende exemplaren van een web-app. - 
              
Azure.Extensions.AspNetCore.DataProtection.Keys: Schakelt het beveiligen van sleutels in rust in met behulp van de azure Key Vault-sleutelversleuteling/wrapping-functie. 
Opmerking
Zie de artikelen onder Pakketten installeren en beheren bij Verbruikswerkstroom voor pakketten (NuGet-documentatie)voor begeleiding bij het toevoegen van pakketten in .NET-apps. Bevestig de juiste pakketversies op NuGet.org.
- 
              
 Werk
Program.csbij met de volgende gemarkeerde 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();Met de voorgaande wijzigingen kan de app de DP-service beheren met behulp van een gecentraliseerde, schaalbare architectuur. DefaultAzureCredential detecteert de beheerde identiteit van de container-app nadat de code is geïmplementeerd in Azure en gebruikt deze om verbinding te maken met blobopslag en de sleutelkluis van de app.
Voer de volgende stappen uit om de beheerde identiteit voor de container-app te creëren en toegang te verlenen tot blobopslag en een sleutelkluis:
- Navigeer in Azure Portal naar de overzichtspagina van de container-app.
 - Selecteer ServiceConnector in het linkernavigatievenster.
 - Selecteer + Maken in de bovenste navigatiebalk.
 - Voer in het flyoutmenu Verbinding maken de volgende waarden in: 
- Container: Selecteer de container-app die u hebt gemaakt om uw app te hosten.
 - Servicetype: Selecteer Blob Storage.
 - Abonnement: Selecteer het abonnement dat eigenaar is van de container-app.
 - 
              Verbindingsnaam: Voer een naam in van 
scalablerazorstorage. - Clienttype: Selecteer .NET en selecteer vervolgens 'Volgende'.
 
 - Selecteer Door het systeem toegewezen beheerde identiteit en selecteer Volgende.
 - Gebruik de standaardnetwerkinstellingen en selecteer Volgende.
 - Nadat Azure de instellingen heeft gevalideerd, selecteert u maken.
 
Herhaal de voorgaande instellingen voor de Key Vault. Selecteer de juiste sleutelkluisservice en -sleutel op het tabblad Basisbeginselen .
Opmerking
In het voorgaande voorbeeld wordt gebruikgemaakt DefaultAzureCredential van het vereenvoudigen van verificatie bij het ontwikkelen van apps die in Azure worden geïmplementeerd door referenties te combineren die worden gebruikt in Azure-hostingomgevingen met referenties die worden gebruikt in lokale ontwikkeling. Wanneer u overstapt op productie, is een alternatief een betere keuze, zoals ManagedIdentityCredential. Zie Azure-gehoste .NET-apps verifiëren bij Azure-resources met behulp van een door het systeem toegewezen beheerde identiteit voor meer informatie.
IIS
Wanneer u IIS gebruikt, schakelt u het volgende in:
Zie de richtlijnen en externe IIS-resourcekruiskoppelingen in Een ASP.NET Core-app publiceren naar IIS voor meer informatie.
Kubernetes
Maak een ingress-definitie met de volgende Kubernetes-annotaties voor sessieaffiniteit:
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 met Nginx
Volg de richtlijnen voor een ASP.NET Core SignalR-app met de volgende wijzigingen:
- Wijzig het 
locationpad van/hubroute(location /hubroute { ... }) in het hoofdpad/(location / { ... }). - Verwijder de configuratie voor proxybuffering (
proxy_buffering off;) omdat de instelling alleen van toepassing is op Server-Sent Gebeurtenissen (SSE), die niet relevant zijn voor Blazor client-serverinteracties van de app. 
Raadpleeg de volgende bronnen voor meer informatie en configuratierichtlijnen:
- ASP.NET Core SignalR productiehosting en schaalbaarheid
 - Host ASP.NET Core op Linux met Nginx
 - Configureer ASP.NET Core voor gebruik met proxyservers en load balancers
 - NGINX als een WebSocket-proxy
 - WebSocket-proxying
 - Raadpleeg ontwikkelaars op niet-Microsoft-ondersteuningsforums:
 
Linux met Apache
Als u een Blazor app wilt hosten achter Apache op Linux, configureert u ProxyPass deze voor HTTP- en WebSockets-verkeer.
In het volgende voorbeeld:
- Kestrel de server draait op de host.
 - De app luistert naar verkeer op poort 5000.
 
ProxyPreserveHost   On
ProxyPassMatch      ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass           /_blazor ws://localhost:5000/_blazor
ProxyPass           / http://localhost:5000/
ProxyPassReverse    / http://localhost:5000/
Schakel de volgende modules in:
a2enmod   proxy
a2enmod   proxy_wstunnel
Controleer de browserconsole op WebSockets-fouten. Voorbeeldfouten:
- Firefox kan geen verbinding maken met de server op ws://the-domain-name.tld/_blazor?id=XXX
 - Fout: Kan het transport WebSockets niet starten: fout: er is een fout opgetreden bij het transport.
 - Fout: Kan het transport 'LongPolling' niet starten: TypeError: this.transport is undefined
 - Fout: Kan geen verbinding maken met de server met een van de beschikbare transporten. WebSockets zijn mislukt
 - Fout: kan geen gegevens verzenden als de verbinding niet de status Verbonden heeft.
 
Raadpleeg de volgende bronnen voor meer informatie en configuratierichtlijnen:
- Configureer ASP.NET Core voor gebruik met proxyservers en load balancers
 - Apache-documentatie
 - Raadpleeg ontwikkelaars op niet-Microsoft-ondersteuningsforums:
 
Netwerklatentie meten
JS interop kan worden gebruikt om de netwerklatentie te meten, zoals in het volgende voorbeeld wordt gedemonstreert.
              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();
        }
    }
}
Voor een redelijke gebruikersinterface-ervaring raden we u aan om een duurzame UI-latentie van 250 ms of minder te gebruiken.