I have been using the HttpRuntime Cache for caching simple user preferences on an in house [dasboard] asp.net app that gets used by almost 200 users daily.
I simply cache stuff such as the last query conditions, scales, options (just checkboxes dependent on other checkboxes etc.) just so that when a user closes the browser, they will be returned to the exact dashboard/report option the next time they open the browser.
I do not want to use the database to cache these values because they are "unlimited" and "dynamic".
Anyway, the HttpRunime Cahce has been working fine but now every once in a while it doesn't work on the production server.
Is there any approach to fix this problem?
The cache is application wide - are you cacheing these items on a per user basis?
The cache will periodically die, and you have no control over this - if you need these items to persist, then DB cacheing may the only way to go.
Edit - as to the unlimited and dynamic, you could potentially store them in an XML field in the database. If you have an object where they are currently stored in the cache, it would be relatively easy to serialize/deserialize this from the DB, if the cache is empty.
There are timespan and absolute expiration settings available qhen you insert into cache, but when the app pool recycles, the cache is wiped out. Check your App Pool setting in IIS, and see how frequently it recycles.
Related
Can someone give me a good reason why ViewState isn't stored on the server by default?
Why not send a small session token in place of ViewState, which can then be mapped to whatever ViewState info is needed on the server, to prevent the whole ViewState being posted back and forwards multiple times.
Am I missing something?
Scalability - imagine how much server resources would be needed if a complex WebForms page was viewed by 1M users. Server would need to hold ViewState for at least the duration of the session timeout. Automatic server side cleanup of viewstate would also be problematic - user may be viewing several pages at once so ViewState for all pages would need to be retained.
Edit
There are several techniques discussed in these posts on how to move viewstate to the server. However, before you do that, it would be a good idea to remove unnecessary viewstate from controls / pages which don't need it (e.g. View only / no postback rendering).
I'm guessing now, but when viewstate was designed 10 years or so ago, 1GB RAM on a 32 bit server was about as good as it got, and MS presumably had to think of hosting providers wanting load 100's of apps per server. So bandwidth was probably viewed as cheaper than server Ram and disk storage.
There are a number of issues with storing the ViewState in memory.
If the application recycles, the VS for all anyone using the application is lost.
It increases the memory consumption of the application. This isn't an issue if there are only a few apps hosted on a server; but there are cases when there could be many websites hosted on one box.
Scalability; the more active the application, the more VS needs to be stored. And you can't assume 1-1 (1 user - 1 VS). A user can have multiple tabs open, can go back, leave tabs inactive, etc... which leads to:
How long do you store VS? Keeping the data encoded on the page ensures that it'll still be there if the user leaves the site open for a while.
What happens if you're hosted on a web farm. We can't guarantee that the user will hit the same machine on each request.
That being said, there are a few solutions:
Memcached-Viewstate - stores the VS in distributed memory using Memcache. This isn't ideal - if a server goes down the VS for anyone who had the VS stored to that server is lost, but will allow for application pools to reset without issue.
SQL-Viewstate - stores the VS in a SQL database. This adds a least 1 DB read and 1 DB write per request. Again, not ideal, but if the VS is getting unmanagable getting and setting the VS from the database is faster than sending and recieving it over HTTP.
Filesystem-Viewstate - stores the VS in the filesystem. It's less expensive than the SQL connection but would require a file server to work in a distributed environment.
It improves scalability because the server doesn't need to maintain all of that in memory. It is possible to store the viewstate in session but it's generally not recommended.
The root cause is using client side view state is that server doesn't know the current state of the page.
If a user is anxious, does multiple (partial) postback on the page, without waiting the response, browser will send out multiple partial postback requests, that each request create a new view state on server side, which will eventually flush out the initial view state in the browser. Finally the user does his last postback, at that time, the inital copy is gone, thus exception is thrown.
Also server side view state impacts server performance and user experience. If a user doesn't interact with the page for a day or a long time, the view state on server will expire. When the user posts back the page later, an exception is thrown.
For instance I watch youtube video of length 40 minutes. Yesterday I watched the first half, didn't close the tab but hiberated my computer. Today I continue watchig the last half, and post back something, the page will get errored out if the view state is in server and expired.
I've tried to read up on Caching in ASP.NET and still have a few questions.
When using a Sql Cache Dependency ... I know that you can specify which tables will be monitored but if a change happens to any one of those tables does it reset the entire cache? I understand that I don't want to cache tables that will have frequent changes but we could end up with a good handful of cached tables and even if each table only gets a few updates a day, that could turn into 50ish resets of the cache daily (8 hour window).
I would be creating and maintaining this cache via a GAC DLL. A large number of different applications would be accessing that GAC at any one time. Does each application maintain its own copy of the cache or is it just stored in one global location (or possibly per app pool)?
Is there a physical location on the server where I can see how much space the Cache is currently consuming? This would be extremely pertinent if each application maintains its own Cache as that could end up taking large amounts of disk space.
Is there some way to physically force the cache to rebuild itself? I could see my boss assuming that the cache was at fault for a particular issue and I'd need to be able to rule that out at the rootest level. No "changing a record and saying that SHOULD rebuild the cache" but rather "doing [Action X] and KNOWING that whatever was in the cache is now gone"
Thanks in advance for your answers and time.
SqlCacheDependency only monitors tables in the old-style SQL 2000 approach, which relies on triggers and polling. The SQL 2005+ method monitors changes at the row level, and uses Service Broker. At the level of the Cache object, changes will invalidate just the Cache entries associated with the given SqlCacheDependency (not the entire cache).
Each application has a separate copy of the Cache. If you have many apps sharing the same data, you might consider creating a separate "caching server," and have your apps get their data from there, using WCF -- basically add another tier to your app.
You can look at a couple of cache-related performance counters, but if your concern is disk space, then there's nothing to worry about, since the ASP.NET cache is stored entirely in RAM. In addition, if RAM gets too full, one feature of the cache is that it will let go of old/infrequently referenced objects to make room for new objects.
The easiest way to force the cache to be dropped is to simply recycle your application or AppPool (which happens once a day or so by default anyway). If you want something more targeted, you would need to write some code to forcibly remove certain items from the cache, either using Cache.Remove() or using linked dependencies.
from top of my head:
Only that table's content will be invalidated.
Each web application has it's own cache.
Cache is stored in memory. and see this question How to determine total size of ASP.Net cache? regarding cache size
http://bit.ly/vsqNDl this may help
I have two separate web applications:
The "admin" application where data is created and updated
The "public" application where data is displayed.
The information displayed on the "public" changes infrequently, so I want to cache it.
What I'm looking for is the "simplest possible thing" to update the cache on the public site when a change is made in the admin site.
To throw in some complexity, the application is running on Windows Azure. This rules out file and sql cache dependencies (at least the built in ones).
I am running both applications on a single web role instance.
I've considered using Memcached for this purpose. but since I'm not really after a distributed cache and that the performance is not as good as using a memory cache (System.Runtime.Caching) I want to try and avoid this.
I've also considered using NServiceBus (or the Azure equivalent) but again, this seems overkill just to send a notification to clear the cache.
What I'm thinking (maybe a little hacky, but simple):
Have a controller action on the public site that clears the in memory cache. I'm not bothered about clearing specific cached items, the data doesn't change enough for me to worry about that. When the "admin" application makes a cache, we make a httpwebrequest to the clear cache action on the public site.
Since the database is the only shared resource between the two applications, just adding a table with the datetime of the last update. The public site will make a query on every request and compare the database last update datetime to one that we will hold in memory. If it doesn't match then we clear the cache.
Any other recommendations or problems with the above options? The key thing here is simple and high performance.
1., where you have a controller action to clear the cache, won't work if you have more than one instance; otherwise, if you know you have one and only one instance, it should work just fine.
2., where you have a table that stores the last update time, would work fine for multiple instances but incurs the cost of a SQL database query per request -- and for a heavily loaded site this can be an issue.
Probably fastest and simplest is to use option 2 but store the last update time in table storage rather than a SQL database. Reads to table storage are very fast -- under the covers it's a simple HTTP GET.
Having a public controller that you can call to tell the site to clear its cache will work as long as you only have one instance of the main site. As soon as you add a second instance, as calls go through the load balancer, your one call will only go to one instance.
If you're not concerned about how soon the update makes it from the admin site to the main site, the best performing and easiest (but not the cheapest) solution is to use the Azure AppFabric Cache and then configure it to use a a local (in memory) cache with a short-ish time out (say 10 minutes).
The first time your client tries to access an item this would be what happens
Look for the item in local cache
It's not there, so look for the item in the distributed cache
It's not there either so load the item from persistent storage
Add the item to the cache with a long-ish time to live (48 hours is the default I think)
Return the item
Steps 1 and 2 are taken care of for you by the library, the other bits you need to write. Any subsequent calls in the next X minutes will return the item from the in memory cache. After X minutes it falls out of the local cache. The next call loads it from the distributed cache back into the local cache and you can carry on.
All your admin app needs to do is update the database and then remove the item from the distributed cache. The next time the item falls out of the local cache on the client, it will simply reload the data from the database.
If you like this idea but don't want the expense of using the caching service, you could do something very similar with your database idea. Keep the cached data in a static variable and just check for updates every x minutes rather than with every request.
In the end I used Azure Blobs as cache dependencies. I created a file change monitor to poll for changes to the files (full details at http://ben.onfabrik.com/posts/monitoring-files-in-azure-blob-storage).
When a change is made in the admin application I update the blob. When the file change monitor detects the change we clear the local cache.
A website that I'm working on is making extensive use of the HttpContext.Current.Application store to cache lookup data from the database. (This isn't a lot of data - just simple things that are used in drop down lists etc..)
A few questions about this approach:
Does this store have a lifetime (in the same way that a user's session will time-out after 20 minutes, does the application store timeout)?
Do events in IIS or events in the same App Domain as the website cause the Application store to refresh? (I understand that changing a value in the web.config file causes the store to be re-created.. are there other things that do this?)
Is there a better way to do this?
Web.config causes the application to restart, and it is that action which is clearing out HttpContext.Current.Application.
Anything that restarts the application, touching web.config, manually doing it in IIS, having the application pool recycled by IIS will "clear" that data.
With that in mind it is still the most pernament in-memory store available, so if you need something more pernament you will have to persist your data to disk or to a database somewhere.
You probably don't really need to use it though (we rarely do), usually the best tactic is to use the application cache and rebuild resources as required. As long as your server isnt under high memory stress then cache will not be dropped either (unelss an expiry is set).
My understanding this is available for the application lifetime, or until the application pool is reset.
There is a good article here on all the various reasons the application/session pool in IIS would be recycled.
There are settings in both IIS and also web.config which can change the behavior of the application store availability.
I'm using the SqlProfileProvider on one of my websites and in one page I need to fetch the whole list of profiles (it is an intranet).
The method that I use is the ProfileManager.GetAllProfiles(). The problem is that its performance is really bad and it slows down the website considerably.
Therefore, I was thinking of caching the result of the method call in the Application scope as a DataTable (so I could filter/search on it as well).
My problem is that I have several servers running this webapp, and I would like the cache to be in sync. I started using memcached but I was put off by some problems (hence going back to thinking in caching in the Application scope).
So, here are my questions:
Would it be efficient to store the DataTable containing the profiles in the Application object? Or, is it possible to store objects in the Cache and have them available for all clients/browsers?
Is it possible to add a (SQL) Cache Depedency to this cache?
You could cache portions of the web page which will depend on the list of profiles by putting them in a user control and marking it as cacheable. SqlCacheDependency cache policy expiration could be defined as well. As for the cache location, every web server in the farm will have it's own version in memory but using cache expiration will make sure that this version is not out of sync with the data in the DB.
Page or fragment caching is the most effective caching technique because contrary to caching your model (a DataTable or whatever) you don't pay the price of HTML rendering.