DCSIMG
State Management in Cloud Applications - Manu Cohen-Yashar's Blog

Manu Cohen-Yashar's Blog

State Management in Cloud Applications

Cloud applications are distributed applications by design. There are many instances of roles located on different VMs and everything is load balanced. In Windows Azure there is no sticky load balancing so you can never know which role instance will serve your request. Such an environment introduces the challenge of state management. This is not a new challenge we know it from Asp.Net applications. Now in windows azure we find it everywhere – In web roles and worker roles.

When you create a object and save data in its member you want to keep working with the same object instance because your data is there. In a distributed applications it is not possible because objects instances cannot be shared across VMs.

So all state (information traditionally placed in object members) must be moved to a shared location. Somewhere all instances will have access to the data.

Azure storage is independent of Azure roles so it can function as a common place holder for state. Some data fit great in blobs or tables but usually it is not convenient to save simple data in Azure storage. saving objects in blobs requires serialization, persisting data in tables requires adding partition key and row key to every object.

Well … There one more option. Azure AppFabric Cache.
Azure AppFabric Cache is a distributed cache independent of Azure roles where you can persist objects (the only requirement on the objects is that they should be DataContract serializable) 

It is simple. It is scalable and safe. 
I wrote a little State Manager that I use in my Azure applications. Instead of saving state in my business objects I export it to this state manager.

/// <summary>

/// Provides a State management infrastructure for distributed stateless services which needs to save state (i.e. data)

/// The State management infrastructure is independent and distributed which allows the services to remain stateless.

/// This State management infrastructure is implemented using Azure AppFabric Distributed Cache.

/// </summary>

public static class StateManager

{

  private static DataCacheFactory CacheFactory;

  private static Dictionary<string,DataCacheLockHandle> lockHandle;

 

  static StateManager()

  {

    CacheFactory = new DataCacheFactory();

    lockHandle = new Dictionary<string, DataCacheLockHandle>();

  }

 

  /// <summary>

  /// Get an object which was previously saved in the state manager

  /// </summary>

  /// <param name="stateID"></param>

  /// <param name="key"></param>

  /// <returns></returns>

  public static object GetState(string stateID, string key)

  {

    Contract.Requires(!string.IsNullOrEmpty(stateID));

    Contract.Requires(!string.IsNullOrEmpty(key));

 

    try

    {

      var cache = CacheFactory.GetDefaultCache();

      if (cache == null)

         throw new DataCacheException("Could not create a cache object");

 

       return cache.Get(stateID + key);

    }

    catch (DataCacheException ex)

    {

       if (ex.ErrorCode != 6) //Key referred to does not exist

          Logger.HandleException(ex);

 

        return null;

    }

    catch (Exception ex)

    {

       Logger.HandleException(ex);

       return null;

    }           

  }

 

 

/// <summary>

/// Get an object which was previously saved in the state manager yet lock it for lockDuration

/// </summary>

/// <param name="stateID"></param>

/// <param name="key"></param>

/// <param name="lockDuration"></param>

/// <returns></returns>

public static object GetStateAndLock(string stateID, string key, TimeSpan lockDuration)

{

   Contract.Requires(!string.IsNullOrEmpty(stateID));

   Contract.Requires(!string.IsNullOrEmpty(key));

 

   try

   {

     var cache = CacheFactory.GetDefaultCache();

     if (cache == null)

        throw new DataCacheException("Could not create a cache object");

 

        DataCacheLockHandle handle;

        var result = cache.GetAndLock(stateID + key,
                                      lockDuration, out handle);

                lockHandle[stateID + key] = handle;

                return result;

   }

   catch (DataCacheException ex)

   {

      if (ex.ErrorCode != 6) //Key referred to does not exist

         Logger.HandleException(ex);

 

       return null;

   }

   catch (Exception ex)

