In this blog post I’ll take my MVC Movie app and in 15 minutes connect it to the preview Windows Azure Cache service. The image below shows the details of a movie along with timing data (1.4 milliseconds), cache status (Hit in this case) and the PID of the IIS server.
You can download the completed app here. Later in the tutorial we’ll use the PID to show the session cache preserves data across web site failovers.
Features
- Fast! Cache read access is typically in the 1 millisecond range, writes about 1.2 millisecond for the premium cache. The basic and standard caches are not quite that fast, but do provide a major speedup over typical database access (which is often in the hundreds to thousands of millisecond range.)
- Ultra-fastLocal Cache - about 100 times faster than cache access. Local Cache is great in applications like the movie app or weather apps that can use recent data. I’ll show how easy this is to configure.
- Easy to set up, configure and use in your app. I’ll show how to do that later in this tutorial.
- Low cost. A cache can provide a cost effective approach to speeding up your app. See the Capacity Planning Guide spreadsheet for Windows Azure Caching.
- Multiple named caches, high availability, local cache, notifications, regions, tags, IncrementDecrement APIs, AppendPrepend APIs, Cache level BulkGet operations, expiration and eviction, and more. See What's new in Windows Azure Caching for details.
Set up the app to use Azure caching
Create a cache on the Windows Azure portal
- Log into the Windows Azure portal, and click the New button on the bottom left of the screen.
- Click Data Services, Cache, and then Quick Create.
- Enter an Endpoint and a region near you (where your web site will run). In this sample we'll use the basic 128 MB cache.
You can use the Capacity Planning Guide spreadsheet for Windows Azure Caching to help you determine the appropriate cache size, performance and features for your application.
Configure the cache
Select the Configure tab for Cache in the Management Portal. Each cache has a default named cache, and the Standard and Premium cache offerings support up to nine additional named caches, for a total of ten. Each named cache has its own set of options which allow you to configure your cache in a highly flexible manner.
In the image below, the default cache is configured for a one minute sliding policy.
Each time a cache item is accessed, the one minute expiration clock is reset. Setting it to one minute makes it easy to test the app In the download example, each page shows the cache Hit or Miss status, so setting it to one minute makes it easy to show expirations. Cache aside algorithms generally use a sliding cache. You should configure the expiration for the longest period possible that doesn’t overflow the cache and force excessive evictions. When the cache memory is full, new additions to the cache force evictions of the oldest items in the cache (LRU), and you pay a minor penalty waiting to evict the oldest cache items to make room for the new items. You can stress test your app and use the Monitor tab to see what percent of the cache capacity the app is using. (Monitoring is shown later in the tutorial.)
Configure the MvcMovie app for caching
- Use NuGet to install the Windows Azure Cache package. Select Online in the left tab and enter caching in the search box on the top right. Click the Install button for the Windows Azure Cache package.
- In the Select Projects dialog click OK and then click Install.
- Open the root web.config file and find the
element at the bottom of the file. - In the Windows Azure portal, copy the name of the Endpoint URL (fixitcache.cache.windows.net in the images above) and paste it into the
identifier
attribute of the
element. - Remove the comment characters from the
element and paste in the authentication key. You can get the key from the portal by clicking on Manage Keys when you've selected your cache. The code below shows the markup you must change:
On Demand/ Cache Aside code
There are many cache approaches you can take depending on your application needs. For this sample I’ll use the on demand/cache aside approach. Each query for a movie or list of movies first searches the cache. If the data is found in the cache, it’s immediately returned without banging on the database. If the requested data is not in the cache, it uses the normal data access code, but then caches the data for the next request. The following shows the getMovie method which is called by the Details, Edit and Delete action methods.
public class MoviesController : Controller{private MovieDBContext db = new MovieDBContext();private DataCache cache = new DataCache();Movie getMovie(int id) {Stopwatch sw = Stopwatch.StartNew();Movie m = (Movie)cache.Get(id.ToString());if (m == null) {Movie movie = db.Movies.Find(id); cache.Put(id.ToString(), movie); StopWatchMiss(sw);return movie; } StopWatchHit(sw);return m; }
When a movie is edited or deleted, it is evicted from the cache:
void ClearAllMoviesCache(int id = 0) {if (id > 0) { cache.Remove(id.ToString()); } cache.Remove("All Movies"); }
Note the code above also clear out the cache entry “All Movies”, which contains a list of all the movies and is used in the Index method.
Download and run the sample
Download and configure the sample using the instructions above. You must create a web site with a database. For instructions on deploying a web site with a database, see my tutorial Deploy a Secure ASP.NET MVC 5 app with Membership, OAuth, and SQL Database to a Windows Azure Web Site.
The app is configured to display timing and cache status on each page.
Configure Local Cache
In the root Web.config file, find the
Monitor the Cache
From the portal, click on a cache endpoint, then click Monitor. The image below shows the cache usage data over the last hour. Note the read/write requests per second are in units of a 1,000.
ASP.NET session state using a cache provider
While it’s considered a best practice is to avoid using session state, some applications can actually have a performance/complexity benefit from using some session data, other app require session state. The default in memory provider for session state does not allow scale out (running multiple instances of the web site). The ASP.NET SQL Server session state provider will allow multiple web sites to use session state, but it incurs a high latency cost compared to an in memory provider. The ASP.NET session state cache provider is a low latency alternative that is very easy to configure and set up. If your app uses only a limited amount of session state, you can use most of the cache for caching data and a small amount for session state.
Configuring the ASP.NET session state cache provider
You must install the Windows Azure Cache package using NuGet (see the instructions earlier in this tutorial). In the Web.config file, remove the comments from the
and
elements inside the
element. The following code shows the uncommented markup inside the
element: <system.web><customErrors mode="Off"/><compilation debug="true" targetFramework="4.5" /><httpRuntime targetFramework="4.5" /><sessionState mode="Custom" customProvider="AFCacheSessionStateProvider"><providers><add name="AFCacheSessionStateProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheSessionState"/>providers>sessionState><caching><outputCache defaultProvider="AFCacheOutputCacheProvider"><providers><add name="AFCacheOutputCacheProvider" type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheOutputCache" />providers>outputCache>caching>system.web>
The sample download provides an easy mechanism to test session state is preserved on web site fail over. Run the download sample an click the Write Session button. You can optionally add route data to the session in the URL, such as Movies/WriteSession/MyTestSessionData.
Click on the Read Session tab to read the session data. Now stop and restart the web site. (You can do this from the portal or from Visual Studio). Refresh the page or click the Read Session tab and you’ll see the PID has changed.
See Session State Provider for more details. Erez Benari has a great blog on Disabling ARR’s Instance Affinity in Windows Azure Web Sites to allow you to use session state with multiple web sites, but with that approach, when a web site or host is updated, the load balancer sends subsequent requests to a new web site and all session data will be lost. If you app doesn’t use much session state and you’re using the already using the cache, you can get reliable and fast session state for practically free with the cache Session State Provider.
Caching Tips
- For large objects, use protobuf-net, Migrant, MessagePack or another fast and flexible serialization framework.
- Objects larger than 8MB should first be compressed or split up.
- The default the cache algorithm is well distributed, you don’t need to manage it in your code, or worry about regions/named caches.
- A region puts all the objects into a single instance which is useful for scenarios that need to keep related objects together (for example, you could have a region per user and keep multiple user objects user in a user region. Using regions allows you to bulk-query very efficiently. If you aren’t using bulk operations or getting tagged objects from the cache, you don’t need to create regions.
- A single named cache on is always distributed across all the nodes in the cluster, so you don’t need to create multiple named caches to distribute your data.
Let me know how you like this sample and what cache features I should add for the next version.
Follow me ( @RickAndMSFT ) on twitter where I have a no spam guarantee of quality tweets.