Getting Started with the Windows Azure Cache

Windows Azure has a great caching service that allows applications (whether or not they are hosted in Azure) to share in-memory cache as a middle tier service.  If you’ve followed the ol’ Velocity project, then you’re likely aware this was a distributed cache service you could install on Windows Server to build out a middle tier cache.  This was ultimately rolled into the Windows Server AppFabric, and is (with a few exceptions) the same that is offered in Windows Azure. The problem with a traditional in-memory cache (such as, the ASP.NET Cache) is that it doesn’t scale – each instance of an application maintains their own version of a cached object.  While this has a huge speed advantage, making sure data is not stale across instances is difficult.   Awhile back, I wrote a series of posts on how to do this in Windows Azure, using the internal HTTP endpoints as a means of syncing cache. On the flip side, the problem with building a middle tier cache is the maintenance and hardware overhead, and it introduces another point of failure in an application.  Offering the cache as a service alleviates the maintenance and scalability concerns. The Windows Azure cache offers the best of both worlds by providing the in-memory cache as a service, without the maintenance overhead.   Out of the box, there are providers for both the cache and session state (the session state provider, though, requires .NET 4.0).  To get started using the Windows Azure cache, we’ll configure a namespace via the Azure portal.  This is done the same way as setting up a namespace for Access Control and the Service Bus: Selecting new (upper left) allows you to configure a new namespace – in this case, we’ll do it just for caching: Just like setting up a hosted service, we’ll pick a namespace (in this case, ‘evangelism’) and a location.  Obviously, you’d pick a region closest to your application.  We also need to select a cache size.  The cache will manage its size by flushing the least used objects when under memory pressure.  To make setting up the application easier, there’s a “View Client Configuration” button that creates cut and paste settings for the web.config: In the web application, you’ll need to add a reference to Microsoft.ApplicationServer.Caching.Client and Microsoft.ApplicationServer.Caching.Core.  If you’re using the cache for session state, you’ll also need to reference Microsoft.Web.DistributedCache (requires .NET 4.0), and no additional changes (outside of the web.config) need to be done.  For using the cache, it’s straightforward: using (DataCacheFactory dataCacheFactory = new DataCacheFactory()){ DataCache dataCache = dataCacheFactory.GetDefaultCache(); dataCache.Add("somekey", "someobject", TimeSpan.FromMinutes(10));} If you look at some of the overloads, you’ll see that some features aren’t supported in Azure: That’s it!  Of course, the big question is:  what does it cost?  The pricing, at the time of this writing, is: Standard pay-as-you-go pricing for caching 128 MB cache for $45.00/mo 256 MB cache for $55.00/mo 512 MB cache for $75.00/mo 1 GB cache for $110.00/mo 2 GB cache for $180.00/mo 4 GB cache for $325.00/mo One additional tip:  if you’re using the session state provider locally in the development emulator with multiple instances of the application, be sure to add an applicationName to the session state provider: <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider"> <providers> <add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="default" applicationName="SessionApp"/> </providers></sessionState> The reason is because each website, when running locally in IIS, generates a separate session identifier for each site.  Adding the applicationName ensures the session state is shared across all instances. Happy Caching!

Distributed Cache in Azure: Part III

It has been awhile since my last post on this … but here is the completed project – just in time for distributed cache in the Azure AppFabric!  : )  In all seriousness, even with the AppFabric Cache, this is still a nice viable solution for smaller scale applications. To recap, the premise here is that we have multiple website instances all running independently, but we want to be able to sync cache between them.   Each instance will maintain its own copy of an object in the cache, but in the event that one instance sees a reason to update the cache (for example, a user modifies their account or some other non-predictable action occurs), the other instances can pick up on this change.  It’s possible to pass objects across the WCF service however because each instance knows how to get the objects, it’s a bit cleaner to broadcast ‘flush’ commands.  So that’s what we’ll do.   While it’s completely possible to run this outside of Azure, one of the nice benefits is that the Azure fabric controller maintains the RoleEnvironment class so all of your instances can (if Internal Endpoints are enabled) be aware of each other, even if you spin up new instances or reduce instance counts. You can download this sample project here:     When you run the project, you’ll see a simple screen like so: Specifically, pay attention to the Date column.  Here we have 3 webrole instances running.  Notice that the Date matches – this is the last updated date/time of some fictitious settings we’re storing in Azure Storage.    If we add a new setting or just click Save New Settings, the webrole updates the settings in Storage, and then broadcasts a ‘flush’ command to the other instances.  After clicking, notice the date of all three changes to reflect the update: In a typical cache situation, you’d have no way to easily update the other instances to handle ad-hoc updates.  Even if you don’t need a distributed cache solution, the code base here may be helpful for getting started with WCF services for inter-role communication.  Enjoy!

