My Goal: Cache basically all the pages all the time so that users rarely ever have to hit my CMS for content.
I have a c#/.Net MVC 5 Web App deployed in Azure. I also have all the OutputCache's on my controllers set for 1 week [604800s] (content rarely changes). I assume, maybe naively, that the cached outputs are stored in memory in Azure. However, when I start my app and crawl the website, I'd expect the Azure memory to fill up with cached content, but in practice, there might be a bump in memory utilization. It goes back to its "resting state" of like 60% utilization after about 5 mins, though. I've also tried using MemoryCache, but it has a similar result - a bump in memory usage, and it goes down to normal shortly after.
In any case, the result is that the pages act like they weren't cached. For example, if I crawl 1 page and visit it - it loads in about 1 second (it's cached). If i crawl 2000 pages and visit a random one, it loads in 3-4 seconds (it's not cached). I've tested this by putting a datetime in the view itself.
So... the bottom line is: cached = fast, not cached = average. I want it to be fast!
I've looked at Redis Cache, which could be a way to do this, and seems easy enough... but my gut says this should be basic functionality (since it's built into the framework).
Azure Web App did support in-memory OutputCache. We can easily confirm it using following code. The output datetime will not be changed after you refresh the TestCache page.
[OutputCache(Duration = 3600)]
public ActionResult TestCache()
{
return Content(DateTime.Now.ToString());
}
But there are some problems when using in-memory cache in Azure Web App.
First problem with this is that it limits you to the memory that is available on your web app instance and this may create an out of memory issue when you cache a large amount of page output data. Your web app will be restarted if your memory is full. If the web app is restart, all the cached content will be lost. Another issue is that your application runs on multiple load balanced instances. The next request might go to another instance, which creates a new copy of ASP.NET Output Cache data in this instance, as well. These redundant copies of page outputs in each Web Role instance consume a lot of extra memory.
To avoid the upper problems, I suggest you use Redis Cache to store the cached content. For how to use Redis Cache, link below is for your reference.
ASP.NET Output Cache Provider for Azure Redis Cache
Related
To describe the app, it has an default page where it will be checking user role from request header then assign the user id into session and redirect to corresponding pages. In every other pages, it will check whether the session has value or not, if no then will redirect the default page.
This has been tested in my dev environment and its working without any issue. However, when I hosted it in IIS (AWS EC2 environment). It started behaving very weird. If the application's bindings is stick to default. I can browse it in the server using http://localhost:26943/ with no issue.
default bindings
However, when i change the bindings to hostname and browse using http://testing.com/, I found that the session containing user ID is empty.
hostname bindings
I have tried several methods including :
Add Session["init"] = 0 in Global.asax
Change cookieless=true in web.config
Change sessionState's mode to "StateServer"
Redirect to "~/page.aspx" instead of "page.aspx"
Only change cookieless method worked for me but it will show session ID in the URL which I doubt is the correct method.
Details of app:
.NetFramework 4.8
Uses WCF service
Current session state info is sessionState mode="InProc" cookieless="false" timeout="60"
Configured c:\Windows\System32\Drivers\etc\hosts to add 127.0.0.1 testing.com
Tested using IE 11
Since AWS is on a server farm?
Then in-proc sessions are going to be VERY flakey and problematic. Those massive cloud systems will spool out your web server multiple times - a WILD guess as to where the next page will come from. If pages are served across different instances of the IIS server?
You going to lose session values. As noted, even some un-handled code errors will cause a app-pool re-set. All of these issues add up to easy and frequent loss of sessions.
I would suggest you adopt SQL server based session management. This should eliminate a zillion issues that can cause a session() re-set. I like in- proc. Memory based is fast, and since your not writing the next Facebook, then of course typical server loads are next to nothing (again, this favors use of in-proc sessions). However, since you a have server farm, and some application errors will become problematic? Adopt SQL server based sessions, and 99 if not 100% of your session() re-sets and loss will go away.
this suggestion is MUCH more warranted since you using AWS and you have little control over the VM's they run and their behind the scenes "fabric" controller could for fail safe and redundancy issues be running multiple copies of your server. So, adopt SQL based session management.
HttpContext.Current.Session["myvariable"]
I am going through a tutorial in ASP.Net MVC 5 and I learned about caching. But I could not understand what determines whether I should cache at client or server.
Here is the code snippet.
For client:
[OutputCache(Duration = 86400, Location = OutputCacheLocation.Client)]
public ActionResult SelectLocation()
{
}
For server:
[OutputCache(Duration = 86400, Location = OutputCacheLocation.Server)]
public ActionResult SelectLocation()
{
}
Question: Can someone tell me when I should apply client caching and when should I use the server one. And the downside or any consequences I should look for?
In regards to OutputCache, "client" caching simply means that cache-control headers and/or an expires header will be sent with the response, indicating that the client may cache the document. Typically, the client, especially if it's a web browser, will choose to do so. It then will not need to make a new request if the same resource is needed again. However, the browser may still occasionally make a HEAD request just to check if there's a new version of the resource.
"Server" caching means, still in regards to OutputCache, that the server will cache the response locally, usually in memory. This means that as long as the cache is still valid, the server will not actually render the action again, but rather, will just serve up the cached resource, instead.
The main difference, then, between the two is that the server cache will be used for all requests for that resource, regardless of what client is currently making the request, while client cache will obviously just be limited to that one particular client. The server will not need to render the action again for that client, but will for the next client that comes along.
However, the default is Any, which includes server and client caching (as well as other locations). In other words, server and client caching are not mutually exclusive, and usually you'd do both to minimize both the work the server needs to do and the amount of requests it needs to respond to.
Have a look here. It is very nicely explained
By default, content is cached in three locations: the web server, any proxy servers, and the user's browser. You can control the content's cached location by changing the location parameter. When you cache on the server, every user receives the same content and when it is only client side, the cached content differs by users.
The location parameter has the default value Any which is appropriate for most the scenarios. But some times there are scenarios when you required more control over the cached data.
Suppose you want to cache the logged in use information then you should cached the data on client browser since this data is specific to a user. If you will cached this data on the server, all the user will see the same information that is wrong.
You should cache the data on the server which is common to all the users and is sensitive.
One point of view could by the cache invalidation scenario. When caching on the client side, you'd need to adjust the URL the client hits to avoid cache hit / force recalculation of response. When caching on the server side, you might invalidate the cached content easier. See this question: How to programmatically clear outputcache for controller action method
As described in https://msdn.microsoft.com/en-us/library/system.web.ui.outputcachelocation(v=vs.110).aspx
Client will instruct browser to cache html in it's own cache.
Pros: faster since it is cached on browser, does not take up server memory.
Cons: it is dependable on user browser settings (cache size, expiration etc.) and user can delete on it's own
Server will keep cached html on server
Pros: does not depend on browser rules since it sends no-cache, you control the cache, not user.
Cons: slower then client since it will always include transport, takes up server memory
The reason that there are a variety of options when dealing with cache control is simple; there is no universal correct answer that is applicable to all sites.
A "business card" site that is pretty static in it's design and content as well as being the only site on the server could pretty much be set to cache it everywhere for an infinite time period. However, if that server is actually hosting a thousand sites then we start have to worry about the server cache and its viability because IIS will start dumping cache items if the memory gets low, so we may not want that server cache.
If we have an ecomm site that is very high traffic with product changes and additions on an hourly basis, we would want to reduce the max-age so that the content remains up to date. But then again, the content generation for these more demanding applications can slow the server down due to all of the dynamic content processing, especially if this site is on a shared server.
There are plenty of resources on the general internet, MSDN, and here that you can review to help you determine on what is best for you. With the wide variety of sites that I have worked with in single and shared environments I have most as Server and client locations, some will use the Last-Modified header and others use eTag.
I'm new working with files so i have done some reading, altough i feel that i'm still not certain how to deal with them using asp.net web api.
What i want is to be able to reach images thru my web api. What i've read so far is that many people prefer saving the file and then call for its URI, instead of saving the image to the database u only save the URI there. So I then created a imageController on the web api that does exactly this(Atleast working using localhost). I now get some people arguing that i should use blob storage(since i use Azure).
My question is: Is it wrong or bad practice to have a folder in my project where i save my image files? Else what would be the better way to save images?
Your question is really two questions:
1. database vs. filesystem
It depends on 2 main factors: security and performance.
If your images are sensitive and the risk of accessing them "outside" your app (for example by hotlinking) is unacceptable, you must go for database, and serving images via ASP.NET request - which you can authenticate any way you want. However, this is MUCH more resources-intensive than second option (see below).
If security is no concern, you definitely want to go for filesystem storage. On traditional hosting, you would save them "anywhere" on disk, and the IIS (the webserver) would serve them to user (by direct URL, bypassing your ASP.NET application). This alone is HUGE performance improvement over DB+ASP.NET solution for many reasons (request thread pool, memory pressure, avg. request duration, caching on IIS...).
2. Local directory on webrole vs. blob storage
However, in Azure you can, and HAVE TO go one step further - use dedicated blob storage, independent from your web role, so not even your IIS on webrole will be serving them, but dedicated server on blob storage (this does not need to concern you at all - it just works). Your web role should not store anything permanently - it can fail, be destroyed and replaced with new one at any time by Azure fabric. All permanent stuff must go to Azure blob storage.
Adding to #rouen's excellent answer (and I will focus only on local directory v/s blob storage).
Assuming you're deploying your WebApi as an Azure Web Application (instead of Web Role), consider the following scenarios:
What would happen to your images if accidentally you delete your Web Application. In that case, all your images will be lost.
What would happen if you need to scale your application from one instances to more than one. Since the files are located in instances local directory, they will not be replicated across other instances. If a request to fetch the image lands on an instance where the image is not present on the VM, then you will not be able to serve that image.
What would happen if you need to store more images than the disk size available to you in your web application?
What would happen if you need to serve the same images through another application (other than your WebApi)?
Considering all these, my recommendation would be to go with blob storage. What you do is store the image in blob storage and save the image URL in the database. Some of the advantages offered by blob storage are:
At this time, you can store 500 GB worth of data in a single blob storage account. If you need more space, you simply create another storage account. Currently you can create 100 storage accounts per subscription so essentially you can store 50TB worth of data in a single subscription.
Blob storage is cheap and you only pay for the storage that you use + storage transaction costs which are also very cheap.
Contents in blob storage are replicated thrice and if you opt for geo-redundancy option (there's an extra cost for that), your content is replicated six time (three times in primary region + three times in secondary region). However you should not confuse replication with backup!
Since the content is served from blob storage, you're essentially freeing up IIS server from serving that content.
You can take advantage of Azure CDN and serve the content from a CDN node closest to your end user.
Considering all these advantages, I would strongly urge you to take a look at blob storage.
I'm serving pages using MVC5 and getting data from WebApi services. The MVC5 app makes around 60 requests to the WebApi initial page load to get all the data, I'm using OutputCache on the MVC5 side.
This works until the cache expires. When the Output cache expires new calls to the API are triggered, since theres a lot of people using the site the first request won't finish before subsequent requests are made. This means that suddenly our data service has to cope with a huge load. Say that a 100 new visitors come in then the backend receives approximately 6000 requests, of which most include database calls and some requests to other services. Response times get longer and eventually the WebApi tier crashes.
Are there any methods I can apply to cope with this sudden increase in requests? I've considered adding another layer of caching on the WebApi side but would like to know if theres more that can be done.
My two cents here will be suggesting you that, maybe, it's the time to implement a second-level cache mechanism.
Instead of delegating everything to the ASP.NET output cache, you should have cached data in a neutral layer between your front-end and Web API backend which may be updated overtime and asynchronously. That is, users won't get the performance impact of refreshing the whole cache.
If you want to learn more about this topic, some question was thrown in Meta StackExchange and a developer from StackExchange was proud to share with everyone how they implemented caching (either L1 and L2 cache).
I think a sliding expiry cache could help. But I think you'll need to either go third party or create your own attribute for that.
Maybe this can help some:
Asp.net Mvc OutputCache attribute and sliding expiration
I am writing an MVC webAPI that will be used to return values that will be bound to dropdown boxes or used as type-ahead textbox results on a website, and I want to cache values in memory so that I do not need to perform database requests every time the API is hit.
I am going to use the MemoryCache class and I know I can populate the cache when the first request comes in but I don't want the first request to the API to be slower than others. My question is: Is there a way for me to automatically populate the cache when the WebAPI first starts? I see there is an "App_Start" folder, maybe I just throw something in here?
After the initial population, I will probably run an hourly/daily request to update the cache as required.
MemoryCache:
http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx
UDPATE
Ela's answer below did the trick, basically I just needed to look at the abilities of Global.asax.
Thanks for the quick help here, this has spun up a separate question for me about the pros/cons of different caching types.
Pros/Cons of different ASP.NET Caching Options
You can use the global.asax appplication start method to initialize resources.
Resources which will be used application wide basically.
The following link should help you to find more information:
http://www.asp.net/web-forms/tutorials/data-access/caching-data/caching-data-at-application-startup-cs
Hint:
If you use in process caching (which is usually the case if you cache something within the web context / thread), keep in mind that your web application is controlled by IIS.
The standard IIS configuration will shut down your web application after 20 minutes if no user requests have to be served.
This means, that any resources you have in memory, will be freed.
After this happens, the next time a user accesses your web application, the global asax, application start will be excecuted again, because IIS reinitializes your web application.
If you want to prevent this behaviour, you either configure the application pool idle timeout to not time out after 20minutes. Or you use a different cache strategy (persistent cache, distributed cache...).
To configure IIS for this, here you can find more information:
http://brad.kingsleyblog.com/IIS7-Application-Pool-Idle-Time-out-Settings/