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.
Related
Since we have moved to azure, we have numerous session lost issues only on production.
We have InProc, cookie based, sticky session, large timeout, no high traffic and no high memory/process usage.
We use HAProxy as loadbalancer.
I have done basic research and none of the following seems to be the cause:
session timeout
application pool settings/recycling
memory size and usage thresholds
no eaten exceptions
there is no changes to file system to cause a restart
I'm particularly more suspicious about how loadbalancer/ssl and application work together and if http headers are fine, but I don't know any tools to really monitor that.
I'm assigned to find a solution at the same time I have no privilege to access the machines.
Logs(Log4Net) are all stored in database but doesn't help to give a clear understanding of what is going on the system and cannot follow a user session using them.
I'm allowed to find the problem by adding required logs to code or to develop some kind of monitoring module or to use profiling/debugging tools.
Only once a month there will be a production deployment so I'm trying to use the opportunity as best as possible.
Question:
Is there any useful monitoring/profiling tool that can give me a clear view of what is happening in the system by aggregating information I may need? for example following a user/session between requests from time of login until session drop plus information about headers and other system application parameters.
if there is not such a tool out there, please give me your ideas to write one?
This is a common issue in load balanced environment. As mentioned in this answer for a similar question,
InProc mode, which stores session state in memory on the Web server. Which means that session data is maintained inside your web server on a given VM and is not shared outside of the VM. So when you have multiple server for load balancing, the session state isn't shared with each other. To solve this, you must store your session state external to the web server.
Use Redis, or SQL Database, or something else.
I am working on a MVC 3 application that will be hosted in a web-farm with a multi-worker process setup. There are about a dozen variables that are being stored in Session but are getting lost due to the IIS setup.
By getting lost I mean that when the Logon process succeeds I see through logging that I have set the Session variables but then after the Redirect action and on the landing Controller Action the Session variables are often empty. I'm not sure if this is related but this is in a HTTPS.
We are looking at the possibility of moving our user-specific settings that are stored in Session out to some other mechanism but there is one variable that I won't be able to do that with. Given the above deployment environment I have the following questions.
Are cookies my only (best?) alternative to storing Session variables for user-specific settings?
If so is there a secure mechanism for writing cookies so they cannot be manipulated and can still be read in a multi-server environment?
As I understand it System.Runtime.Caching suffers from the same problem when ran in the above IIS configuration. Is that true?
Are cookies my only (best?) alternative to storing Session variables
for user-specific settings?
No - they are about the worst possible approach. Three reasons that come to mind:
They can be manipulated.
They travel with every request from client to server - inefficient.
They will add more complications to your implementation since you'll have to start thinking about securing them in different ways.
If so is there a secure mechanism for writing cookies so they cannot
be manipulated and can still be read in a multi-server environment?
See answer above.
As I understand it System.Runtime.Caching suffers from the same
problem when ran in the above IIS configuration. Is that true?
True. You should be using any of the State Providers that are out of proc. You can either use Sql Server to store session data -provided your objects are serializable, obviously- or the State server mode mode="stateserver"
Read here for more details
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 wrote a composite web control that is used in several web applications. If I use sessions variables, for example HttpContext.Current.Session("MyProgramMemberId"), do I run the risk that the host site might have also defined that same session key name?
I'd like to hear of your experiences if you had a problem with this. It would be a bonus if you have website reference that you trust.
Thanks!
I can't say that I have any actual experience with this (mainly because I wouldn't do this), but yes it's absolutely possible that you could have a collision with another session variable named the same thing in the hosting web application.
What I would suggest is removing the reliance on the session variable, and instead use a ViewState variable instead. These are more isolated to specific instances of your control, and therefore should not conflict with each other. Of course there are considerations based on what you need to store, you would want to be careful trying to store large objects, lists, dictionaries, as well as sensitive information in the viewstate (which ends up being transmitted to the client). But based on your sample code, it looks like it's a simple Id property which is small and (usually) not sensitive.
It also depends on how you setup your website. If you are re-using the control in different web applications but on the same site it should not be an issue. If you are re-using them in the same application this would be a design issue.
If you are asking if you need to be worried if your session names will collide if you go to a shared host you will not need to worry. The thing you will have to worry about is if you are storing your session InProc. If you are storing your values InProc and your site is load balanced there could be issues as the balancer chooses different servers to serve your content.
In order to improve speed of chat application, I am remembering last message id in static variable (actually, Dictionary).
Howeever, it seems that every thread has own copy, because users do not get updated on production (single server environment).
private static Dictionary<long, MemoryChatRoom> _chatRooms = new Dictionary<long, MemoryChatRoom>();
No treadstaticattribute used...
What is fast way to share few ints across all application processes?
update
I know that web must be stateless. However, for every rule there is an exception. Currently all data stroed in ms sql, and in this particular case some piece of shared memory wil increase performance dramatically and allow to avoid sql requests for nothing.
I did not used static for years, so I even missed moment when it started to be multiple instances in same application.
So, question is what is simplest way to share memory objects between processes? For now, my workaround is remoting, but there is a lot of extra code and I am not 100% sure in stability of this approach.
I'm assuming you're new to web programming. One of the key differences in a web application to a regular console or Windows forms application is that it is stateless. This means that every page request is basically initialised from scratch. You're using the database to maintain state, but as you're discovering this is fairly slow. Fortunately you have other options.
If you want to remember something frequently accessed on a per-user basis (say, their username) then you could use session. I recommend reading up on session state here. Be careful, however, not to abuse the session object -- since each user has his or her own copy of session, it can easily use a lot of RAM and cause you more performance problems than your database ever was.
If you want to cache information that's relevant across all users of your apps, ASP.NET provides a framework for data caching. The simplest way to use this is like a dictionary, eg:
Cache["item"] = "Some cached data";
I recommend reading in detail about the various options for caching in ASP.NET here.
Overall, though, I recommend you do NOT bother with caching until you are more comfortable with web programming. As with any type of globally shared data, it can cause unpredictable issues which are difficult to diagnosed if misused.
So far, there is no easy way to comminucate between processes. (And maybe this is good based on isolation, scaling). For example, this is mentioned explicitely here: ASP.Net static objects
When you really need web application/service to remember some state in memory, and NOT IN DATABASE you have following options:
You can Max Processes count = 1. Require to move this piece of code to seperate web application. In case you make it separate subdomain you will have Cross Site Scripting issues when accesing this from JS.
Remoting/WCF - You can host critical data in remoting applcation, and access it from web application.
Store data in every process and syncronize changes via memcached. Memcached doesn't have actual data, because it took long tim eto transfer it. Only last changed date per each collection.
With #3 I am able to achieve more than 100 pages per second from single server.