I have now found out that ASP.NET does lock all requests if you use sessions (e.g. here), meaning that if there are 2 concurrent requests then one has to wait until the first one is finished. I have few questions with regards to that as I was not able to find the answers:
If session is not used (turned off in IIS), does it still do this locking?
What is the algorithm that is used to determine if the locking is needed? Is it simply locking ALL requests if session is turned on? Does it try to analyze the code to see if session is used there?
Does it affect non aspx requests like css, javascript, custom handlers and such?
Related
As of my empirically gathered knowledge suggests, .NET WebForms is probably using a queue of requests and when the first request is properly handled, the new first comes to the head of the queue and so on. This behavior recently led to a misunderstanding, where we thought that a feature is very slow, but as a matter of fact, some other features always running before it were the slow ones. But this is only a minor misunderstanding. I can imagine more serious problems, for instance a longer request blocking the other requests and I did not find the time yet to test this on multiple sessions, to see whether this queue is session-level, but I think it should be if I am even right about its existence. Hence my question: why are later requests waiting for earlier requests' parsing in .NET WebForms projects?
Probably Session.
Requests from the same session that use session state don't run concurrently. This means that applications can use session state without needing to worry about race conditions.
There is no blocking for calls from different sessions. Also not blocking for calls from the same client that have session state disabled or readonly.
See the MSDN description of the PagesEnableSessionState Enumeration
Using PerfMon, I can see that my ASP.NET Applications (Total)\Sessions Active is growing indefinitely to the tens of thousands, and I suspect this is causing a recent performance degradation we are observing.
The growth appears to be around a few dozen per minute.
We are using .Net 4.5 and IIS 7.5
How can I get a sample of some details regarding these sessions using administrative tools? What could cause this? What next steps can I take to diagnose this odd behavior?
Place a hook on the Session_OnStart event (more on those events at MSDN: https://msdn.microsoft.com/en-us/library/ms178583.aspx).
From there you should examine and escalate depending on the situation.
First, simply place a breakpoint inside of the event handler and do some normal browsing in your development environment. You can use incognito windows in chrome to achieve anonymity for the sake of creating sessions. If you need to do this in production then you should set up some sort of logging database or leverage your existing logging database to record the session requests (you can serialize them temporarily if you need all of the data).
Look at what the request path is for these sessions, and at some of the contextual data in general. If there are erroneous sessions the handler should be called multiple times per request and that should be immediately obvious. From there you can determine how to handle the extra paths or requests that are coming in.
Since you tagged this asp.net, it is hard to tell what exact version or framework associated with that you are using. However, in general I have noticed that many browsers will accidentally cause an extra session for requesting resources, especially the favicon.
It is highly recommended that you do not create sessions for favicons. In asp.net mvc you can do that by ignoring the route. In asp.net mvc you can also ignore excessive resources. That is done in the global.asax.cs file like this
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("favicon.ico");
See if you have a place in your application that you can do this if the extra sessions are being created as a result of these types of requests.
I am currently debugging some issue about this.
We have a ASP.NET web application and I am debugging on Cassini. When I tried to use IE and send out the request to the server, some time (e.g. in about 20minutes) is needed to process and then send out the response.
In case of multi-tab IE, I tried to send out the requests in different tab at about the same time to the same server but the response is handled only after the one of the response is sent out.
If a new instance of IE is started and the requests are sent out in these different instances, the server can process and send out the response almost simultaneously. After doing some research I found that IIS express may solve my problem, but I cannot. Anyone has experienced similar problem or have I missed out some really important things to check with first?
Thank you for your help.
This is primarily due to ASP.net's session state variable and the fact that only one request at a time may have R/W access to a particular session (as determined by the SessionID cookie).
Any additional requests requiring any form of session access (since Read/Write is the default) will be blocked until the previous request has been completed.
Based on the following links:
http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/
https://msdn.microsoft.com/en-us/library/ms178581.aspx?f=255&MSPPError=-2147217396
I think that you miss the point that the session is lock all request leaving only one per time to run.
Read about that and why:
Replacing ASP.Net's session entirely
Also : Web app blocked while processing another web app on sharing same session
The reason is that Sessions in ASP.NET are not thread safe. Therefore ASP.NET serializes access to requests from the same session.
If you have a multi-tab IE then your tabs share one session. The first request is executed right off and the other ones are queued. If you have different instances then each of them creates a new session and therefore the request are executed in parallel.
I have a web application that uses ASP.NET with "InProc" session handling. Normally, everything works fine, but a few hundred requests each day take significantly longer to run than normal. In the IIS logs, I can see that these pages (which usually require 2-5 seconds to run) are running for 20+ seconds.
I enabled Failed Request Tracing in Verbose mode, and found that the delay is happening in the AspNetSessionData section. In the example shown below, there was a 39-second gap between AspNetSessionDataBegin and AspNetSessionDataEnd.
I'm not sure what to do next. I can't find any reason for this delay, and I can't find any more logging features that could be enabled to tell me what's happening here. Does anyone know why this is happening, or have any suggestions for additional steps I can take to find the problem?
My app usually stores 1-5MB in session for each user, mostly cached data for searches. The server has plenty of available memory, and only runs about 50 users.
It could be caused by lock contention for the session state. Take a look at the last paragraph of MSDN's ASP.NET Session State Overview. See also K. Scott Allen's helpful post on this subject.
If a page is annotated with EnableSessionState="True" (or inherits the web.config default), then all requests for that page will acquire a write lock on the session state. All other requests that use session state -- even if they do not acquire a write lock -- are blocked until that request finishes.
If a page is annotated with EnableSessionState="ReadOnly", then the page will not acquire a write lock and so will not block other requests. (Though it may be blocked by another request holding the write lock.)
To eliminate this lock contention, you may want to implement your own [finer grained] locking around the HttpContext.Cache object or static WeakReferences. The latter is probably more efficient. (See pp. 118-122 of Ultra-Fast ASP.NET by Richard Kiessig.)
There is chance your are running up against the maximum amount of memory that Application Pool is allowed to consume, which causes a restart of the Application Pool (which would account for the delay you are seeing in accessing the session). The amount of memory on the server doesn't impact the amount of memory ASP.NET can use, this is controlled in the machine.config in the memoryLimit property and in IIS 6.0 later in IIS itself using the "Maximum memory used" property. Beyond that, have you considered alternatives to each user using 5 MB of session memory? This will not scale well at all and can cause a lot of issues while under load. Might caching be a more effective solution? Do the searches take so long that you need to do this, could the SQL/Database Setup be optimized to speed up your queries?
I am not able to make more than one request at a time in asp.net while the session is active. Why does this limitation exist? Is there a way to work around it?
This issue can be demonstrated with a WebForms app with just 3 simple aspx pages (although the limitation still applies in asp.net mvc).
Create an asp.net 3.5 web application.
There should be just three pages:
NoWait.aspx, Wait.aspx, and SessionStart.aspx
NoWait.aspx has this single nugget added between the default div tags: <%=DateTime.Now.Ticks %>. The code-behind for this page is the default (empty).
Wait.aspx looks just like NoWait.aspx, but it has one line added to Page_Load in the code-behind: Thread.Sleep(3000); //wait 3 seconds
SessionStart.aspx also looks just like NoWait.aspx, but it has this single line in its code-behind: Session["Whatever"] = "Anything";
Open a browser and go to NoWait.aspx. It properly shows a number in the response, such as: "633937963004391610". Keep refreshing and it keeps changing the number. Great so far! Create a new tab in the same browser and go to Wait.aspx. It sits for 3 seconds, then writes the number to the response. Great so far! No, try this: Go to Wait.aspx and while it's spinning, quickly tab over to NoWait.aspx and refresh. Even while Wait.aspx is sleeping, NoWait.aspx WILL provide a response. Great so far. You can continue to refresh NoWait.aspx while Wait.aspx is spinning, and the server happily sends a response each time. This is the behavior I expect.
Now is where it gets weird.
In a 3rd tab, in the same browser, visit SessionStart.aspx. Next, tab over to Wait.aspx and refresh. While it's spinning, tab over to NoWait.aspx and refresh. NoWait.aspx will NOT send a response until Wait.aspx is done running!
This proves that while a session is active, you can't make concurrent requests with the same user. Requests are all queued up and served synchronously. I do not expect or understand this behavior. I have tested this on Visual Studio 2008's built in web server, and also IIS 7 and IIS 7.5.
So I have a few questions:
1) Am I correct that there is indeed a limitation here, or is my test above invalid because I am doing something wrong?
2) Is there a way to work around this limitation? In my web app, certain things take a long time to execute, and I would like users to be able to do things in other tabs while they wait of a big request to complete. Can I somehow configure the session to allow "dirty reads"? This could prevent it from being locked during the request?
3) Why does this limitation exist? I would like to gain a good understanding of why this limitation is necessary. I think I'd be a better developer if I knew!
Here is a link talking about session state and locking. It does perform and exclusive lock.
The easiest way around this is to make the long running tasks asynchronous. You can make the long running tasks run on a separate thread, or use and asynchronous delegate and return a response to the browser immediately. The client side page can send requests to the server to check and see if it is done (through ajax most likely), and when the server tells the client it's finished, notify the user. That way although the server requests have to be handled one at a time by the server, it doesn't look like that to the user.
This does have it's own set of problems, and you'll have to make sure that account for the HTTP context closing as that will dispose certain functionality in the asp.net session. One example you'll probably have to account for is probably releasing a lock on the session, if that is actually occurring.
This isn't too surprising that this could be a limitation. Each browser would have it's own session, before the advent of ajax, post back requests were synchronous. Making the same session handle concurrent could get really ugly, and I can see how that wouldn't be a priority for the IIS and ASP.NET teams to add in.
For reasons Kevin described, users can't access two pages that might write to their session state at the same time - the framework itself can't exert fine-grained control over the locking of the session store, so it has to lock it for entire requests.
To work around this, pages that only read session data can declare that they do so. ASP.NET won't obtain a session state write lock for them:
// Or false if it doesn't need access to session state at all
EnableSessionState="ReadOnly"