Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Varning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Viktigt!
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Den här artikeln beskriver hur du värdshåller och distribuerar Blazor-appar på serversidan (Blazor Web App- och Blazor Server-appar) med hjälp av ASP.NET Core.
Värdkonfigurationsvärden
Appar på serversidan Blazor kan acceptera allmänna värdkonfigurationsvärden.
Driftsättning
Med hjälp av en värdmodell Blazor på serversidan körs den på servern inifrån en ASP.NET Core-app. Användargränssnittsuppdateringar, händelsehantering och JavaScript-anrop hanteras via en SignalR anslutning.
En webbserver som kan vara värd för en ASP.NET Core-app krävs. Visual Studio innehåller en projektmall på serversidan. Mer information om Blazor projektmallar finns i ASP.NET Core Blazor projektstruktur.
Publicera en app i Versionskonfiguration och distribuera innehållet i bin/Release/{TARGET FRAMEWORK}/publish mappen, där {TARGET FRAMEWORK} platshållaren är målramverket.
Skalbarhet
När du överväger skalbarheten för en enskild server (skala upp) är det minne som är tillgängligt för en app sannolikt den första resursen som appen avgaser när användarnas krav ökar. Det tillgängliga minnet på servern påverkar:
- Antal aktiva kretsar som en server kan stödja.
- Svarstid för användargränssnittet på klienten.
Information om hur du skapar säkra och skalbara appar på serversidan finns Blazor i följande resurser:
- Vägledning för hotreducering för ASP.NET Core serverbaserad statisk Blazor återgivning
- Vägledning för hotminskning för ASP.NET Core Blazor interaktiv serversideåtergivning
Varje krets använder cirka 250 KB minne för en minimal Hello World-app. Storleken på en krets beror på appens kod och de tillståndsunderhållskrav som är associerade med varje komponent. Vi rekommenderar att du mäter resurskrav under utvecklingen för din app och infrastruktur, men följande baslinje kan vara en startpunkt när du planerar distributionsmålet: Om du förväntar dig att din app ska ha stöd för 5 000 samtidiga användare bör du överväga att budgetera minst 1,3 GB serverminne till appen (eller ~273 KB per användare).
Blazor WebAssembly förhandsladdning av statiska resurser
Komponenten ResourcePreloader i komponentens App huvudinnehåll (App.razor) används för att referera Blazor till statiska tillgångar. Komponenten placeras efter bas-URL-taggen (<base>):
<ResourcePreloader />
En Razor komponent används i stället för <link> element eftersom:
- Komponenten gör det möjligt för bas-URL:en (<base>taggenshrefattributvärde) att korrekt identifiera roten av Blazor-appen inom en ASP.NET Core-app.
- Funktionen kan tas bort genom att ta bort komponenttaggen ResourcePreloaderfrån komponentenApp. Det här är användbart i fall där appen använder ettloadBootResourceåteranrop för att ändra URL:er.
SignalR konfiguration
SignalRvärd- och skalningsvillkor gäller för Blazor appar som använder SignalR.
Mer information om SignalR i Blazor appar, inklusive konfigurationsvägledning, finns i ASP.NET Core-vägledningBlazorSignalR.
Transporter
Blazor fungerar bäst när du använder WebSockets som SignalR transport på grund av lägre svarstid, bättre tillförlitlighet och förbättrad säkerhet. Long Polling används av SignalR när WebSockets inte är tillgängligt eller när appen uttryckligen har konfigurerats för att använda Long Polling.
En konsolvarning visas om Long Polling används:
Det gick inte att ansluta via WebSockets, så fallback-transportmetoden Long Polling används. Detta kan bero på att ett VPN eller en proxy blockerar anslutningen.
Globala distributions- och anslutningsfel
Rekommendationer för globala distributioner till geografiska datacenter:
- Distribuera appen till de regioner där de flesta användare finns.
- Ta hänsyn till den ökade svarstiden för trafik över kontinenter. Information om hur du styr utseendet på återanslutningsgränssnittet finns i ASP.NET Core-vägledningBlazorSignalR.
- Överväg att använda Azure SignalR Service.
Azure App Service
Värdtjänster i Azure App Service kräver konfiguration för WebSockets och sessionstillhörighet, även kallat ARR-tillhörighet (Application Request Routing).
Anmärkning
En Blazor app i Azure App Service kräver inte Azure SignalR Service.
Aktivera följande för appens registrering i Azure App Service:
- WebSockets så att WebSockets-transporten kan fungera. Standardinställningen är Av.
- Sessionstillhörighet för att dirigera begäranden från en användare tillbaka till samma App Service-instans. Standardinställningen är På.
- I Azure-portalen navigerar du till webbappen i App Services.
- Öppna Konfiguration av inställningar>.
- Aktivera Web sockets till På.
- Kontrollera att Sessionstillhörighet är inställt på På.
Azure SignalR Tjänst
Den valfria Azure SignalR Service- fungerar tillsammans med appens SignalR hubb för att skala upp en app på serversidan till ett stort antal samtidiga anslutningar. Dessutom bidrar tjänstens globala räckvidd och högpresterande datacenter avsevärt till att minska svarstiden på grund av geografi.
Tjänsten krävs inte för Blazor appar som finns i Azure App Service eller Azure Container Apps, men kan vara till hjälp i andra värdmiljöer:
- För att underlätta utskalning av anslutningar.
- Hantera global distributionen.
Azure SignalR Service med SDK v1.26.1 eller senare stöder SignalR tillståndskänslig återanslutning (WithStatefulReconnect).
Om appen använder Long Polling eller återgår till Long Polling i stället för WebSockets kan du behöva konfigurera det maximala avsökningsintervallet (MaxPollIntervalInSecondsstandard: 5 sekunder, gräns: 1–300 sekunder), vilket definierar det maximala avsökningsintervallet som tillåts för långa avsökningsanslutningar i Azure SignalR Service. Om nästa avsökningsbegäran inte kommer inom det maximala avsökningsintervallet stänger tjänsten klientanslutningen.
Information om hur du lägger till tjänsten som ett beroende i en produktionsdistribution finns i Publicera en ASP.NET Core-app SignalR till Azure App Service.
Mer information finns i:
- Azure SignalR Tjänst
- Vad är Azure SignalR Service?
- ASP.NET Core-produktionsvärd SignalR och skalning
- Publicera en ASP.NET Core SignalR-app till Azure App Service
Azure Container-appar
En djupare undersökning av skalning av appar på serversidan Blazor i Azure Container Apps-tjänsten finns i Skala ASP.NET Core Apps i Azure. Handledningen förklarar hur du skapar och integrerar de tjänster som krävs för att hosta appar i Azure Container Apps. Grundläggande steg finns också i det här avsnittet.
- Konfigurera Azure Container Apps-tjänsten för sessionstillhörighet genom att följa riktlinjerna i Sessionstillhörighet i Azure Container Apps (Azure-dokumentation). 
- Tjänsten ASP.NET Core Data Protection (DP) måste konfigureras för att bevara nycklar på en central plats som alla containerinstanser kan komma åt. Nycklarna kan lagras i Azure Blob Storage och skyddas med Azure Key Vault. DP-tjänsten använder nycklarna för att deserialisera Razor komponenter. Om du vill konfigurera DP-tjänsten att använda Azure Blob Storage och Azure Key Vault refererar du till följande NuGet-paket: - 
              Azure.Identity: Tillhandahåller klasser för att arbeta med Azures identitets- och åtkomsthanteringstjänster.
