I've read several threads about this topic and need some clarification on a few sentences I read in a book:
If you store your Session state in-process, your application is not scalable. The reason for this is that the Session object is stored on one particular server. Therefore storing Session state in-process will not work with a web farm.
What does "scalable" in the first sentence mean?
Does the third sentence means if my app resides on a shared web host, I shouldn't use Session["myData"] to store my stuff? If so, what should I use?
Thanks.
1:
Scalability in this sense:
the ability of a system, network, or process, to handle growing amounts of work in a graceful manner or its ability to be enlarged to accommodate that growth.[
2:
Use a session server or store sessions in SQL Server, which are described here.
ASP.NET can store all the combined Session information for an Application (the "Session State") in 3 possible places on the server-side (client cookies is also possible but that is a different story):
"InProc" (In Process) which means in memory on the IIS server attached to the asp.net worker process,
"StateServer" which is a separate process that can be accessed by multiple IIS servers but still stores the Session state in memory, and
"SQLServer" which stores the Session state in a SQL Server database.
1) The reason In-process is not scalable is if your needs exceed the capacity of a single IIS server, multiple servers can't use an In-process session state. If you have determined a shared hosting scenario will fulfill you needs, you don't need to worry about it.
2) When you store something in Session["Name"], ASP.net stores that data wherever the application is configured to store Session state. If you want to change where Session state is stored, all you need to do is configure your web.config file. If you are using a shared hosting environment, your IIS deployment is considered single server even though no doubt the actual servers are in a farm of some sort.
See: MSDN Session-State Modes
Related
We currently have a system that has somewhat over 200,000 unique session request/day and so we have introduce a new server with a load balancer to handle the load. This is where the problem comes in because Our sessionstate ="InProcess". Once a user initiates the application, we load a some important variables in the Session because these variables are used throughout the application and instead of hitting the database every page we store it in a Session Object. Which works but using this way we have to make sure the App Pool doesn't recycle but once a day and during downtime hours which make the server memory get huge throughout the day. Keep in mind that this system is initiated from System A, so if these main values are lost then the application has to be reopened by System A
Solution 1: Replace using the Session Object for storing variables to an Application Cache (But will this be able to retain their values during App Pool recycle)
Solution 2: Hit the SQL server database every page for these values ( But I think this will not scale well to continually open and close connections for information I could maintain in the application)
Solution 3: update Session Objects used to be serialize and add a StateServer in the mix to handle the session being retained during App Pool recycle and across both servers (but doesn't this bring performance down).
Solution 4: Save these values to the client side of the code by using hidden controls and send those values to the server every hit. These properties are not sensitive information so this should not be a problem
Solution 1: If you use built-in .NET cache, it does not survive the app pool recycle.
Solution 2: I wouldn't recommend that however you can write your own session storage provider and use any key-value storage (e.g. filesystem or maybe some document database). But you are de facto writing your own State Server.
Solution 3: State Server is fine for small number of instances. It is also reasonably fast so I would prefer it.
Solution 4: If the information is large to be stored in a cookie (there is 4kB limit I think), you can use hidden form fields but it is not an elegant solution. It is usable only if we are talking about several variables you need to persist.
I don't know the application however for most cases I would pick the State Server.
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.
The ASP.NET SQL SessionState provider seems excessive for my requirements. SQL Server has to be 'configured' to support it and I have questions about how optimized it is (i.e. is there one db hit to fetch the whole session or one for every session item requested?).
I think I could implement a custom solution very easily that I would understand and easily redeploy to other projects. Is there something fundamental I haven't considered here and an obvious reason why the built in SessionState handler is the 'best' way to go?
Just to clarify, our applications run on single servers at the moment. My main motivation for doing this is to enable Session to persist across IIS restarts and therefore provide more reliability for users.
you could use StateServer mode.
StateServer mode stores session state in a process, referred to as the ASP.NET state service, that is separate from the ASP.NET worker process or IIS application pool.
Using this mode ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
more info at http://msdn.microsoft.com/en-us/library/ms178586.aspx
It takes just minutes to setup SQL session state server (assuming you have SQL server already running). I can't imagine that you can write anything in less time than it would take to at least try out what already exists and is free and supported by MS.
A proven, built-in/off-the-shelf solution is always better place to start than custom. You may still end up with a custom solution, but don't pick it because you didn't bother to test what is already available to you.
If we start to use 2 servers instead of one, with load balancing, is there a way to store sessions in memory, so we wouldn't need to change 50 webconfigs to set sessions are stored in database?
Obviously, 2 servers would be there if one fails, so storing sessions in memory would back things to beginning.
Thanks.
One option is to use a load balancer that supports "sticky sessions". What that means is that the load balancer will always forward requests with the same session id to the same server, so no session sharing is required.
If I understand your question correctly, then the answer is "No". If you are using the default inprocess session provider, then when you switch to using 2 machines, you will need to switch the session provider to some out of process (ie Sql Session provider or Memcached) session providers so that both machines can access the same session source. This means you will need to modify all the web.conf
I was told this works, but...
I guess I'm just not getting this, it seems there's a hidden step I may be missing, can anyone correct this or point out my mistake? Thanks.
I have a blank solution:
- inside is two .net 2.0 web applications
1) webapp1
2) webapp2
I want them to share the same session data.
My page setups:
Application 1:
Session("value") = "this is the value"
Application 2:
If Not (Session("value") Is Nothing) Then
value = Session("value").ToString()
End If
My thought process:
1) go to services, turn on the asp.net state service
2) open the web configs in both projects: set the
< machineKey
validationKey="BFE2909A81903BB303D738555FEBC0C63EB39636F6FEFBF8005936CBF5FEB88CE327BDBD56AD70749F502FF9D5DECF575C13FA2D17CA8870ED21AD935635D4CC"
decryptionKey="2A86BF77049EBA3A2FA786325592D640D5ACD17AF8FFAC04" validation="SHA1" />
< sessionState mode="StateServer" stateConnectionString="tcpip=localhost:42424"
cookieless="false" timeout="20"/>
in both sites.
3) compile and test the site
4) become disappointed because it does not work. I never see the session from the second webapp.
You cannot share sessions between different ASP.NET applications without some custom code. What you did in web.config was to use an out of process sessions, which means that data will no longer reside into memory but into the memory of a dedicated machine. This is useful for server farms and it uses the ApplicationName to know which application the session belongs to. So basically your applications need to have the same name if you want them to share sessions. There are some dirty workarounds though.
Why do you want to share Sessions between applications? ASP.NET Session is not designed to do that.
Your proposed solution of using the same ASP.NET State Server does not work because your user will simply get 2 different session tokens, even if they use your 2 applications concurrently from the same machine, and same browser. You need to consider how Session works to understand why this is.
From MSDN:
ASP.NET session state enables you to store and retrieve values for a
user as the user navigates ASP.NET pages in a Web application. HTTP is
a stateless protocol. This means that a Web server treats each HTTP
request for a page as an independent request. The server retains no
knowledge of variable values that were used during previous requests.
ASP.NET session state identifies requests from the same browser during
a limited time window as a session, and provides a way to persist
variable values for the duration of that session.
ASP.NET Session is a metaphor for a user's current interaction with one ASP.NET application. It exists in ASP.NET to give us a place to store temporary state data between the various page requests that a user makes while using your application.
If your applications are very closely related, e.g. the user uses both at the same time, or almost the same time, you could consider merging them into a single ASP.NET application. You could deploy them into different Virtual Directories to maintain some degree of logical separation, but use only one Application in IIS.
If your applications are not that closely related, perhaps they should be sharing the same database as a means to exchange data, or using an API e.g. based on Web Services to exchange information.
They will share session data if they are in the same app pool and the session mode is set to inproc. The way that stateserver and sqlstate work is they use the root of your web address as logical boundaries.
Eg if they are both hosted on the same address and port (or 'site' in iis) but in different sibfolders then they should share session I think.
Additionally both apps must run on the same domain so that user browser use one cookie to store session id.