Use AppFabric Cache to cache your WCF Service response

Listen with webReader
Published 12 September 10 08:33 PM | wmmihaa

[This post has been updated to support InvokeBegin and InvokeEnd to support BizTalk Receive Locations]

We’ve just finished the “BizTalk Release Party” in Stockholm, where Stephen W. Thomas, Richard Seroter and Ewan Fairweather held some fantastic sessions. One of the talks was about the AppFabric Cache formally known as “Velocity”.

Whenever I come across a new technology I try to put it in some useful context, where I can try it out. This is usually a quite painful process, as I tend to do this long before the technology has reached any sort of mature state. AppFabric Cache is a v1 product and therefore considerable more stable then other products or technologies I’ve been experimenting with.

While Ewan was presenting the Windows Server AppFabric Cache I though it could be interesting to use it for caching outgoing WCF service responses, so that the back-end logic would not be executed if it was cached. I’m not sure how useful this scenario really is, but I guess there could be many scenarios where it would be ok not to get the latest version of the information. Some of those situations might be:

  • Where the information is accessed during office hours, and only updated through nightly batches.
  • Where a composite service get bursts of calls that would often be the same.
  • When services expose static data which will seldom change over time.

In my sample I’ll use a fictitious Weather Forecast Service, which I think would qualify as good candidate because:

  • Nobody trust the weather forecasts in the first place, so it doesn’t matter if the result not 100% up to date.
  • The service is frequently called with the same input parameters (Zip code).
  • The service will support a very popular IPhone Windows 7 Mobile application, which in turn will cause an immense load on our back-end systems.

 image

 

How it works:

WCF: The incoming call from the client is received through the Transport channel, after which it will proceed through an encoder and possible some other channels before it reaches the Dispatcher.

The Dispatcher is the last step before the request is handed over to the actual service. The Dispatcher is responsible for associating the incoming call with the appropriate operation and then invoking it. 

By creating a custom OperationInvoker you may customize the behavior of how the back-end logic is invoked. 

 
image

Windows Server AppFabric Cache provides distributed caching over many servers. It can utilize a cluster of servers that communicate with each other to form a single, unified application cache system. It comes with a decent API, and can be managed using PowerShell.

Solution:

The Visual Studio solution has  three projects:

Project Description
bLogical.CachingExtension This is the main project, responsible for the custom behavior.
bLogical.WcfWeatherService A WCF service application, applying the CacheOperationBehavior attribute to indicate the response of the method should be cached if possible. The service makes a call to a database to pickup the forecast.
bLogical.Client Client tool calling the two services.

 

The cache implementation:

Using the Windows Server AppFabric Cache is pretty straight forward. I recommend you read Scott Hanselman’s post on the subject. The post also covers the installation process.

Basically you use the DataCashe.Put method to add the data to the cache, and the DataCache.Get method to retrieve the cached value. Working with the Windows Server AppFabric Cache is similar to using a HashTable, where you add values along with a key (string) which you can later use to get the value back. 

 

public object Invoke(object instance, object[] inputs, out object[] outputs)
{
// Serialize all input parameters. The string will be used as the Key to the Cache.
string input = GetSerializedKey(inputs);

// Return value from the Method
object value= this._cacheHelper.Cache.Get(input);

if (value != null)
{
outputs = new object[0];
return value;
}
else
{
//Invoke the method
value = this._innerOperationInvoker.Invoke(instance, inputs, out outputs);

// Add the return value to the Cache.
this._cacheHelper.Cache.Put(input, value, new TimeSpan(0,0,0,0,this._timeOut));

return value;
}
}

 

I use the input parameters as Key. But as the parameters can be any number of objects, I need to serialize them into an XML string first. I can then use the string as key together with the result from the invoked method. As I don’t want the value to be cached forever, I also pass in a TimeSpan to indicate the lifetime of the cached object.

Using the caching behavior:

You can use the cache behavior either declaratively in your code:

[ServiceContract]
public interface IWeatherForecastService
{
[CacheOperationBehavior(TimeOut=2000)]
[OperationContract]
Forecast GetForecast(string zipCode);
}

…or through configuration:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<cachingBehavior timeout="00:10:00" cacheName="bLogical"/>
</behavior>
</serviceBehaviors>
</behaviors>

<extensions>
<behaviorExtensions>
<add name="cachingBehavior"
type="bLogical.CachingExtension.CacheElement, bLogical.CachingExtension,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=49c05550fea0c875"
/>
</behaviorExtensions>
</extensions>
</system.serviceModel>

 

Performance:

I’ve run two tests; One with and one without caching enabled. I haven’t got time to run this in any real test environment. But even though I’ve run the test on my local laptop, the tests came out pretty clear.

Without Caching (~3 calls/sec):

image

(Using Visual Studio profiler, I found the database call to take ~200ms)

With Caching (~23 calls/sec):

image

 

Download and install:

1. Download the Windows Server AppFabric.

2. Read Scott Hanselman’s post as to how to set it up.

3. Open PowerShell and run the following commands:

get-command -module DistributedCacheConfiguration