- 
              Microsoft.Extensions.Azure: Tillhandahåller användbara tilläggsmetoder för att utföra grundläggande Azure-konfigurationer.
- 
              Azure.Extensions.AspNetCore.DataProtection.Blobs: Tillåter lagring av ASP.NET Core Data Protection-nycklar i Azure Blob Storage så att nycklar kan delas mellan flera instanser av en webbapp.
- 
              Azure.Extensions.AspNetCore.DataProtection.Keys: Aktiverar skydd av vilande nycklar med hjälp av nyckelkryptering/omslutningsfunktionen i Azure Key Vault.
 - Anmärkning - Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket på Arbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org. 
- 
              
- Uppdatera - Program.csmed följande markerade kod:- 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();- De föregående ändringarna gör det möjligt för appen att hantera DP-tjänsten med hjälp av en centraliserad, skalbar arkitektur. DefaultAzureCredential identifierar den hanterade identiteten för containerappen när koden har distribuerats till Azure och använder den för att ansluta till bloblagring och appens nyckelvalv. 
- Utför följande steg för att skapa den hanterade identiteten för containerappen och ge den åtkomst till bloblagring och ett nyckelvalv: - I Azure-portalen går du till översiktssidan för containerappen.
- Välj Tjänstanslutning i det vänstra navigeringsfältet.
- Välj + Skapa i det övre navigeringsfönstret.
- I den utfällbara menyn Skapa anslutning anger du följande värden: - Container: Välj den containerapp som du skapade som värd för din app.
- Tjänsttyp: Välj Blob Storage.
- Prenumeration: Välj den prenumeration som äger containerappen.
- 
              Anslutningsnamn: Ange namnet scalablerazorstorage.
