Aggiornamento: Ora l'ho implementato correttamente. Per maggiori informazioni vedi il mio blog post a riguardo.AppFabric: impossibile contattare il servizio cache
Sto cercando di utilizzare AppFabric con NHibernate come provider di cache di secondo livello, ma ricevo il seguente errore: ErrorCode: Inizializzazione: impossibile contattare il servizio cache. Contattare l'amministratore e fare riferimento alla documentazione della guida del prodotto per possibili motivi.
Presumo che il problema è con la mia configurazione nel 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>
Ho scaricato il codice sorgente di NHibernate.Caches per cercare di scoprire dove sta il problema e l'eccezione viene gettata nel costruttore VelocityClient quando il metodo GetCache si chiama:
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 posso aggiungere un orologio alla variabile cacheCluster, posso trovare un _servers variabile privata che ha una System.Data.Caching.EndpointID che ha la prope MyURI rty set to net.tcp: // localhost: 22234/AppFabricCachingServive che presumo provenga dalla configurazione in web.config.
Se non si conosce la causa esatta del problema ma si hanno alcune idee su come risolvere questo problema, sarebbe molto apprezzato.
Altre Informazioni
io ottenere i seguenti risultati 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
Quindi penso che il valore c'ho configurato in web.config sono OK.
Googling questo problema e investigando come impostare AppFabric, in primo luogo, mi sono imbattuto in due modi leggermente diversi su come configurare la cache in web.config. Il modo in cui ho descritto sopra e il modo in cui Hanselman ha nel suo AppFabric blog post
realtà ho iniziato con in questo modo però, ho ricevuto il seguente errore che è come mi è venuto di averlo configurato come devo subito:
ErrorCode: tag "dcacheClient" non specificato nel file di configurazione dell'applicazione. Specifica un tag valido nel file di configurazione.
traccia dello stack completo l'eccezione che viene gettato in VelocityClient:
System.Data.Caching.CacheException verificato Messaggio = "ErrorCode: \" tag dcacheClient \" non specificato nel file di configurazione dell'applicazione Specificare un tag valido nel file di configurazione. " Source = "CacheBaseLibrary" ErrorCode = "ERRCMC0004" StackTrace: a System.Data.Caching.ClientConfigFile.ThrowException (String errorCode, String param) a System.Data.Caching.ClientConfigReader.GetDeployementMode() al sistema. Data.Caching.ClientConfigurationManager.InitializeDepMode (ClientConfigReader CFR) a System.Data.Caching.ClientConfigurationManager.Initialize (string path) a System.Data.Caching.ClientConfigurationManager..ctor() a System.Data.Caching.CacheFactory.InitCacheFactory() presso System .Data.Caching.CacheFactory.GetCache (String cacheName) in NHibernate.Caches.Velocity.VelocityClient..ctor (String regionName, IDictionary`2 proprietà) in C: \ Source \ Projects \ NHibernate.contrib \ trunk \ src \ NHibernate .Caches \ Velocity \ NHibernate.Caches.Velocity \ VelocityClient.cs: linea 67 InnerException:
EDIT: Rese da get-cachehost
come richiesto dal @PhilPursglove
uscita da get-cachehost
:
HostName : CachePort Service Name Service Status Version Info
-------------------- ------------ -------------- ------------
tn-staylor-02:22233 AppFabricCachingService UP 1 [1,1][1,1]
SOLUZIONE: @PhilPursglove era perfetto. Il provider di velocità di NHibernate stava usando vecchi dll per aggiornarli e fare alcune modifiche al codice ha risolto i miei problemi. Ho pensato di includere la mia soluzione completa qui.
- scaricato i sorgenti NHibernate.contrib dal repository SVN a https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk
- aperto la soluzione NHibernate.Caches.Everything e rimossi i riferimenti ai vecchi velocità dll dal progetto NHibernate.Caches.Velocity.
- Aggiunti riferimenti alle dll di App Fabric che sono state installate durante l'installazione di App Fabric. Questo non è il caso normale di aggiungere un riferimento a un assembly nel GAC, ma this article describes how to do it.
- L'aggiunta dei nuovi riferimenti ha significato che la classe VelocityClient non è più compilata. Con un po 'di aiuto da this ho trovato la versione di VelocityClient.cs qui sotto.
- Ho aggiunto un riferimento alla nuova versione di NHibernate.Caches.Velocity al mio progetto, apportato le modifiche di seguito alla mia configurazione e tutto ha funzionato.
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>
...
Non ho apportato ulteriori modifiche alla mia configurazione di App Fabric o altro.
La cache è in esecuzione? Qual è l'output di 'get-cachehost'? – PhilPursglove
@PhilPursglove, sì la cache è in esecuzione e ho aggiunto l'output di get-cachehost alla domanda originale. Grazie per aver il tempo di commentare – s1mm0t
Contento che l'abbia risolto! È necessario inviare le modifiche di NHibernate al trunk in modo che nessun altro possa ottenere questo problema. – PhilPursglove