Distributed Cache in Azure: Part II

In my last post, I talked about creating a simple distributed cache in Azure.   In reality, we aren’t creating a true distributed cache – what we’re going to do is allow each server manage its own cache, but we’ll use WCF and inter-role communication to keep them in sync.   The downside of this approach is that we’re wasting n* more RAM because each server has to maintain its own copy of the cached item.   The upside is:  this is easy to do. So let’s get the obvious thing out the way.  Using the built in ASP.NET Cache, you can add something to the cache like so that inserts an object that expires in 30 minutes: 1 Cache.Insert("some key", 2 someObj, 3 null, 4 DateTime.Now.AddMinutes(30), 5 System.Web.Caching.Cache.NoSlidingExpiration); With this project, you certainly could use the ASP.NET Cache, but I decided to you use the Patterns and Practices Caching Block.  The reason for this:  it works in Azure worker roles.  Even though we’re only looking at the web roles in this example, it’s flexible enough to go into worker roles, too.  To get started with the caching block, you can download it here on CodePlex.  The documentation is pretty straightforward, but what I did was just set up the caching configuration in the web.config file.  For worker roles, you’d use an app.config: 1 <cachingConfiguration defaultCacheManager="Default Cache Manager"> 2 <backingStores> 3 <add name="inMemory" 4 type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching" /> 5 </backingStores> 6 7 <cacheManagers> 8 <add name="Default Cache Manager" 9 type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching" 10 expirationPollFrequencyInSeconds="60" 11 maximumElementsInCacheBeforeScavenging="250" 12 numberToRemoveWhenScavenging="10" 13 backingStoreName="inMemory" /> 14 </cacheManagers> 15 </cachingConfiguration> The next step was creating a cache wrapper in the application.  Essentially, it’s a simple static class that wraps all the insert/deletes/etc. from the underlying cache.  It doesn’t really matter what the underlying cache is.  The wrapper is also responsible for notifying other roles about a cache change.   If you’re a purist, you’re going to see that this shouldn’t be a wrapper, but instead be implemented as a full fledged cache provider since it isn’t just wrapping the functionality.   That’s true, but again, I’m going for simplicity here – as in, I want this up and running _today_, not in a week. Remember that the specific web app dealing with this request knows whether or not to flush the cache.  For example, it could be a customer updates their profile or other action that only this server knows about.  So when adding or removing items from the cache, we send a notify flag that instructs all other services to get notified… 1 public static void Add(string key, object value, CacheItemPriority priority, 2 DateTime expirationDate, bool notifyRoles) 3 { 4 _Cache.Add(key, 5 value, 6 priority, 7 null, 8 new AbsoluteTime(expirationDate) 9 ); 10 11 if (notifyRoles) 12 { 13 NotificationService.BroadcastCacheRemove(key); 14 } 15 } 16 17 public static void Remove(string key, bool notifyRoles) 18 { 19 _Cache.Remove(key); 20 21 if (notifyRoles) 22 { 23 Trace.TraceWarning(string.Format("Removed key '{0}'.", key)); 24 NotificationService.BroadcastCacheRemove(key); 25 } 26 } The Notification Service is surprisingly simple, and this is the cool part about the Windows Azure platform.  Within the ServiceDefinition file (or through the properties page) we can simply define an internal endpoint: This allows all of our instances to communicate with one another.  Even better, this all maintained by the static RoleEnvironment class.  So, as we add/remove instances to our app, everything magically works.  A simple WCF contract to test this prototype looked like so: 1 [ServiceContract] 2 public interface INotificationService 3 { 4 [OperationContract(IsOneWay = true)] 5 void RemoveFromCache(string key); 6 7 [OperationContract(IsOneWay = true)] 8 void FlushCache(); 9 10 [OperationContract(IsOneWay = false)] 11 int GetCacheItemCount(); 12 13 [OperationContract(IsOneWay = false)] 14 DateTime GetSettingsDate(); 15 } In this case, I want to be able to tell another service to remove an item from its cache, to flush everything in its cache, to give me the number of items in its cache as well as the ‘settings date’ which is the last time the settings were updated.  This is largely for prototyping to make sure everything is in sync. We’ll complete this in the next post where I’ll attach the project you can run yourself, but the next steps are creating the service and a test app to use it.    Check back soon!

