4 façons d'améliorer les performances ASP.NET sous des charges de pointe

 

Introduction

ASP.NET devient très populaire pour le développement d'applications Web et bon nombre de ces applications génèrent un trafic élevé et desservent des millions d'utilisateurs. En conséquence, ces applications ont un impact important sur les entreprises et sont donc très importantes.

Fait intéressant, l'architecture d'application ASP.NET est très évolutive au niveau de l'application. Et, le protocole HTTP est également sans état. Ces deux éléments signifient que vous pouvez exécuter votre application ASP.NET dans une batterie de serveurs Web à charge équilibrée où chaque requête HTTP est acheminée vers le serveur Web le plus approprié. Cela vous permet d'ajouter facilement plus de serveurs Web à votre ferme Web à mesure que votre trafic utilisateur augmente. Et cela rend votre niveau d'application ASP.NET très évolutif. Mais qu'est-ce que j'entends par évolutivité ici?

L'évolutivité est essentiellement la capacité à fournir des performances élevées même en cas de pics de charge. Ainsi, si le temps de réponse de votre page d'application ASP.NET est très rapide avec 10 utilisateurs et qu'il reste aussi rapide avec 100,000 XNUMX utilisateurs, votre application ASP.NET est évolutive. Mais, si votre temps de réponse ASP.NET ralentit à mesure que vous augmentez le nombre d'utilisateurs, votre application n'est pas évolutive.

 

Le problème : les goulots d'étranglement de l'évolutivité

Malgré une architecture très évolutive au niveau de l'application, les applications ASP.NET sont aujourd'hui confrontées à d'importants goulots d'étranglement en matière d'évolutivité. Ces goulots d'étranglement se produisent dans quatre domaines différents comme suit :

  1. Base de données d'applications
  2. Stockage d'état de session ASP.NET
  3. ASP.NET View State
  4. Exécution de page ASP.NET pour une sortie statique

Laissez-moi vous expliquer chacun plus en détail ci-dessous.

 

Base de données d'applications

La base de données d'application comme SQL Server ou Oracle devient rapidement un goulot d'étranglement d'évolutivité à mesure que vous augmentez la charge de transaction. Cela se produit car bien que vous puissiez augmenter le niveau base de données en achetant un serveur de base de données plus puissant, vous ne pouvez pas augmenter la taille en ajoutant plus de serveurs au niveau base de données. Par exemple, il est très courant de voir 10 à 20 serveurs au niveau application, mais vous ne pouvez pas faire la même chose au niveau base de données.

 

Stockage d'état de session ASP.NET

De plus, l'état de session ASP.NET doit être stocké quelque part. Et les options prêtes à l'emploi fournies par Microsoft sont InProc, StateServer et SqlServer. Malheureusement, les trois options présentent des problèmes de performances et d'évolutivité majeurs. InProc et StateServer vous obligent à utiliser des sessions persistantes et à envoyer toutes les requêtes HTTP sur le même serveur sur lequel la session a été créée. Si vous configurez StateServer en tant que serveur autonome pour éviter les sessions persistantes, StateServer devient un point de défaillance unique et ses performances deviennent également un problème majeur. Et, SqlServer stocke les sessions ASP.NET dans la base de données SQL Server sous forme de BLOB. De plus, cette approche pose de sérieux problèmes de performances et d'évolutivité.

 

ASP.NET View State

ASP.NET View State est une chaîne masquée codée (souvent de 100 Ko) qui est envoyée au navigateur de l'utilisateur dans le cadre de la réponse HTTP. Le navigateur n'en fait rien et le renvoie au serveur Web en cas de HTTP Post-Back. Cela ralentit la réponse de la page ASP.NET, alourdit la charge sur les cartes réseau du serveur Web et consomme également beaucoup de bande passante supplémentaire. Et, comme vous le savez, la bande passante n'est pas bon marché.

 

Exécution de page ASP.NET pour une sortie statique

Enfin, ASP.NET framework exécute une page ASP.NET contre une demande d'utilisateur, même si la sortie de la page ne change pas depuis la demande précédente. Cela peut convenir dans les environnements à faible transaction. Mais dans un environnement à transactions élevées où vous poussez déjà toutes les ressources à leurs limites, cette exécution supplémentaire peut devenir assez coûteuse et constituer un goulot d'étranglement pour l'évolutivité.

