Instant Azure Caching with MVC

Rick_Anderson

Warning. This is obsolete, see my new blog

MVC movie app with Azure Redis Cache in 15 minutes

Warning: Most of the information in this blog is for the Preview edition and should not be used or targeted for production code. Use the In-Role Cache for production code.

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.

details

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-fast Local 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. You can create a cache from 128MB to 150 GB. I’ll show how to do that later in this tutorial.
  • Works with every cloud product. Use the same cache from worker roles, web roles, web sites, VMs (even Linux VMs).
  • Huge. You can create caches from 128MB all the way to 150 GB.
  • **Reliable, high availability. **I’ll show how to hook up session cache, restart the web site and show session data is preserved. No more need to set up session affinity.
  • 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, Increment Decrement APIs, Append Prepend 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

  1. Log into the Windows Azure portal, and click the New button on the bottom left of the screen.

    New

  2. Click Data Services, Cache, and then Quick Create.

    QuickCreate 

  3. 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.

    endPt

    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.

ConfigCache

Each time a cache item is accessed, the 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

  1. 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.

    NuGet 

  2. In the Select Projects **dialog click **OK and then click Install.

  3. Open the root web.config file and find the <dataCacheClients> element at the bottom of the file.
  4. 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 identifierattribute of the <autoDiscover> element.
  5. 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:

    webCon

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 time that data is requested. 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);
         <mark> cache.Put(id.ToString(), movie);</mark>
         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.

Note: Latency between your desktop and the cloud service cache will be high because your desktop must access the cache service in the cloud. When your web app is located in the same region as the cache service, latency will be very low, in the one millisecond range.

Configure Local Cache

In the root Web.config  file, find the element and remove the comment characters. Local Cache, an ultra-fast second level cache stores cached items locally (in the memory of your web site or cloud service instance so there are no network hops or deserialization costs). Local Cache is hundreds of times faster than the cache service, reducing latency to the .01 millisecond range. Local Cache is not synchronized with the cache, so it shouldn’t be used where you need exact data values. However you can register for notifications to update the local cache at regular intervals from the cache cluster. Deploy the updated application and you will notice cache hits are now in the .01 millisecond range.

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.

monitor

Click the Add Metrics button on the bottom of the portal page to add additional metrics.

image_thumb_1FB46D89

 

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, and other apps 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 <sessionState> and <caching>elements inside the  <system.web> element. The following code shows the uncommented markup inside the <system.web> element:

  <system.web>
    <customErrors mode="Off"/>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  <!-- Windows Azure Cache session state provider -->
     <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>
     <!-- Windows Azure Cache output cache provider --><!--Uncomment this section to use Windows Azure Cache for output cache-->
     <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.

ws

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.

rs

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. To enable compression, add the isCompressionEnabled attribute to the element:

<dataCacheClients>
    <
dataCacheClient name=defaultisCompressionEnabled=true>
    

</
configuration>

* 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 is always distributed across all the nodes in the cluster, so you don’t need to create multiple named caches to distribute your data.

Follow me ( @RickAndMSFT )  on twitter where I have a no spam guarantee of quality tweets.

Resources:

Windows Azure Cache Extension Library WACEL implements high-level data structures that can be shared among your services and application. You can use WACEL data structures just as if you were using local data structures such as arrays, tables, circular buffers and OLAP cubes, and these data structures are backed by Windows Azure Cache, Windows Azure Table Storage, or both.

Microsoft Patterns and Practices – Windows Azure Guidance. See Caching guidance and Cache-Aside pattern.

0 comments

Discussion is closed.

Feedback usabilla icon