Héberger et déployer des applications Blazor côté serveur

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Cet article explique comment héberger et déployer une application Blazor côté serveur avec ASP.NET Core.

Valeurs de configuration de l’hôte

Les applications Blazor côté serveur peuvent accepter les valeurs de configuration d’hôte générique.

Déploiement

En utilisant un modèle d’hébergement côté serveur, Blazor est exécutée sur le serveur à partir d’une application ASP.NET Core. Les mises à jour de l’interface utilisateur, la gestion des événements et les appels JavaScript sont gérés par le biais d’une connexion SignalR.

Un serveur web capable d’héberger une application ASP.NET Core est nécessaire. Visual Studio inclut un modèle de projet d’application côté serveur. Pour plus d’informations sur les modèles de projet Blazor, consultez ASP.NET structure de projet principale Blazor.

Extensibilité

Lorsque vous envisagez la scalabilité d’un serveur unique (scale-up), la mémoire disponible pour une application est probablement la première ressource que l’application épuise à mesure que les demandes des utilisateurs augmentent. La mémoire disponible sur le serveur affecte :

  • Le nombre de circuits actifs qu’un serveur peut prendre en charge.
  • La latence de l’interface utilisateur sur le client.

Pour obtenir des conseils sur la génération d’applications côté Blazor serveur sécurisées et évolutives, consultez les ressources suivantes :

Chaque circuit utilise environ 250 Ko de mémoire pour une application de style Hello World minimale. La taille d’un circuit dépend du code de l’application et des exigences de maintenance d’état associées à chaque composant. Nous vous recommandons de mesurer les demandes de ressources pendant le développement de votre application et de votre infrastructure, mais la base de référence suivante peut être un point de départ dans la planification de votre cible de déploiement : si vous prévoyez que votre application prenne en charge 5 000 utilisateurs simultanés, envisagez de budgéter au moins 1,3 Go de mémoire serveur pour l’application (ou environ 273 Ko par utilisateur).

Configuration SignalR

Les conditions d’hébergement et de mise à l’échelle de SignalR s’appliquent aux applications Blazor qui utilisent SignalR.

Pour plus d’informations sur les applications SignalR intégrées sur Blazor, y compris des conseils de configuration, consultez les conseils BlazorSignalR ASP.NET Core.

Transports

Blazor fonctionne le mieux lors de l’utilisation de WebSockets en tant que transport SignalR en raison d’une latence plus faible, d’une meilleure fiabilité et d’une sécurité améliorée. L’interrogation longue est utilisée par SignalR lorsque WebSockets n’est pas disponible ou lorsque l’application est explicitement configurée pour utiliser l’interrogation longue. Lors du déploiement sur Azure App Service, configurez l’application pour utiliser WebSockets dans les paramètres du Portail Azure pour le service. Pour plus d’informations sur la configuration de l’application pour Azure App Service, consultez les instructions de publication de SignalR.

Un avertissement de console s’affiche si l’interrogation longue est utilisée :

Échec de la connexion via WebSockets, avec le transport de secours d’interrogation longue. Cela peut être dû au blocage de la connexion par un VPN ou un proxy.

Échecs de déploiement global et de connexion

Recommandations pour les déploiements globaux vers des centres de données géographiques :

  • Déployez l’application dans les régions où résident la plupart des utilisateurs.
  • Prenez en compte la latence accrue du trafic entre les continents. Pour contrôler l’apparition de l’interface utilisateur de reconnexion, consultez Aide ASP.NET Core BlazorSignalR.
  • Pour l’hébergement Azure, utilisez Azure SignalR Service.

Service Azure SignalR

Pour les applications web Blazor qui adoptent un rendu côté serveur interactif, envisagez d’utiliser le service Azure SignalR. Le service fonctionne conjointement avec le hub Blazor de l’application pour effectuer un scale-up vers un grand nombre de connexions SignalR simultanées. De plus, la portée générale du service et les centres de données hautes performances contribuent de manière significative à réduire la latence due aux emplacements géographiques. Si votre environnement d’hébergement gère déjà ces problèmes, l’utilisation du service Azure SignalR n’est pas nécessaire.

Envisagez d’utiliser le service Azure SignalR, qui fonctionne conjointement avec le hub Blazor de l’application pour effectuer un scale-up vers un grand nombre de connexions SignalR simultanées. De plus, la portée générale du service et les centres de données hautes performances contribuent de manière significative à réduire la latence due aux emplacements géographiques. Si votre environnement d’hébergement gère déjà ces problèmes, l’utilisation du service Azure SignalR n’est pas nécessaire.