   {

       Logger.HandleException(ex);

       return null;

   }           

}

 

/// <summary>

/// Save an object in the state manager

/// </summary>

/// <param name="stateID"></param>

/// <param name="key"></param>

/// <param name="state"></param>

public static void PutState(string stateID, string key, object state)

{

   Contract.Requires(!string.IsNullOrEmpty(stateID));

   Contract.Requires(!string.IsNullOrEmpty(key));

 

   try

   {

     var cache = CacheFactory.GetDefaultCache();

     if (cache == null)

        throw new DataCacheException("Could not create a cache object");

 

     cache.Put(stateID+key, state);

   }

   catch (Exception ex)

   {

       Logger.HandleException(ex);

       return null;

   }           

}

 

 

public static void PutState(string stateID, string key, object state, TimeSpan invalidationTimeout)

{

   Contract.Requires(!string.IsNullOrEmpty(stateID));

   Contract.Requires(!string.IsNullOrEmpty(key));

 

   try

   {

     var cache = CacheFactory.GetDefaultCache();

 

     if (cache == null)

         throw new DataCacheException("Could not create a cache object");

 

      cache.Put(stateID + key, state, invalidationTimeout);

   }

   catch (Exception ex)

   {

       Logger.HandleException(ex);

       return null;

   }           

}

 

 

 /// <summary>

/// Save an object in the state manager and unlock it

/// </summary>

/// <param name="stateID"></param>

/// <param name="key"></param>

/// <param name="state"></param>

public static void PutStateAndUnlock(string stateID, string key, object state)

{

   Contract.Requires(!string.IsNullOrEmpty(stateID));

   Contract.Requires(!string.IsNullOrEmpty(key));

 

   try

   {

     var cache = CacheFactory.GetDefaultCache();

 

     if (cache == null)

         throw new DataCacheException("Could not create a cache object");


    
if (lockHandle.ContainsKey(stateID + key))

     {

       cache.PutAndUnlock(stateID + key, state, lockHandle[stateID + key]);

       lockHandle.Remove(stateID + key)

     }

      else

         cache.Put(stateID + key, state);                  

               

   }

   catch (Exception ex)

   {

       Logger.HandleException(ex);

       return null;

   }           

}

 

/// <summary>

/// Clear an object from the state manager

/// </summary>

/// <param name="stateID"></param>

/// <param name="key"></param>

public static void RemoveState(string stateID, string key)

{

   Contract.Requires(!string.IsNullOrEmpty(stateID));

   Contract.Requires(!string.IsNullOrEmpty(key));

 

   try

   {

     var cache = CacheFactory.GetDefaultCache();

 

     if (cache == null)

         throw new DataCacheException("Could not create a cache object");

 

      cache.Remove(stateID + key);

 

      if (lockHandle.ContainsKey(stateID + key))

         lockHandle.Remove(stateID + key);

    }

   catch (Exception ex)

   {

       Logger.HandleException(ex);

       return null;

   }           

}

}

Enjoy

Manu

Comments

BUSINESS CAPITAL » Blog Archive Retain Working Capital Guarantee scheme said:

Pingback from  BUSINESS CAPITAL  &raquo; Blog Archive  Retain Working Capital Guarantee scheme

# February 25, 2011 6:58 AM

Activate Windows 7 (Product Key) ACTIVATOR TESTED&WORKING 2010(HQ).flv said:

Pingback from  Activate Windows 7 (Product Key) ACTIVATOR TESTED&amp;WORKING 2010(HQ).flv

# February 25, 2011 8:41 AM

[WATCH]: Ultrasonido Vaginal – Vaginal Scan | pain ovarian cysts said:

Pingback from  [WATCH]: Ultrasonido Vaginal &#8211; Vaginal Scan | pain ovarian cysts

# February 25, 2011 11:04 AM

WIRELESS HOME SECURITY SYSTEM HOUSE ALARM w AUTO DIALER 6 said:

Pingback from  WIRELESS HOME SECURITY SYSTEM HOUSE ALARM w AUTO DIALER 6

# February 25, 2011 5:42 PM

3DS MAX – CG Acad? Tutorials crumb S PERSIE 2] – [1 – What process? Dural – Pt 1 | How To Abs Fast said:

Pingback from  3DS MAX &#8211; CG Acad? Tutorials crumb S PERSIE 2] &#8211; [1 &#8211; What process? Dural &#8211; Pt 1 | How To Abs Fast

# February 26, 2011 1:54 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: