Je viens de découvrir pourquoi tous les ASP.Net les sites web sont lents, et je suis en train de travailler sur ce qu'il faut faire
Je viens de découvrir que chaque demande dans un ASP.Net l'application web a une Séance de verrouillage au début d'une demande, et puis il libère à la fin de la demande!
Dans le cas où les implications de ce sont perdu sur vous, comme elle l'a été pour moi au premier abord, cela signifie essentiellement la suivante:
-
À tout moment un ASP.Net page est longue à charger (peut-être en raison d'une base de données est lente appel ou quoi que ce soit), et que l'utilisateur décide d'accéder à une page différente parce qu'ils sont fatigués d'attendre, ILS ne PEUVENT PAS! L'ASP.Net session de verrouillage des forces de la nouvelle page de demande d'attendre jusqu'à ce que la demande initiale a fini sa lente et douloureuse de la charge. Arrrgh.
-
À tout moment un UpdatePanel se charge lentement, et que l'utilisateur décide d'accéder à une autre page avant de l'UpdatePanel a terminé la mise à jour... ILS ne PEUVENT PAS! L'ASP.net session de verrouillage des forces de la nouvelle page de demande d'attendre jusqu'à ce que la demande initiale a fini sa lente et douloureuse de la charge. Double Arrrgh!
Alors, quelles sont les options? Jusqu'à présent, j'en suis venu avec:
- Mettre en œuvre une Coutume SessionStateDataStore, qui ASP.Net prend en charge. Je n'ai pas trouvé trop de là à copier, et il semble genre de risque élevé et facile à gâcher.
- Garder une trace de toutes les demandes en cours, et si la demande vient de la même utilisateur, d'annuler la demande d'origine. Ca semble assez extrême, mais il pourrait fonctionner (je pense).
- N'utilisez pas de Session! Quand j'ai besoin d'une sorte d'état pour l'utilisateur, j'ai juste l'utilisation de Cache au lieu de cela, et les principaux éléments sur le nom d'utilisateur authentifié, ou quelque chose de ce genre. Semble de nouveau extrêmes.
J'ai vraiment ne peux pas croire que le ASP.Net Microsoft team aurait laissé un énorme goulot d'étranglement des performances dans le cadre de la version 4.0! Ai-je raté quelque chose d'évident? Comment serait-il difficile d'utiliser un thread-safe collection pour la Session?
- Vous vous rendez compte que ce site est construit au sommet .NET. Cela dit, je pense qu'il évolue très bien.
- OK, donc j'étais un peu facétieux avec mon titre. Encore, à mon humble avis les performances choquantes que la sortie de la boîte de mise en œuvre de session impose est saisissante. Aussi, je parie que le Dépassement de Pile gars ont eu à faire un bon peu de hautement personnalisé dev pour obtenir les performances et l'évolutivité ils ont atteint et bravo à eux. Enfin, Stack Overflow est une APPLICATION MVC, pas WebForms, qui je parie aide (même si il est vrai que cela encore utilisés de la même session de l'infrastructure).
- Article sur cette MVC, à partir d'un point de vue
- Si Joel Mueller vous a donné l'information afin de résoudre votre problème, pourquoi n'avez-vous pas de marquer sa réponse que la réponse correcte? Juste une pensée.
- Joël Muller a fourni beaucoup d'informations, et je voulais le remercier pour cela. Cependant, j'ai finalement allé avec une autre route que celle qui est proposée dans son poste. Par conséquent, le marquage d'un poste différent, comme la réponse.
- Avez-vous vérifié si votre site démarre plus vite sans https? Si oui, essayez de le fixer dans ce MCS post: blogs.msdn.microsoft.com/mcsuksoldev/2011/01/19/...
- Comment avez-vous compris que votre session est verrouillée? Est-il possible de comprendre par programme de cette session est verrouillée?
Vous devez vous connecter pour publier un commentaire.
Si votre page ne modifie pas les variables de session, vous pouvez vous désinscrire de la plupart de ce verrou.
Si votre page n'a pas pour lire toutes les variables de session, vous pouvez vous désinscrire de ce verrou entièrement, pour cette page.
Si aucun de vos pages utiliser des variables de session, il suffit de tourner hors d'état de session dans le site web.config.
Je suis curieux, qu'en pensez-vous "un des Threads de la collection" pour devenir "thread-safe", si ce n'est pas utiliser des verrous?
Edit: je devrais sans doute expliquer par ce que j'entends par "exclusion de la plupart de ce verrou". N'importe quel nombre de lecture seule session ou pas de session de pages peuvent être traitées pour une session donnée en même temps sans bloquer les uns les autres. Cependant, une lecture-écriture-session de page ne peut pas commencer le traitement jusqu'à ce que toutes les demandes en lecture seule, et alors qu'il est en cours d'exécution, il doit disposer d'un accès exclusif à la session de cet utilisateur dans le but de maintenir la cohérence. Verrouillage sur les valeurs individuelles ne marcherait pas, parce que si on change de page d'un ensemble de valeurs liées en tant que groupe? Comment vous assurez-vous que d'autres pages en cours d'exécution dans le même temps, serait d'obtenir une vue cohérente de l'utilisateur, les variables de session?
Je suggère que vous essayez de réduire la modification des variables de session une fois qu'ils ont été définis, si possible. Cela vous permettra de faire la majorité de vos pages en lecture seule session de pages, ce qui augmente les chances que plusieurs demandes simultanées d'un même utilisateur ne serait pas bloquer les uns les autres.
<pages enableSessionState="ReadOnly" />
dans le web.configuration et l'utilisation @Page pour permettre à écrire sur des pages spécifiques seulement.OK, donc en gros Accessoires de Joël Muller pour l'ensemble de son entrée. Mon ultime solution a été d'utiliser la Coutume SessionStateModule détaillées à la fin de cet article MSDN:
http://msdn.microsoft.com/en-us/library/system.web.sessionstate.sessionstateutility.aspx
C'était:
Cela a fait une ÉNORME différence dans le sentiment de "snapiness" de notre application. Je ne peux toujours pas croire que la coutume de la mise en œuvre de ASP.Net Session verrouille la session pour l'ensemble de la demande. Cela ajoute une telle quantité énorme de la lenteur de sites web. À en juger par la quantité de la recherche en ligne j'ai eu à faire (et des conversations avec plusieurs vraiment vécu ASP.Net les développeurs), beaucoup de personnes ont rencontré ce problème, mais très peu de gens ont jamais eu à le fond de la cause. Peut-être que je vais écrire une lettre à Scott Gu...
J'espère que cette aide quelques personnes!
ReaderWriterLock
a été dépréciée en faveur deReaderWriterLockSlim
- vous devez utiliser à la place. Deuxièmement,lock (typeof(...))
a également été supprimé - vous devez le verrouiller en revanche sur un private static instance de l'objet. Troisièmement, le membre de phrase "Cette application n'empêche pas simultanée Web demandes de l'aide du même identifiant de session" est un avertissement, pas une fonction.SessionStateItemCollection
dans l'exemple de code avec un thread-safe classe (peut-être fondée surConcurrentDictionary
) si vous voulez éviter difficile à reproduire les erreurs de sous-charge.SessionStateItemCollection
(qui est une propriété de la SessionItem classe dans l'exemple) avec un "thread-safe" de la mise en œuvre deISessionStateItemCollection
vous avez encore des problèmes potentiels. Une autre chose à considérer: avez-vous stocker toutes les instances de classe dans des variables de session? Sont ces classes thread-safe? Car vous avez permis à la possibilité de plusieurs threads accèdent à des instances de ces classes en même temps.ISessionStateItemCollection
nécessite laKeys
bien être de typeSystem.Collections.Specialized.NameObjectCollectionBase.KeysCollection
- qui n'a pas les constructeurs publics. Gee, merci les gars. C'est très pratique.J'ai commencé à utiliser le AngiesList.Redis.RedisSessionStateModule, qui part en utilisant le (très rapide) Redis serveur pour le stockage (je suis en utilisant le windows port -- mais il y a aussi un MSOpenTech port), il ne fait absolument pas le verrouillage de la session.
À mon avis, si votre application est structurée d'une manière raisonnable, ce n'est pas un problème. Si vous avez réellement besoin verrouillé et la cohérence des données dans le cadre de la session, vous devez mettre en œuvre un verrou/contrôle d'accès concurrentiel sur votre propre.
MS décider que chaque ASP.NET la session doit être verrouillé par défaut uniquement pour gérer la mauvaise conception de l'application est une mauvaise décision, à mon avis. Surtout parce qu'il semble comme la plupart des développeurs ne sont pas/ne réalisent même pas les sessions ont été verrouillés et, a fortiori, que les applications apparemment besoin d'être structuré de sorte que vous pouvez le faire en lecture seule session de l'etat autant que possible (opt-out, si possible).
J'ai préparé une bibliothèque basée sur les liens publiés dans ce fil. Il utilise les exemples à partir de MSDN et CodeProject. Grâce à James.
J'ai également procédé à des modifications conseillé par Joel Mueller.
Code est ici:
https://github.com/dermeister0/LockFreeSessionState
HashTable module:
ScaleOut StateServer module:
Module personnalisé:
Si vous souhaitez mettre en œuvre le soutien de Memcached ou Redis, installer ce package. Puis héritent de la LockFreeSessionStateModule de la classe et de mettre en œuvre des méthodes abstraites.
Certains sans verrouillage de session prestataires de l'aide Redis:
À moins que votre application a spécialement besoin, je pense que vous avez 2 méthodes:
Session n'est pas seulement "thread-safe", mais aussi " l'état fort, d'une manière que vous savez que jusqu'à ce que la requête en cours est terminée, chaque variable de session ne changeront pas à partir d'une autre requête active. Pour que cela arrive, vous devez assurer cette session SERA VERROUILLÉ jusqu'à ce que la requête en cours est terminée.
Vous pouvez créer une session, comme le comportement de nombreuses façons, mais si elle ne permet pas de verrouiller la session en cours, il ne sera pas 'session'.
Pour les problèmes que vous avez mentionnés, je pense que vous devriez vérifier HttpContext.Actuel.Réponse.IsClientConnected. Ceci peut être utile pour éviter des exécutions et l'attend sur le client, bien qu'il ne peut pas résoudre ce problème, car cela peut être utilisé que par une mise en commun, et non pas async.
Si vous utilisez la mise à jour
Microsoft.Web.RedisSessionStateProvider
(à partir de3.0.2
), vous pouvez l'ajouter à votreweb.config
pour permettre à des séances simultanées.Source
Pour ASPNET MVC, nous avons fait le suivant:
SessionStateBehavior.ReadOnly
sur l'ensemble du contrôleur de l'action en substituantDefaultControllerFactory
SessionStateBehaviour.Required
Créer des ControllerFactory et remplacer
GetControllerSessionBehaviour
.AcquireSessionLockAttribute
Crochet jusqu'à la création de la fabrique de contrôleurs dans
global.asax.cs
Maintenant, nous pouvons avoir les deux
read-only
etread-write
l'état de session dans un seulController
.Marquage d'un contrôleur d'état de session comme readonly ou désactivé permettra de résoudre le problème.
Vous pouvez décorer d'un contrôleur avec l'attribut suivant à marquer en lecture seule:
la Système.Web.SessionState.SessionStateBehavior enum a les valeurs suivantes:
Juste pour aider quelqu'un à ce problème (demandes verrouillage lors de l'exécution d'un autre de la même session)...
Aujourd'hui, j'ai commencé à résoudre ce problème et, après quelques heures de recherche, je l'ai résolu en supprimant le
Session_Start
méthode (même vides) de la Mondiale.asax fichier.Cela fonctionne dans tous les projets que j'ai testé.