ASP.NET MVC-Anwendung löst Session_Start mehrmals für eine einzelne Sitzung aus

8

Wir haben eine MVC.NET-Anwendung, die beim Neustart fatale Fehler meldet. In unserem Session_Start-Ereignishandler fügen wir die Sitzungs-ID einem Wörterbuch hinzu. Im Session_End-Handler entfernen wir es. Betrachten Sie die folgende Reihenfolge von Anforderungen:

GET home.mvc
& lt; Anwendung startet neu & gt;
GET main.css
Erhalten Sie banner.jpg
GET somedata.mvc
...

Aufgrund der Art und Weise, wie die Anwendung aufgebaut wird, tritt diese Art von Sequenz ziemlich häufig auf, wenn Sie eine Neuerstellung durchführen, während die Anwendung in einem Browserfenster geöffnet ist. Das wäre nicht besonders bedenklich, außer dass ich es auch in Produktionsumgebungen sehe. Zum Beispiel wird es (wenn auch selten) beim Bearbeiten von web.config auftreten.

Die Anfragen nach dem Neustart sind alle auf Links auf der Homepage oder auf AJAX-Aufrufe von JavaScript zurückzuführen.

Ich beobachte, dass .NET die ersten fünf Anfragen parallel bearbeitet. Jede solche Anfrage bewirkt, dass das Session_Start-Ereignis ausgelöst wird. Nach kurzer Zeit wird das Session_End-Ereignis dreimal ausgelöst. Um klar zu sein, entspricht jeder Session_Start genau der gleichen Sitzung. Sie haben alle die gleiche Sitzungs-ID und die IsNewSession-Eigenschaft ist für alle Sitzungsstatusobjekte wahr. Außerdem entsprechen die Session_End-Ereignisse nicht der Sitzung, die beendet wird. Die Sitzung wird zusammen mit den im Sitzungszustand gespeicherten Daten beibehalten.

Ich muss entweder verhindern, dass Session_Start mehr als einmal ausgelöst wird oder herausfinden, wann Session_End nicht wirklich bedeutet, dass die Sitzung beendet ist.

    
Peter Ruderman 29.07.2010, 18:46
quelle

3 Antworten

3

Die Antwort auf diese Frage erwies sich als ziemlich geradlinig, obwohl das Verhalten sicherlich verwirrend war.

Normalerweise synchronisiert MVC alle Anfragen an eine Anwendung in der Sitzungszustandssperre der Anwendung (da das http-Modul von MVC als Sitzungsstatus markiert ist). In meinem Szenario startet die Anwendung nach dem Bereitstellen der Hauptseite neu. Wenn also die Hauptseitenanforderungen eingehen, gibt es noch keinen Sitzungszustand für diese Sitzungs-ID und die Anforderungen werden parallel ausgeführt.

Ich sehe 5 parallele Anfragen, weil ich auf XP entwickle und Desktop-Versionen von IIS sind auf 5 gleichzeitige Anfragen begrenzt. Da das Sitzungsstatusobjekt für keine dieser Anforderungen existiert, erstellt jede Anforderung ein neues Sitzungsstatusobjekt und löst Session_Start aus. Vier der Anfragen gehen an MVC-Aktionsmethoden. Da diese den Sitzungsstatus erfordern, versucht .NET, die erstellten Sitzungsstatusobjekte mit dem Sicherungsspeicher zu synchronisieren, sobald die Anforderungen abgeschlossen sind.

Nur die erste Synchronisation kann erfolgreich sein. .NET verwirft einfach die drei zusätzlichen Sitzungsstatusobjekte und feuert Session_End für jeden einzelnen. .NET versucht nicht, das fünfte Sitzungsstatusobjekt mit dem Sicherungsspeicher zu synchronisieren, da es für ein asynchrones HTTP-Modul erstellt wurde, das als schreibgeschützt gekennzeichnet ist.

Also, das Update hat zwei Teile:

(1) In meinem Session_Start-Handler prüfe ich jetzt, ob das Session-State-Objekt schreibgeschützt ist. Wenn es so ist, komme ich sofort zurück, ohne etwas zu tun. .NET wird kein entsprechendes Session_End auslösen und somit wird alles, was ich mache, nicht richtig bereinigt.

(2) Ich halte jetzt eine Referenzzählung in meinem Wörterbuch. Ich inkrementiere den Zähler jedes Mal, wenn ein Session_Start-Handler versucht, eine Sitzungs-ID hinzuzufügen und sie jedes Mal zu dekrementieren, wenn Session_End versucht, einen zu entfernen. Sobald die Anzahl 0 erreicht, entferne ich die Sitzungs-ID aus meinem Wörterbuch.

    
Peter Ruderman 03.08.2010, 15:57
quelle
1

Die Sitzungs-ID kann wiederverwendet werden, wenn der Client Ihnen einen Wert sendet, der abgelaufen ist. Lesen Sie über den & lt; sessionState & gt; Das Attribut regenerateExpiredSessionId des Elements hier und beachten Sie, dass der Standardwert "true"

ist

Vielleicht finden Sie auch das interessant:

    
matt-dot-net 30.07.2010 13:05
quelle
0

Das war mir bei einer alten ASP.NET-App in der Entwicklung passiert - es stellte sich heraus, dass RequireSSL für Cookies auf True gesetzt war ... was natürlich bedeutete, dass das Session-Cookie nicht von der client (localhost, nicht SSL) - so haben nachfolgende Anfragen neue Session (s) erstellt.

    
Nathan 22.12.2015 11:41
quelle

Tags und Links