system.web.caching - At what level is the cache maintained? - asp.net

I am looking at implementing caching in a .net Web App. Basically... I want to cache some data that is pulled in on every page, but never changes on the database.
Is my Cache Element unique to each:
Session?
App Pool?
Server?
If it is session, this could get out of hand if thousands of people are hitting my site and each cache is ~5k.
If App Pool, and I had several instances of one site running (say with a different DB backend, all on one server, though) then I'd need individual App Pools for each instance.
Any help would be appreciated... I think this data is probably out there I just don't have the right google combination to pull it up.

By default it is stored in memory on the server. This means that it will be shared among all users of the web site. It also means that if you are running your site in a web farm, you will have to use an out-of-process cache storage to ensure that all nodes of the farm share the same cache. Here's an article on MSDN which discusses this.

"One instance of this class is created per application domain, and it remains valid as long as the application domain remains active" - MSDN

Related

Azure Scale Out WebApp Connection Constantly Switches Between Servers

We have an ASP.NET WebForms website running in an Azure WebApp with automatic "Scale Out" enabled. I can see there are currently two instances running. We have a test page with the following code:
Request.ServerVariables["LOCAL_ADDR"]
If we constantly refresh this page, the IP randomly switches between two different values (presumably for the two different website instances that are running). This is breaking functionality that relies on Sessions, as the Sessions are server-specific.
Is there a way to keep users on the same server instead of connecting them to a random server for each request? (I understand this wouldn't fully solve the problem, so my next question is...)
Is it not viable to use Session objects with the "Scale Out" feature enabled? If not, what are some other options? If we use cookies, I'm concerned about reaching data limits since we occasionally use Sessions to preserve large data sets for short periods. If we use something like a Redis cache, it adds to our operating costs. Is there a better way to do this?
In Azure App Service we need to enable ARR Affinity to keep the session active in one Server.
The Application requesting routing identifies the user and assigns a Affinity cookie. Client establishes the session with the current instance and keeps the instance active until the session expires.
ARR affinitywill not work when we scale out the app service instances, when we scale out, new instances of our app services server will be created and the ARR Affinity will fail if the request goes to new server.
Thanks #ajkuma-MSFT
If our application is stateful, scaling up would be the best option, If our application is stateless, scaling out gives the greater flexibility and a better scalability potential.
Instead of Scaling out we can Scale up App Services plan by increasing the size and SKU of our existing App Service plan to higher tier with more compute, features and then enable the ARR affinity, which helps the sessions remain active and persistent in one Server.
If we use something like a Redis cache, it adds to our operating costs.
Thanks #Praveen Kumar Sreeram
when you configure Load Balancer utilizing the auto-scaling capability, "Sessions" wouldn't work as planned in the Azure App Service.
Another option is to use Redis Cache.
Currently I am using the Standard Tier S1.
With auto Scaling Rule, we can scale up and down when it is not required.
Scale up to Standard S3.
One affinity cookie will be associated to the app server for each request, even if the app receives repeated requests; this will maintain the session's persistence and activity.
And as new instance of app server won’t be created, the application session will remain active due to ARR affinity.
Reference taken from Microsoft Q&A

Multiple Azure Web App Instances - Inconsistent DB Queries / Data

I have an Azure Web App with autoscaling configured with a minimum of 2 instances. Database is SQL Azure.
User will make changes to the data e.g. edit a product's price. The change will make it to the database and I can see it in SSMS. However, after user refreshes the page, the data may or may not get updated.
My current theory is something to do with having multiple instances of the web app, because if I turn off autoscale and just have 1 instance, the issue is gone.
I haven't configured any sort of caching in Azure at all.
It sounds like what is happening is the data may or may not appear because it is stored in memory on the worker server (at least temporarily). When you have multiple worker servers, a different one may serve the request, in which case that server would not have the value in memory. The solution is to make sure that your application's code is re-fetching the value from the database in every case.
Azure Web Apps has some built in protection against this, called the ARR affinity cookie. Essentially each request has a cookie which keeps sessions "sticky". i.e. if a worker server is serving requests to a certain user, that user should receive subsequent requests from that server as well. This is the default behavior, but you may have disabled it. See: https://azure.microsoft.com/en-us/blog/disabling-arrs-instance-affinity-in-windows-azure-web-sites/

Application variable across load balanced servers (ASP.Net)

We have a website that runs on two load balanced servers. We used the ASP.Net Application variable to make application state "online/ offline", or for some important messages across the application,
So when i try update a application variable its available on one server but not on other.
How i can manage a application variable across load balanced servers.
What may I use? Of course keeping it as simple as possible.
Are you using sticky sessions? How often does the data change? Is application cache even necessary?
One option: You can have each webserver store (and manage, refresh, invalidate) its own application cache. But then you run the chance of storing different copies.
Another option: distributed cache such as memcached or ncache or something else.
Another option: read/write the data out to a shared disk.
Store that information in a database that all servers have access to and access information from.

How to deploy website to production with minimal impact to users

I'm trying to find the best server architecture solution to deploy monthly updates to an Asp.net external public facing website. What I'm looking for are ways to release a new version of a website with minimal impact to users. Besides deploying the standard way (ie. stop IIS, copy new website over existing website, start IIS), what are some "better" solutions for deployment out there? It would be nice if they kept their session and didn't have to see a "Website under maintenance" message during the update.
My server configuration
We have 2 IIS web servers (2003) and are trying to figure out the best way to utilize them for deployments. My first thought was to update the non-active web server with the latest release. Then to gracefully point the web traffic to that server with minimal impact to users (best case, the user doesn't lose his session). How would you go about "repointing" the web traffic from server 1 to server 2? Changing firewall NAT? Changing DNS records? Some other way?? We need to be able to test the live site immediately after we release the new changes (duh).
BTW, we are using nant and cruise control to automate the builds, and a custom web service to deploy the build to production. So it's all automated with the click of a button.
Could a better solution be achieved using a 3rd server? If so how?
The way we do is
We have a load balancer from netscaler,
take one webserver out of loadbalancer , do all deployments, do a iisreset and the put back in load balancer.
Do the same thing for server2 .
Finally invalidate loadbalancer cache.
Well, there are a couple of things here:
First, consider using a load balancing solution. Windows 2003 server ships with windows load balancing (WLBS), though its not the greatest product. It is, though, free. With that, you can point all traffic to one server, update it, and then do the opposite.
Secondly, you may want to consider looking at how you're working with sessions. HTTP is stateless, which means that as long as you can reconstruct a user's session on any page hit, you should be fine. One ideal step towards this is using ASP.NET Forms Authentication - the cookie written by it isn't tied to an ASP.NET session. Of course, this approach leads to greater risk - there is a chance users will get an error screen if they hit something JUST AS you're copying files. And then there will be a delay while the app pool refreshes.
Overall, your better option is load balancing. Even with it, though, consider trying the second option as well - having sessions that can regenerate works well if users fail to be sticky to one of the servers in the pool.
Just wanted to add this for brevity. At my previous work, we achieved seamless deployments by using the following setup:
A load balancer would point to the production ASP.NET webservers (two in your case, but we had three), and the webservers would have their session setup to pull from a third server dedicated to hosting OutOfProc ASP.NET session.
To deploy a site, we'd pull one of the servers out of the load balancer, update the files, fire it back up, and place it back into the load balancer pool. Repeat for the rest of the webservers.
Because each webserver got the session data from the one central server, taking one webserver out, did not log out the users on that server.
If we had code changes that were incompatible with the existing session data, we'd wait till a scheduled maintenance window to deploy. Otherwise, users with that session data would get errors till they logged out.
Additionally, since this setup relies on the webserver being up, if you wanted to increase reliability, you could change the OutOfProc to SQL based session servers. You would need several servers that replicated the same session database and point the webservers to them. More complicated, but would reduce site downtime.

ASP.NET In a Web Farm

What issues do I need to be aware of when I am deploying an ASP.NET application as a web farm?
All session state information would need to be replicated accross servers. The simplest way would be to use the MSSQL session state provider as noted.
Any disk access, such as dynamic files stored by users, would need to be on an area avialable to all servers. Such as by using some form of Network Attached storage. Script files, images and html etc would just be replicated on each server.
Attempting to store any information in the application object or to load information on application startup would need to be reviewed. The events would fire each time the user hit a new machine in the farm.
Machine keys across each server is a very big one as other people have suggested. You may also have problems if you are using ssl against an ip address rather than a domain.
You'll have to consider what load balancing strategy your going to go through as this could change your approach.
Sessions is a big one, make sure you use SQL Server for managing sessions and that all servers point to the same SQL Server instance.
One of the big ones I've run across is issues with different machineKeys spread across the different servers. ASP.NET uses the machineKey for various encryption operations such as ViewState and FormsAuthentication tickets. If you have different machineKeys you could end up with servers not understanding post backs from other servers. Take a look here if you want more information: http://msdn.microsoft.com/en-us/library/ms998288.aspx
Don't use sessions, but use profiles instead. You can configure a SQL cluster to serve them. Sessions will query your session database way too often, while profiles just load themselfs, and that's it.
Use a distributed caching store like memached for caching data, and ASP.Net cache for stuff you'll need alot
Use a SAN or an EMC to serve your static content
Use S3 or something similar to have a fallback on 3.
Have some decent loadbalancer, so you can easily update per server, without ever needing to shut down the site
HOW TO: Set Up Multi-Server ASP.NET Web Applications and Web Services
Log aggregation is easily overlooked - before processing HTTP logs, you might need to combine them to create a single log that includes requests sent to across servers.

Resources