AppFabric: não foi possível entrar em contato com o serviço de cache

Atualizar: Agora eu implementei isso corretamente. Para mais informações, consulte o meupublicação no blog sobre isso.

Estou tentando usar o AppFabric com NHibernate como meu provedor de cache de segundo nível, mas estou recebendo o seguinte erro:ErrorCode: Initialization: Não foi possível entrar em contato com o serviço de cache. Entre em contato com o administrador e consulte a documentação de ajuda do produto por possíveis motivos.

Presumo que o problema esteja na minha configuração no web.config:

    <section name="dcacheClient" 
             type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core"
             allowLocation="true" 
             allowDefinition="Everywhere"/>
...
  <dcacheClient deployment="routing" localCache="False">
    <localCache isEnabled="false" sync="TimeoutBased" ttlValue="300" />
    <hosts>
      <host name="localhost" cachePort="22233" cacheHostName="AppFabricCachingService" />
    </hosts>
  </dcacheClient>

Fiz o download do código-fonte NHibernate.Caches para tentar descobrir onde está o problema e a exceção está sendo lançada no construtor VelocityClient quando o método GetCache é chamado:

  public VelocityClient(string regionName, IDictionary<string, string> properties)
  {
      region = regionName.GetHashCode().ToString(); //because the region name length is limited
      var cacheCluster = new CacheFactory();
      cache = cacheCluster.GetCache(CacheName);
      try
      {
          cache.CreateRegion(region, true);
      }
      catch (CacheException) {}
  }

Se eu adicionar um relógio à variável cacheCluster, posso encontrar uma variável privada _servers que tenha um System.Data.Caching.EndpointID que possua a propriedade MyURI definida como net.tcp: // localhost: 22234 / AppFabricCachingServive que eu presumo que tenha chegado da configuração em web.config.

Se você não souber a causa exata do problema, mas tiver algumas idéias sobre como solucionar esse problema, isso também será muito apreciado.

Informação adicional

Eu recebo os seguintes resultados do comandoGet-CacheHostConfig -HostName tn-staylor-02 -CachePort 22233:

HostName        : tn-staylor-02
ClusterPort     : 22234
CachePort       : 22233
ArbitrationPort : 22235
ReplicationPort : 22236
Size            : 3001 MB
ServiceName     : AppFabricCachingService
HighWatermark   : 90%
LowWatermark    : 70%
IsLeadHost      : True

Então, acho que os valores que configurei no web.config estão corretos.

Pesquisando esse problema e investigando como configurar o AppFabric em primeiro lugar, deparei-me com duas maneiras ligeiramente diferentes de como configurar o cache no web.config. O modo como descrevi acima e o modo como Hanselman o descrevePostagem no blog AppFabric

Na verdade, eu comecei com isso assim, no entanto, recebi o seguinte erro, que foi como cheguei a configurá-lo como o tenho agora:

ErrorCode: tag "dcacheClient" não especificada no arquivo de configuração do aplicativo. Especifique uma marca válida no arquivo de configuração.

Rastreio de pilha completa da exceção lançada no VelocityClient:

System.Data.Caching.CacheException ocorreu Mensagem = "ErrorCode: \" dcacheClient \ "marca não especificada no arquivo de configuração do aplicativo. Especifique a marca válida no arquivo de configuração." Origem = "CacheBaseLibrary" ErrorCode = "ERRCMC0004" StackTrace: no System.Data.Caching.ClientConfigFile.ThrowException (String errorCode, String param) em System.Data.Caching.ClientConfigReader.GetDeployementMode () em System.Data.Caching.ClientConfigurationManager. InitializeDepMode (ClientConfigReader cfr) em System.Data.Caching.ClientConfigurationManager.Initialize (caminho da String) em System.Data.Caching.ClientConfigurationManager..ctor () em System.Data.Caching.CacheFactory.InitCacheFactory () em System.Data.Caching .CacheFactory.GetCache (String cacheName) em NHibernate.Caches.Velocity.VelocityClient..ctor (String regionName, IDictionary`2 propriedades) em C: \ Source \ Projects \ NHibernate.contrib \ trunk \ src \ NHibernate.Caches \ Velocity \ NHibernate.Caches.Velocity \ VelocityClient.cs: linha 67 InnerException:

EDITAR: Saída adicionada deget-cachehost conforme solicitado por @PhilPursglove

Saída deget-cachehost:

HostName : CachePort      Service Name            Service Status Version Info
--------------------      ------------            -------------- ------------
tn-staylor-02:22233       AppFabricCachingService UP             1 [1,1][1,1]

SOLUÇÃO: @PhilPursglove estava no local. O provedor de velocidade do NHibernate estava usando dlls antigas, portanto, atualizá-las e fazer algumas alterações no código resolveram meus problemas. Pensei em incluir minha solução completa aqui.

