Why you shouldn't use InProc Session State in ASP.NET
I see a lot of questions regarding Session state in ASP.NET and invariably the majority of problems are related to the volatility of InProc Session state.
InProc Session state in ASP.NET works using an internal memory based list object. Everytime something gets added to the state it gets added to the Session state of this list. Because it is memory based it is fully dependent on the lifetime of the AppDomain that your Web application runs in.
You might think, no big deal – my app is stable and it doesn’t restart. But are you sure of that? Seriously, in IIS 6 and with ASP.NET there are lots of things that can restart your current application without you explicitly knowing about it.
web.config
The most common scenario is settings in Web.Config. Any change made in web.config causes the AppDomain to unload and the Session state with it. If you change an AppSettings value (if you use that) or if you change a flag like DebugMode for a temporary debug to find that online bug that just won’t repro in your test environment – you will blow away the AppDomain and Session state with it.
IIS 6 Application Pool cycling
IIS 6 also includes a number of health checking services. In fact, most ISPs I work with have their IIS 6 Application Pools (which are the host containers in which ISAPI and ASP.NET applications run) set to recycle once a day. Usually these will be at odd hours in the morning but still. If you’re one of the nightowls who likes to buy underwater goggles at
West Wind Web Monitoring and Integrity checks
In my own applications that I run I have a West Wind Web Monitoring service that monitors (using our own West Wind Web Monitor software) the 20 or so apps that are running on my server for failures both in the raw HTTP state as well as to the content they are returning. These are varied applications, some ASP.NET, some Fox Web Connection applications and even a couple of ASP apps. My monitor checks all of these and if it detects a failure for more than two check cycles it tries to restart the Web Server. This doesn’t happen very frequently, but even once a month is one too many if Session state is lost as a result of it!
Code Updates
Finally, when you update code on your ASP.NET Codebehind assembly (ie. your Web Project’s main assembly) on the live site, the AppDomain also gets cycled as well! Yup… AppDomains load assemblies dynamically, but once loaded they can never be unloaded, so when the assembly is replaced on the server Asp.NET detects the change and unloads the entire AppDomain. You can change pages without a recycle (because page classes are dynamically compiled and named), but the main precompiled assembly has fixed names for the classes and since you can't load the same class ontop of the existing one the AppDomain must be unloaded.
You can try this out with this C# CodeBehind code:
public class ApplicationPoolsAndThreads : System.Web.UI.Page
{
protected System.Web.UI.HtmlControls.HtmlForm Form1;
protected string ApplicationId = "";
protected int ThreadId = 0;
protected string DomainId = "";
protected string ThreadInfo = "";
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
this.ApplicationId = ((HowAspNetWorks.Global)
HttpContext.Current.ApplicationInstance).ApplicationId ;
this.ThreadId = AppDomain.GetCurrentThreadId();
this.DomainId = AppDomain.CurrentDomain.FriendlyName;
this.ThreadInfo = "ThreadPool Thread: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread.ToString() +
"<br>Thread Apartment: " + System.Threading.Thread.CurrentThread.ApartmentState.ToString();
bool IsThreadPoolThread = System.Threading.Thread.CurrentThread.IsThreadPoolThread;
// *** Simulate a slow request so we can see multiple
// requests side by side.
System.Threading.Thread.Sleep(3000);
}
}
Add a page that embdeds the field values:
<table border="1" cellpadding="5" style="WIDTH: 480px" align="center">
<tr>
<td style="WIDTH: 121px"><strong>Application Id: </strong>
</td>
<td>
<%= this.ApplicationId %>
</td>
</tr>
<tr>
<td style="WIDTH: 121px"><strong>Thread Id:</strong>
</td>
<td>
<%= this.ThreadId %>
</td>
</tr>
<tr>
<td style="WIDTH: 121px"><strong>Domain Id:</strong>
</td>
<td>
<%= this.DomainId %>
</td>
</tr>
<tr>
<td style="WIDTH: 121px"><strong>Thread Info:</strong>
</td>
<td>
<%= this.ThreadInfo %>
</td>
</tr>
</table>
Run this code (without the debugger attached) a few times and notice the Domain Id stays steady. If you hit from multiple locations you can see multiple threads active etc.
Now go make a change in the project so it forces a recompile, and recompile the project and make sure the assembly is updated. Watch the Domain Id, then refresh and you’ll see that once the DLL is updated the AppDomain has been replaced with a new one and your InProc Session state is gone.
This particular issue will be addressed in ASP.NET 2.0 with the loony compilation scheme that compiles every page into its own uniquely named assembly rather than one huge codebehind assembly. Not sure if that’s a good or bad thing as it opens up a number of other issues.
Can you get away with it? I don’t think so
Anyway, I don’t think that any application that relies on Session state can reasonably ignore all of these points. Yet many people try to run with InProc anyway, either out of ignorance because it is after all the default or because they feel it’s worth the extra performance.
InProc state is definitely considerably faster than either the state server or
However, I think that it’s really no contest. If you’re using Session state I would assume that the state is fairly vital to your application otherwise you’d stick the information into Cookie or other client carried statebag. So assuming your app relies on session state to keep it running right, how much is that extra performance of InProc Session state worth to you? Enough to piss off even a small number of customers who loose their shopping cart or other tracking mechanism?
The alternatives are the ASP.NET Session Server which provides an IP network interface that’s fairly efficient if run on the local machine, and SQL Server State which writes the session state into a SQL Server table which is the slowest of all approaches but also the most reliable and most useful if you need to take statistics on your session interface. You can read more about the mechanisms in this earlier WebLog entry.
Another alternative is to not rely so much on Session state in the first place. In many of my older applications I didn’t use any Session state at all, instead the application has a current user table that tracks the necessary information in a similar manner. It requires a database too, so in the big scheme of things this is as slow as state too, but in my experience much of the information that ends up in the state is information that the application needs to capture anyway either for logging or often times for the flow of the application. So the round trip to the database would happen anyway. Finding a way to standardize how the data gets persisted into this internal state table (using a business object front end perhaps) can give you the same functionality of Sesison without using a Session mechanism at all…
Ultimately it all depends on your application, but for me there’s never been an occasion where InProc session was appropriate as there were always issues that eventually would cause problems for the user in the front end if the Session died.
Other Posts you might also like
The Voices of Reason
# re: Why you shouldn't use InProc Session State in ASP.NET
1.) If you don't use InProc, any objects you try to store in the session state must be serializable. Many custom business objects do not fall into this category. Independent datatables are another example.
2.) The session server service has been known to be flacky from time to time. Random failures or no-responses, etc. Not surve if SP1 fixed this or not.
# re: Why you shouldn't use InProc Session State in ASP.NET
As to the State Service I Blogged that a while back. It seems .NET 1.1 SP1 has fixed the flakiness of the state server.
http://west-wind.com/weblog/posts/1127.aspx
# Re: Why you shouldn't use InProc Session State in ASP.NET
-----------------------------------
Scott Mitchell
mitchell@4guysfromrolla.com
http://ScottOnWriting.NET
# re: Why you shouldn't use InProc Session State in ASP.NET
In the past (prior to a stateservice in Fox or classic ASP) I used to store all that in tables precisely because of the volatility even though it was much less of an issue than with ASP.NET InProc sessions today. Basically there'd be one User record in the database that captured all this stuff and served the same purpose as Session does now. There was a single Cookie that served as an ID and the ID pointed to this user record. One way or another a state mechanism is needed :-} It's just that using a Session for this is much easier and usually more efficient as well.
But I agree anything that has any value whatsoever and is not transient should always go into a database ASAP.
# re: Why you shouldn't use InProc Session State in ASP.NET
If the session variable is null, then you pull the value from your personalization provider, which is usually persisting data to a SQL Table. Also, everytime a session variable is set, you also persist this setting.
Another plus here is that you can control how a custom type is serialized rather than using the build in serialization which at times can have alot of overhead.
Now you can use the most performant InProc sessions while also backing them up with your database. You only need to go to the database if the session variable is empty or being set/changed.
Of course, on a web farm this could be problematic cause the same user could have sessions on two servers so it won't notice changes. Sticky IP's on your load balancer solves this problem fairly well.
I personally think this is better than storing all sessions to a SQL server using the build in methods.
In 1.x you will have to roll your own personalization storage class but in 2.0 you can use the new personalization stuff that comes in ASP.Net.
BOb
# re: Why you shouldn't use InProc Session State in ASP.NET
As I mentioned in many applications storing captured data with a user record that is persistent is a good idea anyway and in that case it's often possible to write any 'operational' data along with the user specific data and wrap all that into a single database access request.
However, the real advantage of a generic Session is that it is so convenient because it is essentially not bound to your application. It's an operational piece.
Using SQL for storing session data is by far the slowest mechanism and for state service I personally wouldn't use that. If I would go the SQL route I'd just as soon build the logic directly into the app...
# re: Why you shouldn't use InProc Session State in ASP.NET
Cause you only go to the db when you need to. Other than that you use InProc session data which is by far the most performant session state mechanism. As opposed to going to/from db for everything which also adds serialization overhead all the time.
For example, lets say you need something from Session...
If (Session("Item") == Null)
{
string value = MySession.GetUserValue("Item",UserID)
}
else
{
string value = Session("Item")
}
return value;
So, in the above the value is retrieved from the InProc session, which is the most performant. If the item isnt' in the session due to a time out perhaps then it is retrieved from the user personal info.
Basically, I great a Get/Set for each session item in a session class that does the above.
This also has the benefit of giving you strongly typed session items and itellisense so when you type:
MySession. you get a list of all the public properties. Granted you have to know what you are putting into a session ahead of time, but I think that is only good design.
# re: Why you shouldn't use InProc Session State in ASP.NET
Where do you get UserID? How is it persisted?
as in
... MySession.GetUserValue("Item",UserID)
Thanks!
# re:my session variable is still alive
why it's happening
# re: Why you shouldn't use InProc Session State in ASP.NET
I've developed an application that uses plink. Its a window based application and now im trying to create the same application but in ASP.NET. The problem is I get an error when i try to put the instance of my class to a session. Please help me gurus...plsssssssssssssssssssssss
heres the part of my program.
Dim objSSH As classSSH
objSSH = New classSSH
Dim sHostName As String
Dim sUserName As String
Dim sPassword As String
sHostName = drpHostName.SelectedValue.Trim
sUserName = txtUserName.Text
sPassword = txtPassword.Text
Dim sStatusLogin As String
sStatusLogin = objSSH.sPuttyLogin(sHostName, "D:\plink.exe", Me.txtPassword.Text, Me.txtUserName.Text)
Session("ssh") = objSSH 'This is the line where error starts
the error is: Unable to serialize the session state. In 'StateServer' and 'SQLServer'
mode, ASP.NET will serialize the session state objects, and as a result
non-serializable objects or MarshalByRef objects are not permitted. The same
restriction applies if similar serialization is done by the custom session
state store in 'Custom' mode.
# re: Why you shouldn't use InProc Session State in ASP.NET