Important

Lorsque les WebSockets sont désactivés, Azure App Service simule une connexion en temps réel à l’aide de l’interrogation longue HTTP. L’interrogation longue HTTP est sensiblement plus lente que l’exécution avec WebSockets activé, qui n’utilise pas l’interrogation pour simuler une connexion client-serveur. Dans le cas où l’interrogation longue doit être utilisée, vous devrez peut-être configurer l’intervalle d’interrogation maximal (MaxPollIntervalInSeconds), qui définit l’intervalle d’interrogation maximal autorisé pour les connexions d’interrogation longue dans le service Azure SignalR si le service passe de WebSockets à l’interrogation longue. Si la demande d’interrogation suivante ne vient pas dans MaxPollIntervalInSeconds, le service Azure SignalR nettoie la connexion cliente. Notez que le service Azure SignalR nettoie également les connexions lorsque la taille de la mémoire tampon en attente d’écriture est supérieure à 1 Mo pour garantir les performances du service. La valeur par défaut de MaxPollIntervalInSeconds est 5 secondes. Le paramètre est limité à 1 à 300 secondes.

Nous vous recommandons d’utiliser WebSockets pour les applications Blazor côté serveur déployées sur Azure App Service. Le service Azure SignalR utilise des WebSockets par défaut. Si l’application n’utilise pas le service AzureSignalR, consultez Publier une application ASP.NET Core SignalR pour Azure App Service.

Pour plus d'informations, voir :

Configuration

Pour configurer une application pour le service Azure SignalR, l’application doit prendre en charge les sessions persistantes, où les clients sont redirigés vers le même serveur lors de la préversion. L’option ServerStickyMode ou la valeur de configuration est définie sur Required. En règle générale, une application crée la configuration à l’aide de l’une des approches suivantes :

  • Program.cs:

    builder.Services.AddSignalR().AddAzureSignalR(options =>
    {
        options.ServerStickyMode = 
            Microsoft.Azure.SignalR.ServerStickyMode.Required;
    });
    
  • Configuration (utilisez l’une des approches suivantes) :

    • Dans appsettings.json:

      "Azure:SignalR:ServerStickyMode": "Required"
      
    • Paramètres d’application de configuration> d’AppService dans le Portail Azure (Nom : Azure__SignalR__ServerStickyMode, Valeur : Required). Cette approche est adoptée automatiquement pour l’application si vous approvisionnez le service AzureSignalR.

Remarque

L’erreur suivante est générée par une application qui n’a pas activé les sessions persistantes Azure SignalR Service :

blazor.server.js:1 Erreur non interceptée (dans promise) : Appel annulé en raison de la fermeture de la connexion sous-jacente.

Approvisionnez le Service Azure SignalR

Pour approvisionner le service Azure SignalR pour une application dans Visual Studio :

  1. Créez un profil de publication Azure Apps dans Visual Studio pour l’application .
  2. Ajoutez la SignalR dépendance Azure Service au profil. Si l’abonnement Azure n’a pas de instance de service Azure SignalR préexistant à affecter à l’application, sélectionnez Créer un nouveau service Azure SignalR instance pour approvisionner un nouveau service instance.
  3. Publiez l’application sur Azure.

L’approvisionnement du service Azure SignalR dans Visual Studio active automatiquement les sessions persistantes et ajoute la chaîne de connexion SignalR à la configuration du service d’application.

Scalabilité sur les Azure Container Apps

La mise à l’échelle des applications Blazor côté serveur sur Azure Container Apps nécessite des considérations spécifiques en plus de l’utilisation du service AzureSignalR. En raison de la façon dont le routage des requêtes est géré, le service de protection des données ASP.NET Core doit être configuré pour conserver les clés dans un emplacement centralisé auquel toutes les instances de conteneur peuvent accéder. Les clés peuvent être stockées dans Stockage Blob Azure et protégées avec Azure Key Vault. Le service de protection des données utilise les clés pour désérialiser les composants Razor.

Remarque

