ASP.NET Active Sessions Grow Indefinitely - asp.net

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.

Related

ASP.NET: Session state has created a session id, but cannot save it because the response was already flushed by the application

in an old ASP.NET Web Forms application, developed in Visual Studio 2010,
suddenly does not run anymore, and in the log file appears this message:
Session state has created a session id,
but cannot save it because the response was already flushed by the application.
No new deployment has been made, and no code modifications take place.
Until now I didn't find any solution to this.
What I have to check?
I state that the source code is no longer available, and therefore it would be very difficult to change the code and proceed with a new deployment.
Thanks in advance.
Luis
This would suggest that someone might be hitting the site and jumping directly to some URL (and thus code) that say does some response redirect to another page or some such.
Remember, when code behind runs, and say re-directs to another page, in most cases the running code for the current page is terminated, and that is normal behaviors.
However, the idea that you going to debug code and debug a web site when you don't have the code to debug? Gee, I don't see how that's going to work at all. As noted, if this just started, then it sounds like incoming requests are to pages that don't expect to be hit "first", but some pages that expect to be ONLY called from other pages in the site when some session() and imporant values are setup BEFORE such pages are to be hit.
It also not clear if the site is using sql based sessions, or just in-memory sessions. In memory can (and is) faster, but it also not particually relaible. Now, if you deployed to a new web server or new hosting, then often session errrors can now start to appear, and this is due to the MASSIVE HUGE LARGE DIFFERENT of using cloud based hosting vs that of older hosting soluions that run on a single server.
Clould computing is real utility computing, and thus when you host a web site on such systems, then in-memory session() cannot be used anymore, since multiple servers can and will be used to "dish out" web pages. Since more then one server might be used, then obvisouly in-memory sesson() can't work, since a few web pages might be served out by one server, and then a few more pages might be served out by another server. And using shared memory for a session is limited to ONE server, since multiplel servers don't and can't transfer their memory to other servers.
So, this suggests that you want to be sure that sql server based sessions are being used here - and for any kind of server farm, or any kind of system that does load balances between more then one server, then of course you HAVE to use sql server based sessions, since in memory can't work in that kind of environment.
The error could also be due to excessive server loads - often the session database is "locked" for a short period of time, and can thus often be a bottleneck. So, for say years you might not see a issue, but then as load and use of the web site increases, then this can become noticed where as in the past it was not. I suppose the database used for storing sessions could be checked, or looked at, since as you note, you don't have the ability to test + debug the code. I would REALLY but REALLY work towards solving and fixing this lack of source code for the web site, since without that, you have really no means to manage, maintain, and fix issues for that web site.
But, abrupt terminations of web pages? As noted, this could be a error triggered in code, and thus the page never finished what it was supposed to do. And as noted, perhaps a page that expects some session() values but does not have them as explained above could be the problem. It not clear if your errors also shows what URL this was occurring for.
While nothing seems to have changed - something obviously did.
Ultimate, you need to get that source code, or deal with the people + vendor that supplies the code for that site. If you don't have a vendor, and you don't have source code, you quite much attempting to work on a car that you cant even open the hood to check what's going on under that hood.
so, one suggestion here? Someone is hitting a page that expected some value(s) in session to exist. Often the simple solution is to shove ANY simple or dummy value into session so session REALLY does get created, and then when the page attempts to save the session(), there is one to save!!!
In other words, this error often occurs when session is attempted to be saved, but no sesison exists. For such pages, as noted, a simple tiny small code change of doing this session("zoozoo") = "my useless text" will fix this error. So, it sounds like session is being lost.
As noted, a error on a web page can also trigger a app-pool re-start. If app-pool re-starts, then session is lost (in memory session). Now, with session being lost, then any page that decides to terminate early AND ALSO having used session() will trigger this error.
So, this sounds like app-pool is being re-started and session is being lost. (you can google why app-pool restarts and for the many reasons). However, critical to this issue would be are you using sql based sessions, or in-memory (server) sessions? So, this sounds like some code is triggering a error, and with a error triggered, app-pool re-starts. And with app-pool being restarted, then in-memory session is blown away. And now, without ANY session at all, then attempts to save the session trigger the exact error message you see. (and this is why shoving a dummy value into the session allows and can fix some pages - since you can't save a "nothing" session, and if you do, then you get that exact error message.
but, as noted, you can't make these simple changes to code anyway, right?
But, first on this issue - are you using memory based sessions or not? And that feature can be setup and configured in IIS, and without changes to the code base. So, one quick fix might be to turn on sql server based sessions. It will cost web site performance (10%), but the increased reliability is more then worth the performance hit.
Another area to look at? Are AJAX calls being made to a page, and again without any previous session having been created? So, once again, we down to a change in end user behaviors, and possible those hitting a page first before having logged in, or done other things - and again one would see this error crop up.

Surrender control from Pipeline to an HttpHandler

I have a problem with a website. The server is IIS 7, running ASP.NET on the .NET 4.0 CLR. We are hosting a Sitecore application and I hesitated in adding it as a tag, because I really feel it's more the 'why' of the question and not necessarily related to the underlying tech that's causing the problem.
One of the things Sitecore does is add a boatload of custom pipelines. One of these pipelines is called the LayoutResolverPipeline, which is responsible for determining the path to the layout file the requested page will use. We've come up with a terribly useful and complicated way of hosting global content items across multiple domains. Which domain will serve which items is completely configurable through the Administrator web GUI (aka the Sitecore shell). The end goal is to make it possible for our marketing/consumer experience team to run multivariate testing to find the best user experience.
To that end, we have a 'launch' page that is responsible for considering everything about the current user, everything about the current system and domain settings, and determines which experience to give the customer. For most domains, this comes down to a weighted roll of the dice - for the test results to be statistically sound, they have to be sufficiently random. It is written as an IHttpHandler and it stores its decisions in the HttpContext.Current.Session (which is accomplished by also having it implement the IRequiresSessionState interface). The decision is stored so that if the customer decides to backtrack, we don't roll the dice again and instead give them a consistent experience for the duration of their visit. The decision is carried out by the handler issuing a 302 redirect for the next page in the customer's visit.
The launch handler is defined in the web.config file in the usual way:
<system.webServer>
<handlers>
<add verb="*" path="launch.ashx"
type="CMS.HttpHandlers.LaunchRequestHandler, CMS"
name="LaunchHandler"/>
We occasionally do business with partners who, for whatever reason, don't want the resultant 302 between their page and ours. They will instead link directly to a certain customer experience. Over time, however, we depreciate, move or obsolete whole user experiences, which for certain demanding and lazy partners result in lingering links to unsupported or non-existent items. We also have to handle the case of people mis-typing, mis-remembering, mis-linking, revisiting from their browser history or just trying random urls.
These latter cases have resulted in some nasty exceptions in the LayoutResolverPipeline. I am trying to resolve these exceptions by having it fall back to the LaunchHandler if it can't figure out what to do. I have this implemented as a Redirect, but I would like to simply invoke the LaunchHandler directly; it is going to do a 301 to a different item, anyways, and having multiple redirects on a single request is a costly waste of resources that I would like to avoid.
Enough background. The problem is that LayoutResolverPipeline is bound to the HttpBeginRequest portion of the IIS processing stack, which is well before the Session information is ready. This is a constraint of Sitecore's and it can't be moved without solving a whole load of other problems.
Questions:
Is there a way to pass control to a specific IHttpHandler other than redirecting to the URL it is bound to?
Is there a way to rejoin the code a later point in the event pipeline? I suppose this would mean binding to the Application.PostAcquireRequestState event for a single request only, which sounds ludicrous.
Is there a way to acquire session state information early?
I'm of course open to suggestions for how I might be doing it completely wrong. Oh, and if you know of a more useful tag to throw on it for the Asp.net/IIS pipeline specifically, I wasn't able to find one that wasn't a read herring. Thanks!
I don't think you want to go manually invoking any handlers... that sounds pretty hacky. What about using Server.Transfer() here instead of a 301 Redirect? Then it's transparent on the user's end. Of course the disadvantage there is that it doesn't update the apparent URL, but you can't do that without some sort of redirect going on.

ASP.Net Custom images get a half second delay

I've been working on a C# ASP.Net application that requires images to be customized by users. The images aren't very large, and so they are being stored in a database.
To facilitate loading them onto the pages, a single ASPX page has been created that depending on how it's posted to it loads a different image from the database.
The problem I've been seeing is that if a single page makes multiple requests (usually over 4), then each request starts getting a half second delay in the response.
I've added extra logging and run it through a performance analyzer and have not been able to find the source of the half second delays.
Question is:
What is this delay and how can I get rid of it?
-OR-
What is a better way of doing what I am trying to do that would avoid this entirely?
You're probably hitting a session lock. Disable the session if possible for these concurrent requests. For more information see:
ASP.NET MVC and Ajax, concurrent requests?
Underpinnings of the Session State implementation in ASP.NET
What "performance analyzer" are you referring to? Are you profiling your app? A profiler should tell you exactly where the time is going.

Why is the AspNetSessionData stage of page processing delaying my page by 20+ seconds?

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?

What is the best workaround for the ASP.NET forms authentication timeout when using wildcard mapping?

My team is working on a crappy old website and most of the pages are still ASP classic. However, we've recently migrated to forms authentication using ASP.NET and wildcard mapping. Everything works surprisingly well except for one thing: logged in users are timing out too quickly. After looking in the logs it appears people are timing out exactly after 20 minutes (which is the specified timeout due to inactivity).
So, our hypothesis is that the ASP classic pages are not tripping whatever mechanism in the forms authentication framework that resets the inactivity timer. I've googled around and even read the wildcard mapping post by the Great Gu but still can't find anyone else who is having this problem. So, 1) Have you ever seen this problem? and 2) What's the best workaround? (other than manually placing a hidden frame in every janky ASP page that loads a dumb .NET page in the background)
Update: slidingExpiration is set to true
Also: We can't use perpetual sessions because we need the application to time out after 20 minutes of inactivity. Also, this terrible site was written so that the interface is usually stored in the page. There's no simple piece of interface code I could slip the JavaScript into. We tried to put some js into an include file that was called by about 80% of our pages but it's caused some esoteric problems with file download buffers so we may have to try a different tack. Thanks.
Create a perpetual session.
Essentially you end up emitting some JavaScript and an image tag in your master page or navigation users controls (whatever you're using for consistent navigation). This JavaScript on some interval changes the source of the image tag to an http handler endpoint (some .aspx, .ashx) which returns a 1x1 pix clear gif as a response for the image. The constant request ensures that idle pages will keep the session alive.
As long as a browser window is open to your page your ASP.NET session will never time out.
Often the JavaScript will tack on a random number to the request so that the browser doesn't cache the request.
A decent walkthrough is available here.
I am assuming that you have manually created the cookie, in which case your timeout value in code is probably overriding your timeout value in the configuration.
First, if possible (which it probably isn't) don't create the cookie manually, it will save you from not only this headache but dozens of others.
If you must manually create the cookie, make sure that the timeout you are using is actually reading the timeout value that you have set in the configuration file and that sliding expiration is set to true (which you have said it was).
That said, we still have ocassional strange timeout problems when the cookies are manually created. Where I work we implemented a solution which allowed the cookies to be created automatically and timeouts were no longer a problem; however, it did create other issues and we were forced to switch back.

Resources