Creating a Poor Man’s Distributed Cache in Azure

If you’ve read up on the Windows Server AppFabric (which contains Velocity, the distributed caching project) you’re likely familiar with the concepts of distributed cache.   Distributed caching isn’t strictly limited to web environments, but for this post (or if I ramble on and it becomes a series) we’ll act like it does.  In a web environment, session state is one of the more problematic server-side features to deal with in multiple server applications.   You are likely already familiar with all of this, but for those who aren’t:  the challenge in storing session state is handling situations where a user’s first request goes to one server in the farm, then the next request goes to another.   If session state is being relied upon, there are only a few options:  1) store session state off-server (for example, in a common SQL Server shared by all web servers) or 2) use “sticky” sessions so that a user’s entire session is served from the same server (in this case, the load balancer typically handles this).   Each method has pros and cons. Caching is similar.  In typical web applications, you cache expensive objects in the web server’s RAM.  In very complex applications, you can create a caching tier – this is exactly the situation Velocity/AppFabric solves really well.  But, it’s often overkill for more basic applications.   The general rule of thumb(s) with caching is:  1) caching should always be considered volatile – if an item isn’t in the cache for any reason, the application should be able to reconstruct itself seamlessly.  And 2) an item in the cache should expire such that no stale data retained.   (The SqlCacheDependency helps in many of these situations, but generally doesn’t apply in the cloud.) The last part about stale data is pretty tricky in some situations.  Consider this situation:  suppose your web app has 4 servers and, on the the home page, a stock ticker for the company’s stock.  This is fetched from a web service, but cached for a period of time (say, 60 minutes) to increase performance.    These values will quickly get out of sync – it might not be that important, but it illustrates the point about keeping cache in sync.  A very simple way to deal with this situation is to expire the cache at an absolute time, such as the top of the hour.  (But this, too, has some downsides.) As soon as you move into a more complicated scenario, things get a bit trickier.  Suppose you want to expire items from a web app if they go out of stock.   Depending on how fast this happens,  you might expire them based on the number in stock – if the number gets really low, you could expire them in seconds, or even not cache them at all.  But what if you aren’t sure when an item might expire?   Take Worldmaps … storing aggregated data is ideal in the cache (in fact, there’s 2 levels of cache in Worldmaps).  In general, handling ‘when’ the data expires is predictable.  Based on age and volume, a map will redraw itself (and stats updated) between 2 and 24 hours.   I also have a tool that lets me click a button to force a redraw.   When one server gets this request, it can flush its own cache, but the other servers know nothing about this.   In situations, then, when user interaction can cause cache expiration, it’s very difficult to cache effectively and often the result is just not caching at all. With all of this background out of the way, even though technologies like the SqlCacheDependency currently don’t exist in Azure, there are a few ways we can effectively create a distributed cache in Azure – or perhaps more appropriately, sync the cache in a Windows Azure project. In the next post, we’ll get technical and I’ll show how to use the RoleEnvironment class and WCF to sync caches across different web roles.  Stay tuned!

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List