Pour une exploration plus approfondie de ce scénario et de la mise à l’échelle des applications conteneur, consultez Mise à l’échelle ASP.NET Core Apps sur Azure. Le tutoriel explique comment créer et intégrer les services nécessaires pour héberger des applications sur Azure Container Apps. Les étapes de base sont également fournies dans cette section.

  1. Pour configurer le service de protection des données afin qu’il utilise Stockage Blob Azure et Azure Key Vault, référencez les packages NuGet suivants :

    Remarque

    Pour obtenir des conseils sur l’ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

  2. Mettez à jour Program.cs avec le code mis en évidence suivant :

    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();
    

    Les modifications précédentes permettent à l’application de gérer la protection des données à l’aide d’une architecture centralisée et évolutive. DefaultAzureCredential détecte l’identité managée de l’application conteneur après le déploiement du code sur Azure et l’utilise pour se connecter au stockage blob et au coffre de clés de l’application.

  3. Pour créer l’identité managée de l’application conteneur et lui accorder l’accès au stockage blob et à un coffre de clés, procédez comme suit :

    1. Dans le portail Azure, accédez à la page de vue d’ensemble de l’application conteneur.
    2. Dans la navigation de gauche, sélectionnez Connecteur de services.
    3. Sélectionnez + Créer dans la navigation supérieure.
    4. Dans le menu volant Créer une connexion, entrez les valeurs suivantes :
      • Conteneur : sélectionnez l’application conteneur que vous avez créée pour héberger votre application.
      • Type de service : sélectionnez Stockage Blob.
      • Abonnement : sélectionnez l’abonnement qui possède l’application conteneur.
      • Nom de la connexion : entrez un nom de scalablerazorstorage.
      • Type de client : sélectionnez .NET puis Suivant.
    5. Sélectionnez Identité managée affectée par le système, puis Suivant.
    6. Utilisez les paramètres réseau par défaut et sélectionnez Suivant.
    7. Une fois qu’Azure a validé les paramètres, sélectionnez Créer.

    Répétez les paramètres précédents pour le coffre de clés. Sélectionnez le service de coffre de clés et la clé appropriés dans l’onglet De base.

Azure App Service sans Azure SignalR Service

L’hébergement d’une application web Blazor qui utilise le rendu côté serveur interactif sur Azure App Service nécessite une configuration pour l’affinité Application Request Routing (ARR) et des WebSockets. App Service doit également être distribué globalement de façon appropriée pour réduire la latence de l’interface utilisateur. L’utilisation d’Azure SignalR Service lors de l’hébergement sur Azure App Service n’est pas nécessaire.

L’hébergement d’une application Blazor Server sur Azure App Service nécessite une configuration pour l’affinité Application Request Routing (ARR) et des WebSockets. App Service doit également être distribué globalement de façon appropriée pour réduire la latence de l’interface utilisateur. L’utilisation d’Azure SignalR Service lors de l’hébergement sur Azure App Service n’est pas nécessaire.

Utilisez les conseils suivants pour configurer l’application :

IIS

Lorsque vous utilisez IIS, activez :

Kubernetes

Créez une définition d’entrée avec les annotations Kubernetes suivantes pour les sessions persistantes :

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 avec Nginx

Suivez les instructions pour une application ASP.NET Core SignalR avec les modifications suivantes :

  • Remplacez le chemin d’accès location de /hubroute (location /hubroute { ... }) par le chemin racine / (location / { ... }).
  • Supprimez la configuration de la mise en mémoire tampon du proxy (proxy_buffering off;), car le paramètre s’applique uniquement aux événements envoyés par le serveur (SSE), qui ne sont pas pertinents pour les interactions client-serveur de l’applicationBlazor.

Pour plus d’informations et pour obtenir de l’aide sur la configuration, consultez les ressources suivantes :

Linux avec Apache

Pour héberger une application Blazor derrière Apache sur Linux, configurez ProxyPass le trafic HTTP et WebSockets.

Dans l’exemple suivant :

  • Kestrel le serveur s’exécute sur l’ordinateur hôte.
  • L’application écoute le trafic sur le 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/

Activez les modules suivants :

a2enmod   proxy
a2enmod   proxy_wstunnel

Vérifiez les erreurs WebSockets dans la console du navigateur. Exemples d’erreurs :

  • Firefox ne peut pas établir de connexion au serveur à l’adresse ws://the-domain-name.tld/_blazor?id=XXX
  • Erreur : échec du démarrage du transport « WebSockets » : Erreur : une erreur s’est produite avec le transport.
  • Erreur : échec du démarrage du transport « Interrogation longue » : TypeError : this.transport is undefined
  • Erreur : impossible de se connecter au serveur avec l’un des transports disponibles. Échec des WebSockets
  • Erreur : impossible d’envoyer des données si la connexion n’est pas dans l’état « Connecté ».