Comme le dit l'adage "la force d'une chaîne est aussi forte que son maillon le plus faible". Ainsi, tant qu'il existe des goulots d'étranglement d'évolutivité n'importe où dans l'environnement d'application ASP.NET, l'ensemble de l'application ralentit et s'arrête même.

Et, ironiquement, cela se produit lors de pics de charge lorsque vous effectuez les niveaux d'activité les plus élevés. Par conséquent, l'impact d'un ralentissement ou d'un temps d'arrêt est beaucoup plus coûteux pour votre entreprise.

ASP.NET face aux goulots d'étranglement d'évolutivité
Figure 1 : ASP.NET face aux goulots d'étranglement d'évolutivité
 

NoSQL Database Pas la réponse

NoSQL database mouvement a commencé en raison des problèmes d'évolutivité dans les bases de données relationnelles. NoSQL database partitionne les données sur plusieurs serveurs et vous permet d'évoluer comme le niveau application.

Mais, NoSQL database vous oblige à abandonner votre base de données relationnelle et à mettre vos données dans un NoSQL database. Et, c'est plus facile à dire qu'à faire pour une multitude de raisons et en fait impossible dans de nombreux cas.

NoSQL databases n'ont pas la même capacité de gestion et de recherche de données que les bases de données relationnelles et souhaitent que vous stockiez les données d'une manière totalement différente de celle des bases de données relationnelles. De plus, l'écosystème entourant les bases de données relationnelles est trop puissant pour être abandonné par la plupart des entreprises.

En conséquence, NoSQL databaseLes s ne sont utiles que lorsque vous traitez des données non structurées. De plus, la plupart des applications ASP.NET traitent des données d'entreprise qui sont principalement structurées et adaptées aux bases de données relationnelles. Par conséquent, ces données ne peuvent pas être déplacées dans un NoSQL database facilement.

Et, même ceux qui finissent par utiliser un NoSQL database le faire pour un petit sous-ensemble de leurs données totales qui peuvent être considérées comme non structurées. Et, ils utilisent NoSQL database ainsi que leur base de données relationnelle existante.

Par conséquent, la plupart du temps, vous devrez vivre avec votre base de données relationnelle et trouver une autre solution à vos problèmes d'évolutivité. Heureusement, il existe une solution très viable et je vais en discuter ci-dessous.

 

La solution : cache distribué en mémoire

La solution à tous les problèmes mentionnés ci-dessus consiste à utiliser le cache distribué en mémoire dans le déploiement de votre application, comme NCache. NCache est un Cache distribué Open Source pour .NET qui est extrêmement rapide et linéairement évolutif. Considérez-le comme un magasin d'objets en mémoire qui est également distribué. Le fait d'être en mémoire le rend extrêmement rapide et sa distribution le rend linéairement évolutif.

La bonne chose à propos d'un cache distribué en mémoire comme NCache est qu'il ne vous demande pas d'arrêter d'utiliser votre base de données relationnelle existante. Vous pouvez utiliser le cache au-dessus de votre base de données relationnelle car le cache supprime tous les goulots d'étranglement de l'évolutivité de la base de données relationnelle.

NCache Fournit une évolutivité linéaire
Figure 2: NCache Fournit une évolutivité linéaire

Alors, à quoi ressemble un cache distribué en mémoire NCache plus évolutif qu'une base de données relationnelle ? Hé bien, NCache forme un cluster de serveurs de cache et regroupe le CPU, la mémoire et les autres ressources de tous ces serveurs.

Et, NCache vous permet d'ajouter des serveurs de cache au moment de l'exécution sans arrêter le cache ou l'application. Et cela vous permet de faire évoluer votre application de manière linéaire et de gérer des charges de transaction extrêmes. C'est quelque chose que vous ne pouvez pas faire avec votre base de données relationnelle.

Cache distribué en mémoire comme NCache évolue de manière linéaire en vous permettant d'ajouter des serveurs de cache au cluster de cache (le niveau de mise en cache) au moment de l'exécution. Mais, à quel type de performances devez-vous vous attendre d'une solution telle que NCache.

Voici NCache chiffres de performances. Vous pouvez voir plein NCache référence de performance ici.

Chiffres de performance pour NCache
Figure 3 : Chiffres de performance pour NCache