First you need to grant access to your service account:
Grant-CacheAllowedClientAccount [Your Account]
Continue to create the Cache:

New-Cache bLogical

Start the cluster:

Start-CacheCluster 

4. Download the sample

 

Using it with BizTalk:

Follow these steps to use the bLogical.CachingExtensions with BizTalk:

  1. Add a key to the bLogical.CachingExtensions project.
  2. Build the project and add it to the GAC.
  3. Open machine.config and add the extension to the behaviorExtensions section.
  4. Open BizTalk Administration Console
  5. Add a Request/Response ReceivePort > Add a Location
  6. Set the transport to WCF-Custom, and click configure
  7. Set the URI and Binding.
  8. On the Behavior tab, add a ServiceBehavior and select the CacheElement:

image

 

HTH

Comments

# Twitter Trackbacks for Use AppFabric Cache to cache your WCF Service response - Mikael H??kansson [blogical.se] on Topsy.com said on September 13, 2010 07:26 AM:

Pingback from  Twitter Trackbacks for                 Use AppFabric Cache to cache your WCF Service response - Mikael H??kansson         [blogical.se]        on Topsy.com

# Use AppFabric Cache to cache your WCF Service response – Mikael … « cache said on September 13, 2010 02:04 PM:

Pingback from  Use AppFabric Cache to cache your WCF Service response &#8211; Mikael &#8230; &laquo;  cache

# Use AppFabric Cache to cache your WCF Service response – Mikael … « cache said on September 13, 2010 02:04 PM:

Pingback from  Use AppFabric Cache to cache your WCF Service response &#8211; Mikael &#8230; &laquo;  cache

# Scott Banwart's Blog » Blog Archive » Distributed Weekly 68 said on September 17, 2010 03:30 PM:

Pingback from  Scott Banwart&#039;s Blog  &raquo; Blog Archive   &raquo; Distributed Weekly 68

# A Configurable AppFabric Cache Attribute For Your WCF Services | cmmsft said on November 29, 2010 09:11 PM:

Pingback from  A Configurable AppFabric Cache Attribute For Your WCF Services | cmmsft

# Windows Server AppFabric Customer Advisory Team said on November 30, 2010 05:40 PM:

Doing a search online for WCF and Cache will eventually lead you to a number of links* demonstrating

# Stephen W. Thomas BizTalk MVP said on January 10, 2011 08:18 PM:

In the recent edition of The BizTalker Newsletter I featured the below article.&#160; Read the article

# AppFabric CAT | A Configurable AppFabric Cache Attribute For Your WCF Services said on January 28, 2011 08:47 PM:

Pingback from  AppFabric CAT | A Configurable AppFabric Cache Attribute For Your WCF Services

# BiztalkOntwikkelaar said on February 1, 2011 03:38 AM:

In the recent edition of The BizTalker Newsletter I featured the below article.&#160; Read the article

# jarlross said on April 4, 2011 04:12 AM:

hello,

I can not gac the bLogical dll by any means and thus I do not see the cacheBehaviour extension??

# wmmihaa said on April 4, 2011 11:21 AM:

jarlross - What is the problem with gacing the assembly? Do you get any exeptions?

# Paolo Salvatori's Blog said on April 6, 2011 01:48 PM:

Introduction A couple of months ago Yossi Dahan told me that one of his customers in the UK was searching

# Jaime Bula said on May 13, 2011 04:23 PM:

Hi!

I saw that the header has  

[CacheOperationBehavior(TimeOut = new TimeSpan(0,0,10), CacheName="bLogical")]

But TimeSpan isn't a valid data type for attributes.

It is my understanding that the supported data types are bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, or ushort.

So the solution doesn't build in VS 2010. Any suggestion?

# How to use a WCF custom channel to implement client-side caching | AppFabric CAT said on June 28, 2011 12:14 PM:

Pingback from  How to use a WCF custom channel to implement client-side caching | AppFabric CAT

# David Triana said on September 15, 2011 05:44 PM:

This code work great if there's differences between the input parameters for the call, however if there's no diferences or if there's no parameters then it fails because the key for the cache is based only in the input.

I solved it by adding a string parameter in the invoker. That parameter is populeted in the behavior with the namespace, service name and operation name, then I use that string as part of the string that finally build the key. It works great now.

# David's Blog said on September 15, 2011 07:18 PM:

Using Windows AppFabric Cache with WCF

# David's Blog said on September 15, 2011 07:51 PM:

Using Windows Server AppFabric Cache with WCF

# Using Windows Server AppFabric Cache with WCF « David's Blog said on May 17, 2012 09:12 PM:

Pingback from  Using Windows Server AppFabric Cache with WCF &laquo; David&#039;s Blog

# Using Windows Server AppFabric Cache with WCF « David's Blog said on May 17, 2012 09:12 PM:

Pingback from  Using Windows Server AppFabric Cache with WCF &laquo; David&#039;s Blog

This Blog

News

    MVP - Microsoft Most Valuable Professional BizTalk User Group Sweden BizTalk blogdoc

    Follow me on Twitter Meet me at TechEd

    Visitors

    Locations of visitors to this page

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Syndication