Pour plus d’informations et pour obtenir de l’aide sur la configuration, consultez les ressources suivantes :

Mesurer la latence réseau

JS L’interopérabilité peut être utilisée pour mesurer la latence du réseau, comme le montre l’exemple suivant.

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

@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();
        }
    }
}

Pour une expérience d’interface utilisateur raisonnable, nous recommandons une latence soutenue de l’interface utilisateur de 250 ms ou moins.

Gestion de la mémoire

Sur le serveur, un nouveau circuit est créé pour chaque session utilisateur. Chaque session utilisateur correspond au rendu d’un seul document dans le navigateur. Par exemple, plusieurs onglets créent plusieurs sessions.

Blazor maintient une connexion constante au navigateur, appelé circuit, qui a lancé la session. Les connexions peuvent être perdues à tout moment pour plusieurs raisons, par exemple lorsque l’utilisateur perd la connectivité réseau ou ferme brusquement le navigateur. En cas de perte de connexion, Blazor dispose d’un mécanisme de récupération qui place un nombre limité de circuits dans un pool « déconnecté », ce qui donne aux clients un délai limité pour se reconnecter et rétablir la session (par défaut : 3 minutes).

Après ce délai, Blazor libère le circuit et ignore la session. À partir de ce moment, le circuit est éligible pour le garbage collection (GC) et est revendiqué lorsqu’une collecte pour la génération GC du circuit est déclenchée. Un aspect important à comprendre est que les circuits ont une longue durée de vie, ce qui signifie que la plupart des objets enracinés par le circuit atteignent finalement Gen 2. Par conséquent, il se peut que vous ne voyiez pas ces objets libérés tant qu’une collection Gen 2 n’a pas été effectuée.

Mesurer l’utilisation de la mémoire en général

Conditions préalables :

  • L’application doit être publiée dans la configuration Release. Les mesures de configuration de débogage ne sont pas pertinentes, car le code généré n’est pas représentatif du code utilisé pour un déploiement de production.
  • L’application doit s’exécuter sans débogueur attaché, car cela peut également affecter le comportement de l’application et gâcher les résultats. Dans Visual Studio, démarrez l’application sans débogage en sélectionnant>Démarrer sans débogage dans la barre de menus ou Ctrl+F5 à l’aide du clavier.
  • Considérez les différents types de mémoire pour comprendre la quantité de mémoire réellement utilisée par .NET. En règle générale, les développeurs inspectent l’utilisation de la mémoire des applications dans le Gestionnaire des tâches sur le système d’exploitation Windows, qui offre généralement une limite supérieure de la mémoire réelle utilisée. Pour plus d’informations, consultez les articles suivants :

Utilisation de la mémoire appliquée à Blazor

Nous calculons la mémoire utilisée par blazor comme suit :

(Circuits actifs × mémoire par circuit) + (Circuits déconnectés × mémoire par circuit)

La quantité de mémoire utilisée par un circuit et le nombre maximal de circuits actifs potentiels qu’une application peut gérer dépendent en grande partie de la façon dont l’application est écrite. Le nombre maximal de circuits actifs possibles est approximativement décrit par :

Mémoire / disponible maximale Mémoire = par circuit Nombre maximal de circuits actifs potentiels

Pour qu’une fuite de mémoire se produise dans Blazor, les éléments suivants doivent être vrais :

  • La mémoire doit être allouée par l’infrastructure, pas par l’application. Si vous allouez un tableau de 1 Go dans l’application, l’application doit gérer la suppression du tableau.
  • La mémoire ne doit pas être utilisée activement, ce qui signifie que le circuit n’est pas actif et a été supprimé du cache des circuits déconnectés. Si le nombre maximal de circuits actifs est en cours d’exécution, le manque de mémoire est un problème de mise à l’échelle, et non une fuite de mémoire.
  • Un garbage collection (GC) pour la génération GC du circuit a été exécuté, mais le garbage collector n’a pas pu revendiquer le circuit, car un autre objet de l’infrastructure contient une référence forte au circuit.

Dans d’autres cas, il n’y a pas de fuite de mémoire. Si le circuit est actif (connecté ou déconnecté), il est toujours en cours d’utilisation.