Comme vous pouvez le voir, un cache distribué en mémoire comme NCache fournit des performances inférieures à la milliseconde pour les lectures et les écritures et vous permet d'adapter votre capacité de transaction de manière linéaire en ajoutant simplement plus de serveurs de cache.

Voyons maintenant à quoi ressemble un cache distribué en mémoire NCache résout divers goulots d'étranglement d'évolutivité mentionnés ci-dessus.

 

Mise en cache des données d'application

La mise en cache des données d'application vous permet de supprimer les goulots d'étranglement de votre base de données. Cache distribué en mémoire comme NCache vous permet de mettre en cache les données d'application et de réduire ces déplacements coûteux de la base de données. Vous pouvez vous attendre à détourner 70 à 90 % du trafic de la base de données vers le cache distribué en mémoire. Cela réduit la pression sur votre base de données et lui permet de fonctionner plus rapidement et de gérer des charges de transactions plus importantes sans ralentir.

Customer Load(string customerId)
{
 // Key format: Customer:PK:1000
 string key = "Customers:CustomerID:" + customerId;
 Customer cust = (Customer) _cache[key];
 if (cust == null)
 { // Item not in cache so load from db
LoadCustomerFromDb(cust);
// Add item to cache for future reference
_cache.Insert(key, cust);
 }
 return cust;
}

Figure 4 : Utilisation du cache distribué en mémoire pour la mise en cache des données d'application

La mise en cache des données d'application signifie que vous mettez en cache toutes les données d'application que vous obtenez de votre base de données relationnelle. Cela se présente généralement sous la forme d'objets de domaine (également appelés entités). Voici un exemple d'utilisation d'un cache distribué comme NCache pour la mise en cache des données d'application.

 

Mise en cache de l'état de la session ASP.NET

Cache distribué en mémoire comme NCache est également un endroit idéal pour stocker votre état de session ASP.NET. Il est beaucoup plus rapide et plus évolutif que les trois options mentionnées ci-dessus (InProc, StateServer et SqlServer). NCache est plus rapide car il est en mémoire et fournit une interface clé-valeur avec la valeur étant un "objet" qui est un état de session ASP.NET. Et, il est évolutif car il s'agit d'un cache distribué.

Et, NCache réplique également intelligemment les sessions grâce à ses riches topologies de mise en cache, de sorte que même si un serveur de cache tombe en panne, il n'y a aucune perte de données de session. Cette réplication est nécessaire car NCache fournit un magasin en mémoire et la mémoire viole le stockage.

NCache accélère également votre sérialisation de l'objet d'état de session ASP.NET qui est requis avant qu'il puisse être stocké hors processus. NCache le fait en utilisant sa fonctionnalité de sérialisation compacte dynamique qui est 10 fois plus rapide que la sérialisation .NET standard. Vous pouvez utiliser cette fonctionnalité sans apporter de modifications au code.

Vous pouvez brancher NCache Fournisseur d'état de session (SSP) à votre application ASP.NET en apportant quelques modifications à votre fichier web.config comme indiqué ci-dessous.

<system.web>
 ...
 <assemblies>
<add assembly="Alachisoft.NCache.SessionStoreProvider, Version=4.3.0.0,
 Culture=neutral, PublicKeyToken=CFF5926ED6A53769" />
 </assemblies>
 <sessionState cookieless="false" regenerateExpiredSessionId="true"
 mode="Custom" customProvider="NCacheSessionProvider"
timeout="20">
<providers>
 <add name="NCacheSessionProvider"
 type="Alachisoft.NCache.Web.SessionState.NSessionStoreProvider"
 useInProc="false" cacheName="myDistributedCache"
 enableLogs="false“ writeExceptionsToEventLog="false” />
</providers>
 </sessionState>
 ...
</system.web>

Figure 5 : Plug-in NCache en tant que fournisseur d'état de session ASP.NET (SSP) dans Web.Config

 

ASP.NET View State Cache haute performance

J'ai déjà décrit comment ASP.NET View State est une chaîne codée envoyée par le serveur Web au navigateur de l'utilisateur qui la renvoie ensuite au serveur Web en cas de retour HTTP Post. Mais, avec l'aide d'un cache distribué InMemory comme NCache, vous pouvez mettre ceci en cache ASP.NET View State sur le serveur et n'envoyez qu'un petit identifiant unique à sa place.

