I use 3 server through "Amazon balancer". On each server installed 2 (asp.net) web application (website, mobile site). "Balancer-Amazan"- so constituted that every 3 hours produces load transfer between servers, all session will be crash and creating a new (the users logs off)
Advise the possible solutions to the problem.
Thanks in advance.
If you have SQL Server available you can store your session state in that:
HOW TO: Configure SQL Server to Store ASP.NET Session State
You could even implement your own if SQL Server is not available:
http://msdn.microsoft.com/en-us/library/ms178588.aspx
How to: Sample Session-State Store Provider
The only caveats are that you can only store serialisable objects in the store, i.e. you wouldn't, for example, be able to store a System.Xml.XmlDocument object without turning it's representation into something than can be serialised, i.e. a string representing the XML.
I wrote up another answer that may be useful/provide further reading:
ASP.NET Session size limitation
Related
I manage shared session state across 2 production web servers using SQL Server database.
Recently I realized (And I am almost sure that this wasn't the case before) that the session is not really shared when jumping from server to server.
Both servers run the same website on the same domain and are balanced using a hardware load balancer. Both run under IIS7. And in both servers the ASP.NET State Service is running.
When inspecting the HTTP headers and cross referencing with SQL profiler captures I found what I think might be the problem.
The SessionId value in my cookies is a 24 character string, e.g: y4hfairc2xbwlupkdsqpv0nz
The SessionID as recieved by the ASPState database and as stored there is longer and has server specific 8 character postfix. e.g. 2476b033 or 2b7731d2 which is consistent across all sessions stored in the database.
The SessionIDs therefore look like: y4hfairc2xbwlupkdsqpv0nz2476b033 or y4hfairc2xbwlupkdsqpv0nz2b7731d2
Obviously because of that the session is not shared and each server maintains its own session state.
Anyone using a similar configuration that might have encountered this before?
Thanks
update
Turns out here: SessionId saved in SQL Server is different from the one generated from the asp.net runtime that the extra characters are the IIS AppID. Now I have to find out how to change it so both servers will match. So far no luck.
Anyone?
Answering my own question for completeness.
Thanks to this: https://serverfault.com/questions/288981/load-balanced-iis-7-5-web-server-asp-net-session-state-problem
I found out how to match the AppIDs.
Everything seems to work great now.
If I have sessions backed by SQL Server and run a command sequence like
HttpContext.Current.Session['user']
HttpContext.Current.Session['user']
Will this make 2 requests to the session DB table to fetch the value, or does asp.net do anything special with the Session object to prevent multiple DB hits?
Definitely YES.
I have SQL server session state setup and i ran Profiler on it. And could clearly see optimized DB calls.
If fact there are optimizations for getting multiple session items in one shot.
Like the below code will also result in SINGLE optimized set of calls (Note: Its not a plain single DB call to get session item)
HttpContext.Current.Session['user']
HttpContext.Current.Session['userTwo']
NOTE: Tested in .NET 4
You can implement your own session state provider if you need.
http://msdn.microsoft.com/en-us/library/ms178587.aspx
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
I have inherited an ASP.NET 3.5 application that relies heavily on sessions and storing DataTables within them (I know - bad, bad, bad). The application pool on the remote shared hosting service indicated that memory is at full capacity and as a result customers are losing their shopping carts because of dropped sessions.
Ultimately the goal is to rewrite this code, but for the time being I would like to stabilize the site the best I can. The host has recommended I use SQL Server Session State instead of in-proc. I have no experience with this, so I'm hoping it's as simple as running the .sql against the database to configure SQL Server and updating the web.config.
Any ideas? Thanks.
The docs say only that the session data has to be serializable. AFAIK DataTables are not serializable, unless you do it yourself, which is probably not going to work.
I was wondering whether it would be possible to change the sqlConnectionString used for SessionState in ASP.net based upon the domain an application is running on?
A scenario; We have 20 sites running from one application all talking to different databases depending which domain (site) they are browsing from.
When browsing www.domain1.com the application talks to the database 'db1'. The site www.domain2.com on the other hand talks to the database 'db2' etc, thus selecting the relevant content and also spreading the load to each database rather than using one master database to handle all connections for the sites.
An issue that has arisen though - for this setup we use SqlServer mode for the SessionState so all users to all sites sessions are stored in 1 aspstate database, now as the sites get busier / number of sites increase this database comes under increasing strain to handle all the session requests for all the sites and we are starting to get some timeout errors where the connections to this database are bottlenecking.
We can seperate out the sites to from their own application and set up different applications with the same code but within each application set a different Session database in each Web.Config and thus lightening the load. This task would be quite time consuming though and would result in more management in the long term. SO.. I would love to know if it's possible to modify within the code the sqlConnectionString used for SessionState, based upon a domain, before the session object is created? Can we inherit from System.Web.HttpApplication and use the Application_AcquireRequestState event to create the required setup of the HttpSessionState object?
Hopefully this makes sense and that someone can provide some pointers and prove to me that this isn't a pipe dream!
Cheers,
Steve
I think you are missing a big point--putting things in separate databases on the same server isn't going to help things at all if the bottleneck is sql server--it is either SQL running out of headroom or the network running out of bandwidth. I'd try and figure out which one it was before doing anything.
Your issue isn't so much that the connections to the database are bottlenecking, its that you are overwhelming the network connection to the database with data from all of the sessions.
By default, the Sql Server state provider simply serializes your data and ships it to the database. This is VERY inefficient and takes a LONG time to transfer on a fast network.
We solved this problem by going to a custom provider, like DOTSS that compresses session content before shipping it to the database. The compression rates we see are 80%-90% and the compression time is less than 10ms.
You can implement a custom session state provider. See MSDN for details. I've never done it, but with a little luck you can wrap the SqlServer session state module and redirect it based on the domain
First of all, I don't see there is advantage of "I would love to know if it's possible to modify within the code the sqlConnectionString used for SessionState, based upon a domain, before the session object is created" compared to set this in web.config.
Secondly, I think you need change that connection string setting in App_Start, so all the request will use that changed settings.Application_AcquireRequestState probably too late for this.
Why not split up the sites into sperate web applications and use hostheader to differentiate between the web sites. That way you could easily configure which session database you want your web application to use since each web application would have a seperate web.config file.
You could partition your session across different databases by implementing IPartitionResolver, and using a different partition for each domain.
Here's an example showing how to implement a custom partition resolver. (The example partitions by session ID, but it would be trivial to change it to partition by domain instead.)
We have several dozen development sites whose database connections are handled via the project's main Web.Config.
There is a separate configuration section corresponding to each URL on our intranet (e.g. http://development11, http://development12). We have SQL instances with a similar naming convention (DEVDB1\SQL1, DEVDB1\SQL2).
Based on the URL configured on the intranet IIS server, the app grabs the appropriate config. For testing we can easily modify the user, the database server or individual databases utilized for a particular site.