Transferiu a fonte NHibernate.contrib do repositório SVN emhttps://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunkAbriu a solução NHibernate.Caches.Everything e removeu as referências às DLLs de velocidade antigas do projeto NHibernate.Caches.Velocity.Adicionadas referências às DLLs do App Fabric que foram instaladas quando eu instalei o App Fabric. Este não é o caso normal de adicionar uma referência a um assembly no GAC, maseste artigo descreve como fazê-lo.Adicionar novas referências significava que a classe VelocityClient não era mais compilada. Com um pouco de ajuda deesta Eu vim com a versão do VelocityClient.cs abaixo.Adicionei uma referência à nova versão do NHibernate.Caches.Velocity ao meu projeto, fiz as alterações abaixo na minha configuração e tudo funcionou.

VelocityClient.cs

using System;
using System.Collections.Generic;
using Microsoft.ApplicationServer.Caching;
using log4net;
using NHibernate.Cache;
using CacheException = Microsoft.ApplicationServer.Caching.DataCacheException;
using CacheFactory = Microsoft.ApplicationServer.Caching.DataCacheFactory;

namespace NHibernate.Caches.Velocity
{
    public class VelocityClient : ICache
    {
        private const string CacheName = "nhibernate";
        private static readonly ILog log;
        private readonly DataCache cache;
        private readonly string region;
        private Dictionary<string, DataCacheLockHandle> locks = new Dictionary<string, DataCacheLockHandle>();

        static VelocityClient()
        {
            log = LogManager.GetLogger(typeof (VelocityClient));
        }

        public VelocityClient() : this("nhibernate", null) {}

        public VelocityClient(string regionName) : this(regionName, null) {}

        public VelocityClient(string regionName, IDictionary<string, string> properties)
        {
            region = regionName.GetHashCode().ToString(); //because the region name length is limited
            var cacheCluster = new CacheFactory();
            cache = cacheCluster.GetCache(CacheName);
            try
            {
                cache.CreateRegion(region);
            }
            catch (CacheException) {}
        }

        #region ICache Members

        public object Get(object key)
        {
            if (key == null)
            {
                return null;
            }
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("fetching object {0} from the cache", key);
            }

            DataCacheItemVersion version = null;
            return cache.Get(key.ToString(), out version, region);
        }

        public void Put(object key, object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key", "null key not allowed");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value", "null value not allowed");
            }

            if (log.IsDebugEnabled)
            {
                log.DebugFormat("setting value for item {0}", key);
            }

            cache.Put(key.ToString(), value, region);
        }

        public void Remove(object key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("removing item {0}", key);
            }

            if (Get(key.ToString()) != null)
            {
                cache.Remove(region, key.ToString());
            }
        }

        public void Clear()
        {
            cache.ClearRegion(region);
        }

        public void Destroy()
        {
            Clear();
        }

        public void Lock(object key)
        {
            DataCacheLockHandle lockHandle = null;

            if (Get(key.ToString()) != null)
            {
                try
                {
                    cache.GetAndLock(key.ToString(), TimeSpan.FromMilliseconds(Timeout), out lockHandle, region);
                    locks.Add(key.ToString(), lockHandle);
                }
                catch (CacheException) {}
            }
        }

        public void Unlock(object key)
        {
            DataCacheLockHandle lockHandle = null;

            if (Get(key.ToString()) != null)
            {
                try
                {
                    if (locks.ContainsKey(key.ToString()))
                    {
                        cache.Unlock(key.ToString(), locks[key.ToString()], region);
                        locks.Remove(key.ToString());
                    }
                }
                catch (CacheException) {}
            }
        }

        public long NextTimestamp()
        {
            return Timestamper.Next();
        }

        public int Timeout
        {
            get { return Timestamper.OneMs * 60000; } // 60 seconds
        }

        public string RegionName
        {
            get { return region; }
        }

        #endregion
    }
}

NHibernate.config:

...
    <property name="cache.provider_class">NHibernate.Caches.Velocity.VelocityProvider, NHibernate.Caches.Velocity</property>
    <property name="cache.use_second_level_cache">true</property>
    <property name="cache.use_query_cache">true</property>
...

web.config

...
    <section name="dataCacheClient"
             type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             allowLocation="true"
             allowDefinition="Everywhere"/>
...
  <dataCacheClient>
    <!-- cache host(s) -->
    <hosts>
      <host
         name="localhost"
         cachePort="22233"/>
    </hosts>
  </dataCacheClient>
...

Não fiz mais alterações na configuração do App Fabric nem nada.

questionAnswers(1)

yourAnswerToTheQuestion