【问题标题】:AppFabric: Could not contact the cache serviceAppFabric:无法联系缓存服务
【发布时间】:2010-07-13 02:31:39
【问题描述】:

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

我正在尝试使用带有 NHibernate 的 AppFabric 作为我的二级缓存提供程序,但我收到以下错误:ErrorCode:Initialization: 无法联系缓存服务。联系管理员并参考产品帮助文档了解可能的原因。

我认为问题在于我在 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假设来自 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 Message="ErrorCode:\"dcacheClient\" 标签未在应用程序配置文件中指定。请在配置文件中指定有效标签。" 来源="CacheBaseLibrary" 错误代码="ERRCMC0004" 堆栈跟踪: 在 System.Data.Caching.ClientConfigFile.ThrowException(字符串错误代码,字符串参数) 在 System.Data.Caching.ClientConfigReader.GetDeployementMode() 在 System.Data.Caching.ClientConfigurationManager.InitializeDepMode(ClientConfigReader cfr) 在 System.Data.Caching.ClientConfigurationManager.Initialize(字符串路径) 在 System.Data.Caching.ClientConfigurationManager..ctor() 在 System.Data.Caching.CacheFactory.InitCacheFactory() 在 System.Data.Caching.CacheFactory.GetCache(字符串缓存名称) 在 C:\Source\Projects\NHibernate.contrib\trunk\src\NHibernate.Caches\Velocity\NHibernate.Caches.Velocity\VelocityClient 中的 NHibernate.Caches.Velocity.VelocityClient..ctor(字符串 regionName,IDictionary`2 属性)。 CS:第 67 行 内部异常:


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

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 配置或任何其他内容进行任何进一步的更改。

【问题讨论】:

  • 您的缓存是否在运行? get-cachehost 的输出是什么?
  • @PhilPursglove,是的,缓存正在运行,我已将 get-cachehost 的输出添加到原始问题中。感谢您抽出宝贵时间发表评论
  • 很高兴你修好了!您应该将这些 NHibernate 更改提交回主干,以免其他人遇到此问题。
  • @s1mm0t 我正在考虑使用 AppFabric 作为二级缓存。这对你来说效果好吗?
  • 是的,它运行良好。我一直想写一篇关于我的经历的博文

标签: nhibernate appfabric


【解决方案1】:

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

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

  2. 那个异常堆栈跟踪是指CacheBaseLibrary - 我对 NHibernate 知之甚少(阅读:任何东西!),但我会冒险猜测该缓存可能不是使用发行版构建的AppFabric - CacheBaseLibrary 是出现在 CTP 和 beta 中的程序集,但我认为它没有用于 RTM 版本。请注意,在dcacheclient 的部分元素中,它指的是Microsoft.ApplicationServer.Caching.Core 程序集。

【讨论】:

  • 我试过使用 tn-staylor-02 没有任何运气,但看起来你可能正在使用缓存基础库。我将尝试更换最新的程序集,并且可能还需要更新代码 - 我会告诉你我的进展情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-28
  • 2011-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-18
相关资源
最近更新 更多