Azure DataCache Instantiation

1.6k views Asked by At

I'm creating a new MVC app to pull data from an Azure Data Cache. However, as soon as I try and instantiate a DataCache object, my code just hangs indefinitely. I don't get an error or timeout, it just sits there trying to create the new object.

At the moment my code is literally no more than:

public ActionResult Index()
{
  DataCache cache = new DataCache();
  Debugger.break;
}

buts never gets past the new DataCache() statement. If I pause the debugger in visual studio I can see it pausing on the new DataCache() line so that's definitely where execution has stalled.

My web.config has the section added by NuGet when I imported the new azure caching package as follows:

<dataCacheClients>
  <dataCacheClient name="default">
    <!--To use the in-role flavor of Windows Azure Caching, set identifier to be the cache cluster role name -->
    <!--To use the Windows Azure Caching Service, set identifier to be the endpoint of the cache cluster -->
    <autoDiscover isEnabled="true" identifier="{{REMOVED}}" />

    <!--<localCache isEnabled="true" sync="TimeoutBased" objectCount="100000" ttlValue="300" />-->

    <!--Use this section to specify security settings for connecting to your cache. This section is not required if your cache is hosted on a role that is a part of your cloud service. -->
    <securityProperties mode="Message" sslEnabled="false">
      <messageSecurity authorizationInfo="{{REMOVED}}" />
    </securityProperties>
  </dataCacheClient>
</dataCacheClients>

I've double checked the values in the web.config match with those in the Azure portal and they're oK.

Does anyone know the cause of this? I'm guessing its something quite basic given how new it is.

7

There are 7 answers

5
viperguynaz On

You are using Shared caching (Cache Service Preview) - the other two options are "In Role" caching - read more at Windows Azure Cache. Assuming that all your settings are correct in the config, then, you are not properly instantiating the cache. Read How to Use Windows Azure Cache Service (Preview). You need to use either:

DataCache cache = new DataCache("default");

or:

// Cache client configured by settings in application configuration file.
DataCacheFactory cacheFactory = new DataCacheFactory();
DataCache cache = cacheFactory.GetDefaultCache();
// Or DataCache cache = cacheFactory.GetCache("default");
// cache can now be used to add and retrieve items.

Finally, creating the cache object is expensive - you should create a new singleton class for the cache so that is gets created once - not every time an action is called. Here is a full example of the singleton class:

public static class MyCache
{
    private static DataCacheFactory _cacheFactory = null;
    private static ObjectCache Cache
    {
        get
        {
            return MemoryCache.Default;
        }
    }

    private static DataCache ACache
    {
        get
        {
            if (_cacheFactory == null)
            {
                try
                {
                    _retryPolicy.ExecuteAction(() => { _cacheFactory = new DataCacheFactory(); });
                    return _cacheFactory == null ? null : _cacheFactory.GetDefaultCache();
                }
                catch (Exception ex)
                {
                    ErrorSignal.FromCurrentContext().Raise(ex);
                    return null;
                }
            }

            return _cacheFactory.GetDefaultCache();
        }
    }

    public static void FlushCache()
    {
        ACache.Clear();
    }

    // Define your retry strategy: retry 3 times, 1 second apart.
    private static readonly FixedInterval  _retryStrategy = new FixedInterval(3, TimeSpan.FromSeconds(1));

    // Define your retry policy using the retry strategy and the Windows Azure storage
    // transient fault detection strategy.
    private static RetryPolicy _retryPolicy = new RetryPolicy<StorageTransientErrorDetectionStrategy>(_retryStrategy);

    // Private constructor to prevent instantiation
    // and force consumers to use the Instance property
    static MyCache()
    { }

    /// <summary>
    /// Add an item to the cache with a key and set a absolute expiration on it
    /// </summary>
    public static void Add(string key, object value, int minutes = 90)
    {
        try
        {
            if (RoleEnvironment.IsAvailable)
            {
                _retryPolicy.ExecuteAction(() => { ACache.Put(key, value, TimeSpan.FromMinutes(minutes)); });
            }
            else
            {
                Cache.Add(key, value, new CacheItemPolicy { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(minutes) });
            }
        }
        catch (Exception ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
        }
    }

    /// <summary>
    /// Add the object with the specified key to the cache if it does not exist, or replace the object if it does exist and set a absolute expiration on it
    /// only valid for Azure caching
    /// </summary>
    public static void Put(string key, object value, int minutes = 90)
    {
        try
        {  
            if (RoleEnvironment.IsAvailable)
            {
                _retryPolicy.ExecuteAction(() => { ACache.Put(key, value, TimeSpan.FromMinutes(minutes)); });
            }
            else
            {
                Cache.Add(key, value, new CacheItemPolicy { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(minutes) });
            }
        }
        catch (Exception ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
        }
    }

    /// <summary>
    /// Get a strongly typed item out of cache
    /// </summary>
    public static T Get<T>(string key) where T : class
    {
        try
        {
            object value = null;

            if (RoleEnvironment.IsAvailable)
            {
                _retryPolicy.ExecuteAction(() => { value = ACache.Get(key); });
            }
            else
            {
                value = Cache[key];
            }

            if (value != null) return (T) value;
            return null;
        }
        catch (DataCacheException ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
            return null;
        }
        catch (Exception ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
            return null;
        }
    }
    /// <summary>
    /// Microsoft's suggested method for cleaning up resources such as this in a static class
    /// to ensure connections and other consumed resources are returned to the resource pool
    /// as quickly as possible.
    /// </summary>
    public static void Uninitialize()
    {
        if (_cacheFactory == null) return;
        _cacheFactory.Dispose();
        _cacheFactory = null;
    }
}
0
Abhinav Gupta On

You have certainly added the correct NuGet package. What you are using is the Basic offering of the Cache Service (Preview), and not Shared Caching - that has been deprecated.

In the identifier field, are you specifying the full endpoint name - [yourcachename].cache.windows.net?

0
BrettRobi On

Here's my guess, based on my own experience. I'm betting you're using the Cache Service preview, you are trying to access from your local network (as opposed to from an Azure instance) and your network blocks outbound tcp ports (as many corporations do by default).

You said there were no timeouts, but how long did you wait? I have found that it takes an excessive amount of time (a few minutes perhaps?) to get failures in this case, but they do come. And the exceptions indicate the port number the cache client is trying to use. I've seen ports 22233 and 22234, both of which were blocked on my corporate network. The problem went away when I convinced my IT group to allow the traffic through on those ports.

I have yet to find documentation of all ports the cache client might want to use, nor has a forum post on the subject been answered.

0
Andrew Koltz On

I was banging my head against this problem for hours, until I came across this stack overflow which explained it. TL;DR: the latest version of the package doesn't play well with version 2.3 of the SDK. When I rolled back to Azure Caching 2.1, everything worked fine.

Exception while using Windows Azure Caching : No such host is known

0
Holt Mansfield On

I've got a dev sitting across from me that can't hit the cache when he's using IIS Express.

When he switches to IIS Proper it works.

0
Steve On

I've found the DataCache constructor hangs indefinitely because of the performance counter initialisation. I've seen various reports of what might cause the problem, such as installing Office 2013.

I've fixed this by running the ClientPerfCountersInstaller.exe that gets added to your project when you install the Azure Caching NuGet package.

ClientPerfCountersInstaller in Solution Explorer

Open a command prompt with administrative privileges and cd to this folder. Then run the installer with the command:

ClientPerfCountersInstaller.exe install

After that my project ran without hanging.

0
shanthiprakash chirra On

I was fighting with this from Hours and get resolved by Uninstalling the SDK v2.6 and installed with SDK 2.4.

see below for the instructions. https://www.nuget.org/packages/Microsoft.WindowsAzure.Caching/2.4.0