AppFabric:无法联系缓存服务

时间:2010-07-13 02:31:39

标签: nhibernate appfabric

更新:我现在已经正确实施了这一点。有关详细信息,请参阅我的blog post

我正在尝试将AppFabric与NHibernate一起用作我的二级缓存提供程序但是我收到以下错误: ErrorCode:初始化:无法联系缓存服务。请联系管理员并参阅产品帮助文档。

我认为问题在于我在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>

我已经下载了NHibernate.Caches源代码,试图找出问题所在,并在调用GetCache方法时在VelocityClient构造函数中抛出异常:

  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) {}
  }

如果我将一个监视添加到cacheCluster变量,我可以找到一个_servers私有变量,它有一个System.Data.Caching.EndpointID,其MyURI属性设置为net.tcp:// localhost:22234 / AppFabricCachingServive,我presume来自web.config中的配置。

如果您不知道问题的确切原因,但对如何解决此问题有一些想法,那将非常感激。

其他信息


我从命令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

所以我认为我在web.config中配置的值是可以的。


搜索这个问题并首先研究如何设置AppFabric,我遇到了两种稍微不同的方法来配置web.config中的缓存。我上面描述的方式和Hanselman在AppFabric blog post

中的方式

我实际上是这样开始的,然而,我得到了以下错误,这就是我如何配置它如何配置现在:

ErrorCode:应用程序配置文件中未指定“dcacheClient”标记。在配置文件中指定有效标记。


在VelocityClient中抛出异常的完整堆栈跟踪:

发生了System.Data.Caching.CacheException   消息=“ErrorCode:\”dcacheClient \“标记未在应用程序配置文件中指定。在配置文件中指定有效标记。”   来源= “CacheBaseLibrary”   错误码= “ERRCMC0004”   堆栈跟踪:        at System.Data.Caching.ClientConfigFile.ThrowException(String errorCode,String param)        在System.Data.Caching.ClientConfigReader.GetDeployementMode()        在System.Data.Caching.ClientConfigurationManager.InitializeDepMode(ClientConfigReader cfr)        在System.Data.Caching.ClientConfigurationManager.Initialize(String path)        在System.Data.Caching.ClientConfigurationManager..ctor()        在System.Data.Caching.CacheFactory.InitCacheFactory()        在System.Data.Caching.CacheFactory.GetCache(String cacheName)        at NHibernate.Caches.Velocity.VelocityClient..ctor(String regionName,IDictionary`2 properties)在C:\ Source \ Projects \ NHibernate.contrib \ trunk \ src \ NHibernate.Caches \ Velocity \ NHibernate.Caches.Velocity \ VelocityClient中。 cs:第67行   InnerException:


编辑:根据@PhilPursglove的要求添加get-cachehost的输出

get-cachehost的输出:

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

解决方案:@PhilPursglove当场亮相。 NHibernate速度提供程序使用旧的dll,因此升级它们并进行一些代码更改解决了我的问题。我想我会在这里提供完整的解决方案。

  1. https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk
  2. 的SVN存储库下载NHibernate.contrib源代码
  3. 打开NHibernate.Caches.Everything解决方案,并从NHibernate.Caches.Velocity项目中删除对旧速度dll的引用。
  4. 添加了对安装App Fabric时安装的App Fabric dll的引用。这不是在GAC中添加对程序集的引用的常规情况,而是this article describes how to do it
  5. 添加新引用意味着不再编译VelocityClient类。在this的一些帮助下,我想出了下面的VelocityClient.cs版本。
  6. 我在我的项目中添加了对NHibernate.Caches.Velocity新版本的引用,将下面的更改改为我的配置,一切正常。
  7. 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>
    ...
    

    我没有对App Fabric配置或其他任何内容进行任何进一步的更改。

1 个答案:

答案 0 :(得分:6)

我认为这里有两个可能的罪魁祸首:

  1. hosts元素下的web.config中,您列出了localhost - 我尝试将其换成实际的服务器名称tn-staylor-02

  2. 异常堆栈跟踪引用CacheBaseLibrary - 我不知道有关NHibernate的很多内容(阅读:任何内容!)但是我猜想这个缓存可能不会在发布时构建AppFabric的版本 - CacheBaseLibrary是一个出现在CTP和beta版中的程序集,但我不认为它在RTM版本中使用过。请注意,在dcacheclient的section元素中,它引用了Microsoft.ApplicationServer.Caching.Core程序集。