nhibernate - AppFabric: no se pudo contactar con el servicio de caché
(1)
Actualización: ahora he implementado esto correctamente. Para obtener más información, consulte mi blog sobre esto.
Estoy intentando usar AppFabric con NHibernate como mi proveedor de caché de segundo nivel, pero obtengo el siguiente error: Código de error : Inicialización: no se pudo contactar con el servicio de caché. Póngase en contacto con el administrador y consulte la documentación de ayuda del producto para conocer los posibles motivos.
Supongo que el problema está en mi configuración en 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>
He descargado el código fuente de NHibernate.Caches para intentar descubrir dónde se encuentra el problema y la excepción que se presenta en el constructor de VelocityClient cuando se llama al método GetCache:
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) {}
}
Si agrego un reloj a la variable cacheCluster, puedo encontrar una variable privada _servers que tiene un System.Data.Caching.EndpointID que tiene la propiedad MyURI establecida en net.tcp: // localhost: 22234 / AppFabricCachingServive, que presumo ha llegado Desde la configuración en web.config.
Si no conoce la causa exacta del problema pero tiene algunas ideas sobre cómo solucionar este problema, eso también se agradecería.
Información adicional
Obtengo los siguientes resultados del comando, Get-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
Así que creo que los valores que tengo configurados en web.config están bien.
Buscando en Google este problema e investigando cómo configurar AppFabric en primer lugar, he encontrado dos formas ligeramente diferentes de cómo configurar el caché en web.config. La forma en que lo describí anteriormente y la forma en que Hanselman lo tiene en su publicación en el blog de AppFabric
De hecho, comencé con esto de esta manera, pero recibí el siguiente error, que es cómo llegué a configurarlo como lo tengo ahora:
Código de error: etiqueta "dcacheClient" no especificada en el archivo de configuración de la aplicación. Especifique la etiqueta válida en el archivo de configuración.
Rastreo de la pila completa de la excepción que se lanza en VelocityClient:
Se produjo System.Data.Caching.CacheException Message = "ErrorCode: /" dcacheClient / "etiqueta no especificada en el archivo de configuración de la aplicación. Especifique una etiqueta válida en el archivo de configuración." Source = "CacheBaseLibrary" ErrorCode = "ERRCMC0004" StackTrace: at System.Data.Caching.ClientConfigFile.ThrowException (String errorCode, String param) en System.Data.Caching.ClientConfigReader.GetDeployementMode (). InitializeDepMode (ClientConfigReader cfr) en System.Data.Caching.ClientConfigurationManager.Initialize (ruta de la cadena) en System.Data.Caching.ClientConfigurationManager..ctor () en el sistema System.Data.Caching.CacheFactory.InitCacheFactory.InitCacheFacory.InitCacheFacory .CacheFactory.GetCache (String cacheName) en NHibernate.Caches.Velocity.VelocityClient..ctor (String regionName, IDictionary`2 propiedades) en C: / Source / Projects / NHibernate.contrib / trunk / src / NHibernate.Caches / Velocity / NHibernate.Caches.Velocity / VelocityClient.cs: línea 67 InnerException:
EDITAR : Se ha agregado la salida de get-cachehost
según lo solicitado por @PhilPursglove
Salida desde get-cachehost
:
HostName : CachePort Service Name Service Status Version Info
-------------------- ------------ -------------- ------------
tn-staylor-02:22233 AppFabricCachingService UP 1 [1,1][1,1]
SOLUCIÓN : @PhilPursglove fue acertado. El proveedor de velocidad de NHibernate estaba usando archivos DLL antiguos, por lo que actualizarlos y hacer algunos cambios de código resolvió mis problemas. Pensé que incluiría mi solución completa aquí.
- Descargué la fuente NHibernate.contrib del repositorio de SVN en https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk
- Abrí la solución NHibernate.Caches.Everything y eliminé las referencias a las dll de velocidad antiguas del proyecto NHibernate.Caches.Velocity.
- Se agregaron referencias a las dll de App Fabric que se instalaron cuando instalé App Fabric. Este no es el caso normal de agregar una referencia a un ensamblado en la GAC, pero este artículo describe cómo hacerlo .
- Al agregar las nuevas referencias, la clase VelocityClient ya no se compila. Con un poco de ayuda de this me ocurrió la versión de VelocityClient.cs a continuación.
- Agregué una referencia a la nueva versión de NHibernate.Caches.Velocity a mi proyecto, hice los cambios a continuación a mi configuración y todo funcionó.
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>
...
No hice más cambios en la configuración de mi App Fabric ni nada.
Creo que hay dos posibles culpables aquí:
En tu web.config bajo el elemento
hosts
, estás listandolocalhost
- Intentaría cambiar eso por el nombre real del servidortn-staylor-02
El seguimiento de la pila de excepciones se refiere a
CacheBaseLibrary
: no sé mucho (lea: ¡nada!) Sobre NHibernate, pero me atrevería a suponer que ese caché podría no estar construido con la versión de lanzamiento de AppFabric: CacheBaseLibrary fue un ensamblaje que apareció en los CTP y las betas, pero no creía que se utilizara en la versión RTM. Tenga en cuenta que en el elemento de la sección paradcacheclient
, se refiere al conjuntoMicrosoft.ApplicationServer.Caching.Core
.