NCache a mis en place une ASP.NET View State module de mise en cache via un adaptateur de page ASP.NET personnalisé et ASP.NET PageStatePersister. Par ici, NCache intercepte à la fois la requête et la réponse HTTP. Au moment de la réponse, NCache supprime la partie "valeur" de la chaîne encodée et la met en cache et place à la place un identifiant unique (une clé de cache) dans cette "valeur".

Ensuite, lorsque la prochaine requête HTTP arrive, il l'intercepte à nouveau et remplace l'identifiant unique par la chaîne encodée réelle qu'il a mise dans le cache plus tôt. De cette façon, la page ASP.NET ne remarque rien de différent et utilise la chaîne encodée contenant l'état d'affichage comme elle le faisait auparavant.

L'exemple ci-dessous montre un ASP.NET View State chaîne encodée sans mise en cache et également ce qui se passe lorsque la mise en cache est incorporée.

//ASP.NET View State without Caching
<input id="__VIEWSTATE"
 	type="hidden"
 	name="__VIEWSTATE"
 	value="/wEPDwUJNzg0MDMxMDA1D2QWAmYPZBYCZg9kFgQCAQ9kFgICBQ9kFgJmD2QWAgIBD
		xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
		lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
		xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
		lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
		... ==" />
			
//ASP.NET View State with Caching
<input id="__VIEWSTATE"
	type="hidden"
	name="__VIEWSTATE"
	value="vs:cf8c8d3927ad4c1a84da7f891bb89185" />

Figure 6: ASP.NET View State Chaîne codée avec ou sans mise en cache

 

Cache de sortie ASP.NET pour la sortie de page statique

ASP.NET fournit une structure de cache de sortie ASP.NET pour résoudre le problème d'exécution excessive de pages même lorsque la sortie de la page ne change pas. Ce cadre vous permet de mettre en cache la sortie de la page entière ou de certaines parties de la page afin que la prochaine fois que cette page soit appelée, elle ne sera pas exécutée et à la place sa sortie mise en cache sera affichée. Afficher une sortie déjà mise en cache est beaucoup plus rapide que d'exécuter à nouveau la page entière.

<caching>
   <outputCache defaultProvider ="NOutputCacheProvider">
     <providers>
       <add name="NOutputCacheProvider"
         type="Alachisoft.NCache.OutputCacheProvider.NOutputCacheProvider,
               Alachisoft.NCache.OutputCacheProvider, Version=x.x.x.x,
               Culture=neutral, PublicKeyToken=1448e8d1123e9096"
				  
               cacheName="myDistributedCache" exceptionsEnabled="false"
               writeExceptionsToEventLog="false" enableLogs="true” />"
     </providers>
   </outputCache>
</caching>

Figure 7 : Configuration du fournisseur de cache de sortie ASP.NET pour NCache dans Web.Config

NCache a implémenté un fournisseur de cache de sortie ASP.NET pour .NET 4.0 ou versions ultérieures. Cela vous permet de brancher NCache de manière transparente et sans aucun effort de programmation. En cas de NCache, ce fournisseur est destiné à un cache distribué en mémoire qui s'étend sur plusieurs serveurs. Ainsi, si votre application ASP.NET s'exécute dans une batterie de serveurs Web à charge équilibrée, la sortie de page mise en cache à partir du serveur 1 est immédiatement disponible pour tous les autres serveurs de la batterie de serveurs Web. Voici comment vous pouvez vous connecter NCache en tant que fournisseur de cache de sortie ASP.NET.

 

Architecture de cache distribué

Les applications ASP.NET à fort trafic ne peuvent pas se permettre de tomber en panne, en particulier pendant les heures de pointe. Pour ces types d'applications, il existe trois objectifs architecturaux importants qu'un bon cache distribué en mémoire comme NCache fournit. Ils sont:

  1. La haute disponibilité
  2. Évolutivité linéaire
  3. Réplication et fiabilité des données

Laissez-moi vous expliquer chaque domaine ci-dessous.

 

Haute Disponibilité