- Klienttyp: Välj .NET och välj sedan Nästa.
 
- Välj Systemtilldelad hanterad identitet och välj Nästa.
- Använd standardinställningarna för nätverket och välj Nästa.
- När Azure har verifierat inställningarna väljer du Skapa.
 - Upprepa de föregående inställningarna för nyckelvalvet. Välj lämplig nyckelvalvstjänst och nyckel på fliken Grundläggande . 
Anmärkning
I föregående exempel används DefaultAzureCredential för att förenkla autentiseringen vid utveckling av appar som distribueras till Azure genom att kombinera autentiseringsuppgifter som används i Azure-värdmiljöer med autentiseringsuppgifter som används i lokal utveckling. När du flyttar till produktion är ett bättre alternativ till exempel ManagedIdentityCredential. Mer information finns i Autentisera Azure-hostade .NET-appar till Azure-resurser med en systemtilldelad hanterad identitet.
IIS
När du använder IIS aktiverar du:
Mer information finns i vägledningen och externa IIS-resurslänkar i Publicera en ASP.NET Core-app till IIS.
Kubernetes (på engelska)
Skapa en ingressdefinition med följande Kubernetes-annotationer för sessionstillhörighet:
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 med Nginx
Följ riktlinjerna för en ASP.NET Core SignalR-app med följande ändringar:
- 
              locationÄndra sökvägen från/hubroute(location /hubroute { ... }) till rotsökvägen/(location / { ... }).
- Ta bort konfigurationen för proxybuffertning (proxy_buffering off;) eftersom inställningen endast gäller för Server-Sent Events (SSE), som inte är relevanta för Blazor app-klient-server-interaktioner.
Mer information och konfigurationsvägledning finns i följande resurser:
- ASP.NET Core-produktionsvärd SignalR och skalning
- Hosting av ASP.NET Core på Linux med Nginx
- Konfigurera ASP.NET Core att fungera med proxyservrar och lastbalanserare
- NGINX som WebSocket-proxy
- WebSocket-proxyhantering
- Kontakta utvecklare på supportforum som inte kommer från Microsoft:
Linux med Apache
Om du vill vara värd för en Blazor app bakom Apache i Linux konfigurerar du ProxyPass för HTTP- och WebSockets-trafik.
I följande exempel:
- Kestrel servern körs på värddatorn.
- Appen lyssnar efter trafik på port 5000.
ProxyPreserveHost   On
ProxyPassMatch      ^/_blazor/(.*) http://localhost:5000/_blazor/$1
ProxyPass           /_blazor ws://localhost:5000/_blazor
ProxyPass           / http://localhost:5000/
ProxyPassReverse    / http://localhost:5000/
Aktivera följande moduler:
a2enmod   proxy
a2enmod   proxy_wstunnel
Kontrollera efter WebSocket-fel i webbläsarkonsolen. Exempelfel:
- Firefox kan inte upprätta en anslutning till servern på ws://the-domain-name.tld/_blazor?id=XXX
- Fel: Det gick inte att starta transporten "WebSockets": Fel: Det uppstod ett fel med transporten.
- Fel: Det gick inte att starta transporten 'LongPolling': TypeError: this.transport är odefinierat
- Fel: Det går inte att ansluta till servern med någon av de tillgängliga transporterna. WebSockets misslyckades
- Fel: Det går inte att skicka data om anslutningen inte är i tillståndet Ansluten.
Mer information och konfigurationsvägledning finns i följande resurser:
- Konfigurera ASP.NET Core att fungera med proxyservrar och lastbalanserare
- Apache-dokumentation
- Kontakta utvecklare på supportforum som inte kommer från Microsoft:
Mäta nätverksfördröjning
JS interop kan användas för att mäta nätverksfördröjning, vilket visas i följande exempel.
              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();
        }
    }
}
För en rimlig användargränssnittsupplevelse rekommenderar vi en varaktig svarstid för användargränssnittet på 250 ms eller mindre.
ASP.NET Core