Si une collection pour la génération GC du circuit ne s’exécute pas, la mémoire n’est pas libérée, car le garbage collector n’a pas besoin de libérer la mémoire à ce moment-là.

Si une collection pour une génération GC s’exécute et libère le circuit, vous devez valider la mémoire par rapport aux statistiques GC, et non au processus, car .NET peut décider de maintenir la mémoire virtuelle active.

Si la mémoire n’est pas libérée, vous devez trouver un circuit qui n’est ni actif ni déconnecté et qui est enraciné par un autre objet dans l’infrastructure. Dans tous les autres cas, l’impossibilité de libérer de la mémoire est un problème d’application dans le code du développeur.

Réduisez l’utilisation de la mémoire

Adoptez l’une des stratégies suivantes pour réduire l’utilisation de la mémoire d’une application :

  • Limitez la quantité totale de mémoire utilisée par le processus .NET. Pour plus d’informations, consultez Options de configuration d’exécution pour le garbage collection.
  • Réduisez le nombre de circuits déconnectés.
  • Réduisez le temps pendant lequel un circuit est autorisé à être à l’état déconnecté.
  • Déclenchez un garbage collection manuellement pour effectuer une collecte pendant les périodes d’arrêt.
  • Configurez le garbage collection en mode Station de travail, qui déclenche de manière agressive le garbage collection, au lieu du mode Serveur.

Taille du tas pour certains navigateurs d’appareils mobiles

Lors de la création d’une application Blazor qui s’exécute sur le client et cible les navigateurs d’appareils mobiles, en particulier Safari sur iOS, il peut être nécessaire de diminuer la mémoire maximale pour l’application avec la propriété MSBuild EmccMaximumHeapSize. Pour plus d’informations, consultez Héberger et déployer ASP.NET Core Blazor WebAssembly.

Actions et considérations supplémentaires

  • Capturez un vidage de la mémoire du processus lorsque les besoins en mémoire sont élevés et identifiez les objets qui prennent le plus de mémoire et où ces objets sont enracinés (ce qui contient une référence à eux).
  • Vous pouvez examiner les statistiques sur le comportement de la mémoire dans votre application en utilisant dotnet-counters. Pour plus d’informations, consultez Examiner les compteurs de performances (dotnet-counters).
  • Même quand une GC (Garbage Collection) est déclenchée, .NET conserve la mémoire au lieu de la renvoyer immédiatement au système d’exploitation, car il est probable qu’il va réutiliser la mémoire dans un avenir proche. Ceci évite de commiter et de décommiter constamment la mémoire, ce qui est coûteux en ressources. Vous verrez que cela se reflète si vous utilisez dotnet-counters, car vous allez voir que les GC se produisent et que la quantité de mémoire utilisée descend à 0 (zéro), mais vous ne verrez pas le compteur de la plage de travail diminuer, ce qui est le signe que .NET conserve la mémoire pour la réutiliser. Pour plus d’informations sur les paramètres de fichier projet (.csproj) pour contrôler ce comportement, consultez Options de configuration d’exécution pour le garbage collection.
  • La GC du serveur ne déclenche pas de garbage collections tant qu’elle ne détermine pas qu’il est absolument nécessaire de le faire pour éviter de figer votre application et considère que votre application est la seule chose en cours d’exécution sur la machine : elle peut donc utiliser toute la mémoire du système. Si le système a 50 Go, le garbage collector cherche à utiliser la totalité de la mémoire disponible de 50 Go avant de déclencher une collecte Gen 2.
  • Pour plus d’informations sur la configuration de la rétention de circuit déconnecté, consultez ASP.NET Core BlazorSignalR instructions.

Mesure de la mémoire

  • Publiez l’application dans la configuration Release.
  • Exécutez une version publiée de l’application.
  • N’attachez pas un débogueur à l’application en cours d’exécution.
  • Le déclenchement d’un nettoyage de compactage forcé Gen 2 (GC.Collect(2, GCCollectionMode.Aggressive | GCCollectionMode.Forced, blocking: true, compacting: true)) libère-t-il la mémoire ?
  • Déterminez si votre application alloue des objets sur le tas des grands objets.
  • Testez-vous la croissance de la mémoire une fois que l’application reçoit des requêtes et effectue des traitements ? En général, il existe des caches qui sont remplis quand le code s’exécute pour la première fois, ce qui ajoute une quantité constante de mémoire à l’empreinte de l’application.