We're currently building an application in which we rely heavily in storing data in sessions for each individual user. We cannot use Cache since these data are specific to users, and re-querying data when we need it is an expensive process: so the solution was to query once from the DB, store into session, and then keep using it until the session ends. A concern I have is how IIS handles these sessions when too much session data is stored in memory.
when does it know when to clear session data?
how does it determine which session variable to clear out first if memory runs low?
Is there a way to set priories to individual session objects: clear less prioritized data first.
What you're doing is using InProc sessions whereby the sessions are stored in the memory of the current worker process.
when does it know when to clear session data?
InProc sessions are cleared as you might expect when zero requests have been made for the session for the length of the configured session timeout.
<sessionState mode="InProc" timeout="30"/>
However this is not an exact duration. The session will be cleared after the timeout but only when a cleanup is triggered by the internal mechanics of the session handler. Each session doesn't have it's own timer polling for a session timeout. It will get done, when it's optimal for it to be done.
You should also note that since worker processes are regularly recycled any and all sessions stored in that process will be deleted. InProc sessions will also not work in web farms since each request could be handled by a different machine.
how does it determine which session variable to clear out first if memory runs low?
It doesn't. It will simply shift to using virtual memory like any other windows process and as such you would now be backing your sessions with disk based virtual memory instead of chip based memory. Eventually the whole process would get recycled and everything would be wiped as per 1.
Is there a way to set priories to individual session objects: clear less prioritized data first
Not out of the box with InProc. Ultimately the session is just storing objects so you could run your own cleanup according to whatever makes sense for your app by simply tagging your InProc objects with some kind of value. But you'll quickly end up simply replicating the features already available and probably not doing it as well as MS.
Check out System.Web.SessionState namespace for some options but bear in mind that by using InProc you are always going to be held to ransom by worker process recycling which can be triggered by many different things: antivirus software resetting the timestamps on web.config files for example.
For a viable and popular alternative to InProc sessions, check out Redis.
Related
In this question there's a comment with a few upvotes that states:
InProc session state is known to be highly unstable under load. If it's abused (happens all the time), then Session["foo"] = null will perform better than Session.Remove["foo"]. The garbage collector should clean up the mess of excessive session variables
This concerns me as all of my web apps make heavy use of session state (account info, baskets, payment details, user preferences etc.).
I can't seem to find any evidence to back up this claim, can someone debunk this or explain why this is correct. Am I wrong to be storing such info in session? I'm not looking for a pros and cons of InProc vs SQL, I'm aware of the differences.
All of my apps run on a single or dedicated webserver so I've never seen any benefit or point in moving to SQL for session state.
InProc Session State is stable and you don't have to worry about it. I don't know why he called it unstable but I guess he might have thought one of the following reasons while commenting:
If your application gets too much load; when you scale it, you have to use sticky session (for InProc SessionState) to redirect the requests to the same server for a client otherwise session object would not persist.
If an application has memory leaks or inconsistencies, heavy load will most probably trigger the application to reset and this will cause all the session data be lost so that current users' active pages might get errors since their session datas are lost.
Session object is locked out for the entire request (for that user only) to prevent multiple pages to write into the session so that if concurrent requests are made for example, they have to wait for each other to write data into Session. But it happens both in SQL and InProc SessionState.
I saw banking applications which work with InProc SessionState and there is nothing unstable about it.
In ASP.NET, sessions enable us to store and retrieve values for a user as the user navigates ASP.NET pages in a web application. However, using too much sessions is discouraged. Why? What are the disadvantages of using too many sessions?
Thanks for those who will answer.
Memory and/or performance
If you store session state in-process (the default), all of your session data are stored in the app pool's local memory. If you have thousands of users you can see why this may be a problem. The problem gets worse when developers don't remove session variables after they're no longer needed (this is very common due to the fact that it's very hard to control the order in which web pages are accessed) and/or when users do not explicitly logout (e.g. by closing the browser window), which leaves all this memory still allocated but no longer used.
If you store session state out of process (e.g. in SQL Server or a separate state server), all of the session variables end up crossing the wire. As you add more variables, more and more data have to get pulled over. This can end up degrading performance.
Concurrency
If a web application uses session state, the data in which the session state is accessed has to be protected from race conditions and other multithreading concerns. As a result, ASP.NET automatically serializes any requests that use session. If you send two requests at the same time, ASP won't even start on the second request until the first one is finished. This can cause unexpected and poor performance on applications that use a lot of AJAX or other logic that is supposed to be asynchronous.
Infrastructure
If you're using local memory for session state, and your web app is load balanced, the load balancer must enforce session stickiness, either with IP address or a cookie. This constrains the load balancer in the way it can handle requests-- all requests for a certain session always hit the same server-- which reduces overall performance and eliminates redundancy.
Loss of data
If the app pool recycles, all sessions running on that app pool lose session state, often requiring users to log out and start over.
Poor code design
Session variables are essentially global variables. Overuse of global variables tends to lead to sloppy code structure. Variables should always be scoped as tightly as possible.
Basically, it consumes server memory. As generally sessions are stored in process, this solution doesn't scale well, as can't be shared between two or more state servers.
I'm considering moving our web app session storage from In Proc to State Server. Can anybody give any figures as to the performance difference?
I can't give you performance metrics but it won't be as fast as InProc session state due to certain overheads:
Cross Process calls add overheads
Objects have to be serialised and deserialised
Some objects can't be serialised (XmlDocument for example or those that inherit from MarshalByRef)
That said your session state data will survive application pool and IIS resets which may be the reason you're considering changing.
In my .NET web app, I keep basic user info in a user session object. I also usually keep a director class in the session; which is basically just has info about whatever thing it being worked on on that screen (like a customer id).
I am trying to keep from adding a ton of sessions. I also want to make sure at any given time ONLY the sessions that are necessary are in memory.
This means I need an effective way of managing my session variables. Any suggestions?
Two things:
1 - You should not be storing so much in session that managing memory is a concern. I.e., don't store objects in session, store pointers to things, e.g., rather than an instance of User just store the UserID. If you need to, you can add caching of retrieval of info, but that should be in a caching layer separate from sessions.
2 - Use database sessions, so that there is no concern about server memory, and so that you can add more web servers easily if desired (note, StateServer gives you this capability as well). Additionally, this lets you recycle the app pool without users losing their session. This is the main reason I do it - it lets me deploy on the fly.
The reason to treat sessions so delicately, is that they hang around after a user's last request, typically for 10 to 20 minutes. So, requests from many different sessions can use up large amounts of server memory if you are storing large objects in session. Doing even crazier things, like storing database connections in session, can result in you using up all available database connections, just because so many are hanging around in memory waiting for the session to expire.
Ideally, there is no "managing" of sessions required.
What I normally do is only keep the id of an object in Session and keep the data in a caching layer in front of the database. That way, you keep your session fairly small but most data can still be retrieved efficiently if the item is in cache. This has usually worked well for me.
I think you're misunderstanding sessions in ASP.NET. You do not explicitly manage them (although you could, you would rarely want to) they are implicitly created and destroyed by ASP.NET and IIS. Every user is given a session.
Now anything you store inside a users session is stored in memory on the server so if you routinely place large objects in each users sessions this will cause the memory to grow rapidly leading to performance and scalability issues.
The only data you need to store in the session is transient data that you want to be available across different page requests that you want to be secured that it is not available to the client in a cookie or similar construct.
However reading what you're doing this is most likely not needed. Since you are working with a specific page and "director" functionality this would most likely be fitting to place on the page in the viewstate as an intermediary data store.
There is no wright answer. It depends on the number of concurrent users, on the size of your memory.
Keeping things on session is faster than on a database, if you have your session variables in proc.
I usually try to keep just things that I know the user might need during a specific task, or, like you said, information of the current user.
My suggestion is:
Wrap the session access into a IPerSessionCache interface
Have a concrete implementation of this interface
Use an instace of the concrete class in the code to get/set session data
By this, then you have the freedom to clean up the instance of IPerSessionCache when the session ends
The code will not need to know where the IPerSessionCache actually stores the data (ie. it could in the Session or in a database or in a cookie etc.)
You would have better control on the lifetime of the IPerSessionCache especially if you use a DI container for managing & creating the instance
HTH.
My suggestion: Don't use session variables. Store everything in a database.
Which session mode in the following ,should i implement for my ASP.Net website?
1)InProc .
2)State Server.
3)SQL Server.
4)Custom.
It depends entirely on your circumstances and the type of website you wish to operate.
I suspect your expected volumes of traffic and the hardware it is running on is also a large factor.
Can you give us more information.
Performance considerations
InProc - Fastest, but the more session data, the more memory is consumed on the web server, and that can affect performance.
StateServer - When storing data of basic types (e.g. string, integer, etc), in one test environment it's 15% slower than InProc. However, the cost of serialization/deserialization can affect performance if you're storing lots
of objects. You have to do performance testing for your own scenario.
SQLServer - When storing data of basic types (e.g. string, integer, etc), in one test environment it's 25% slower than InProc. Same warning about serialization as in StateServer.
Robustness
InProc - Session state will be lost if the worker process (aspnet_wp.exe) recycles, or if the appdomain restarts. It's because session state is stored in the memory space of an appdomain. For details, see KB324772.
StateServer - Solve the session state loss problem in InProc mode. Allows a webfarm to store session on a central server. Single point of failure at the State Server.
SQLServer - Similar to StateServer. Moreover, session state data can survive a SQL server restart, and you can also take advantage of SQL server failover cluster, after you've followed instructions in KB 311029.
The above is an extract from an article by Peter A. Bromberg available here
There's no one clear answer. It depends on how your app works, how many servers you have, what your tolerance for failure is etc. I would read up on the differences and then make an informed choice.
Providing you make everything that you are storing in the session serializable from the beginning, it is usually fairly easy to switch from one mode to another, unless you are using things like the Session_End event, which only fires when using in proc mode.
The default is InProc, and that works fine for most small and moderate size web sites. You just use it, you don't have to implement anything at all.
If you have any special curcomstances, like load balanced servers or extreme amounts of users, you would need some of the other methods.