L'un des objectifs architecturaux les plus importants de NCache est d'obtenir une haute disponibilité et une élasticité du cache. Et, il le fait grâce aux capacités architecturales suivantes :

  1. Cluster de cache peer-to-peer à réparation automatique : NCache construit un cluster de serveurs de cache sur TCP/IP. Ce cluster a un peer-to-peer architecture qui signifie qu'il n'y a pas de nœuds maître/esclave et pas de clustering majoritaire. Au lieu de cela, chaque nœud est un pair égal. Cela permet NCache pour gérer les situations où n'importe quel nœud pourrait tomber en panne et le cluster s'ajuste automatiquement et continue de fonctionner, et il n'y a pas d'interruption pour votre application.
  2. Paramétrage dynamique : Cela signifie que vous n'avez pas besoin de coder en dur les éléments dans les fichiers de configuration. Ceci est dû au fait NCache propage de nombreuses informations de configuration vers les clients en cache (c'est-à-dire vos applications) lors de l'exécution. Ainsi, lorsque vous ajoutez un serveur de cache lors de l'exécution, l'appartenance au cluster est automatiquement mise à jour et le cluster informe tous les clients de cache de ce changement. Il existe une foule d'autres modifications de configuration qui sont gérées de la même manière.
  3. Prise en charge du basculement de connexion : Il s'agit d'une fonctionnalité dans laquelle lorsqu'un serveur de cache tombe en panne, le cluster de cache et les clients de cache peuvent continuer à fonctionner sans aucune interruption. Dans le cas d'un cluster de cache, j'ai déjà discuté de sa qualité d'auto-guérison qui résout cette situation. Dans le cas de clients de cache, cela signifie que le client de cache continue de fonctionner en interagissant avec d'autres serveurs de cache du cluster.
 

Réplication des données avec évolutivité linéaire

Depuis le cache distribué en mémoire comme NCache utilise la mémoire comme magasin, il doit assurer la réplication des données afin d'assurer la fiabilité. Mais, en même temps, il ne peut pas faire de compromis sur l'évolutivité linéaire car c'est la raison la plus importante d'utiliser un cache distribué comme NCache.

Voici quelques-unes NCache Topologies de mise en cache qui aident à atteindre ces deux objectifs.

  1. Cache partitionné : NCache partitionne le cache en fonction du nombre de serveurs de cache et attribue une partition à chaque serveur de cache. Il ajuste également le nombre de partitions lorsque vous ajoutez ou supprimez des serveurs de cache lors de l'exécution. Le partitionnement est le principal moyen d'assurer une évolutivité linéaire, car à mesure que vous ajoutez des serveurs, cette topologie de mise en cache augmente la taille de stockage globale ainsi que la puissance de traitement du processeur.
  2. Cache de réplica partitionné : Outre le partitionnement, NCache fournit également des répliques pour chaque partition. Ces répliques résident sur des serveurs de cache différents de la partition elle-même pour garantir que si un serveur de cache tombe en panne avec sa partition, la réplique devient immédiatement disponible. De cette façon, la fiabilité des données est assurée. En répliquant chaque partition une seule fois sur un autre serveur de cache, NCache assure la fiabilité des données sans compromettre l'évolutivité linéaire.
  3. Cache client (près du cache) : Une autre capacité très importante de NCache est le cache client. Il s'agit d'un cache local qui se trouve sur la machine cliente du cache (à savoir votre serveur Web ou d'application) et peut même être InProc (ce qui signifie qu'il réside dans votre processus d'application). Il s'agit essentiellement d'un cache au-dessus d'un cache et offre des gains de performances extrêmes ainsi qu'une évolutivité croissante de NCache lui-même car le trafic, même vers le niveau de mise en cache, diminue.
Topologie de mise en cache de partition-réplica de NCache
Figure 8 : Topologie de mise en cache de partition-réplica de NCache

Comme vous pouvez le voir, Partitioned-Replica Cache place une partition et une réplique sur chaque serveur de cache. De plus, cela garantit que la réplique se trouve toujours sur un serveur de cache différent à des fins de fiabilité.

 

Conclusion

J'ai essayé de mettre en évidence les goulots d'étranglement les plus courants en matière de performances et d'évolutivité auxquels les applications ASP.NET sont confrontées aujourd'hui et de vous montrer comment les surmonter en utilisant un cache distribué en mémoire comme NCache. NCache est un cache distribué Open Source pour les applications .NET et Java. Ainsi, vous pouvez l'utiliser sans aucune restriction. Vous pouvez en savoir plus sur NCache au lien suivant

Que faire ensuite?

© Copyright Alachisoft 2002 - . Tous droits réservés. NCache est une marque déposée de Diyatech Corp.