Nov 25, 2011

Azure AppFabric Caching ASP.NET Session State Provider – not working with 2 Instances in the local Compute Emulator

 

A customer asked me for help about this.

Introduction

Windows Azure AppFabric Cache is a subset of the Windows Server 2008 R2 AppFabric distributed in-memory cache (aka “Velocity”) and typically provides it’s services for ASP.NET session provider and output caching.

Enable Cache

To speed up your web apps performance you first need to enable this Azure feature on the management portal

image

Click New Service Namespace –> select Cache –> select your Azure subscription (for the billing) –> the region of the data center –> and a name.

Configure Web App to use the cache

In the management portal Properties copy your host name and authentication token

image

image

to your web.config <Configuration> section:

<configSections>

  <section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere"/>

</configSections>

 

<dataCacheClients>

  <dataCacheClient name="default">

    <hosts>

      <host name="[SERVICE-HOST-NAME]" cachePort="22233" />

    </hosts>

    <securityProperties mode="Message">

      <messageSecurity

        authorizationInfo="[AUTHORIZATION INFO]">

      </messageSecurity>

    </securityProperties>

  </dataCacheClient>

</dataCacheClients>

 

<system.web>

 

  <sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">

    <providers>

      <add name="AppFabricCacheSessionStoreProvider"

            type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"

            cacheName="default"

            useBlobMode="true"

            dataCacheClientName="default" />

    </providers>

  </sessionState>

 

Add assembly references to the Azure libraries

Microsoft.ApplicationServer.Caching.Client.dll
Microsoft.ApplicationServer.Caching.Core.dll
Microsoft.Web.DistributedCache.dll
Microsoft.WindowsFabric.Common
Microsoft.WindowsFabric.Data.Common

2 Instances

Configure your web role to use 2 instances. Otherwise you won’t notice the problem.

Attention

Make sure, you do not confuse with the Windows Server 2008 R2 AppFabric caching libraries. Use the ones under

C:\Program Files\Windows Azure AppFabric SDK\V1.5\Assemblies\NET4.0\Cache

Access the cache from code

In the following example from the AppFabric Lab Samples, store some shopping cart entries into the session

List<string> cart = this.Session["Cart"] as List<string> ?? new List<string>();

cart.Add(selectedItem);

Session["Cart"] = cart;

and read back

var itemsInSession = this.Session["Cart"] as List<string> ?? new List<string>();

Test it

Now when I start the app and add a product to the cart, stop the compute emulator, do an iisreset.exe and refresh the page – then I still see the product. This now comes from the Azure AppFabric Cache:

image

on instance 1. From the debugger:

Checkout on instance deployment16(44).AzureStoreService.MVCAzureStore_IN_1

Pressing F5 to refresh the page again in the browser I suddenly don’t see the product anymore

image

on instance 0. From debugger

Checkout on instance deployment16(44).AzureStoreService.MVCAzureStore_IN_0

Pressing IEs F5 again and again, shows or don’t shows the product …. ?!?

Problem

So the findings are, that the session cache basically works, but not in a (load-balanced) multi-instance environment on the local development fabric compute emulator! Depending on the web role instance (0 or 1) a different session cache is used.

It looks like each web role instance is still using default ASP.NET in-proc session state, meaning you'd have different session state on each instance.

However, the session id is the same

image

I made sure the default in-proc session state provider is removed by commenting it and <clear/>ing the providers list:

<!--<sessionState mode="InProc" customProvider="DefaultSessionProvider">

  <providers>

    <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />

  </providers>

</sessionState>-->

<!-- If session state needs to be saved in AppFabric Caching service, add the following to web.config inside system.web. If SSL is required, then change dataCacheClientName to "SslEndpoint". -->

<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">

  <providers>

   <clear/>

    <add name="AppFabricCacheSessionStoreProvider"

          type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"

          cacheName="default"

          useBlobMode="true"

          dataCacheClientName="default" />

  </providers>

</sessionState>

All over again – it works in the Cloud

Not sure I did something wrong in the Lab sample – I started all over again from scratch with a simple app that stores the text box value into the Session[] state and reads it back using the buttons. Value/InstanceId/SessionID are written to the label below.

Same problem on the local fabric – BUT …

… storing from IE’s first tab the value “m5” to web role instance 0 in session 5WJJ:

image

Reading back from IE’s second tab the value “m5” from web role instance 1 in session 5WJJ:

image

gives me what I expected.

Help

As I understand this should not be the case? Seems to be an issue in the local compute emulator using the AppFabric cache service! It works in the cloud – but still makes local testing hard. Any ideas?

2 comments:

  1. local compute emulator does not actually use the 'live' appfabric cache. This is a minor bug with the emulator.

    Add the application name attribute to your web.config for the correct expected behaviour.

    eg

    ReplyDelete