AppFabric: не удалось связаться со службой кеширования.

Обновление: теперь я правильно реализовал это. Дополнительную информацию см. В моем сообщении в блоге об этом.

Я пытаюсь использовать AppFabric с NHibernate в качестве поставщика кеша второго уровня, но получаю следующую ошибку: Код ошибки: Инициализация: не удалось связаться со службой кеширования. Обратитесь к администратору и обратитесь к справочной документации по продукту, чтобы узнать о возможных причинах.

Я предполагаю, что проблема в моей конфигурации в 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, чтобы попытаться выяснить, в чем проблема, и что исключение выдается в конструкторе VelocityClient при вызове метода 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) {}
  }

Если я добавлю часы к переменной 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. То, что я описал выше, и то, как Гензельман изложил это в своем сообщении в блоге AppFabric

На самом деле я начал с этого, но у меня возникла следующая ошибка, из-за которой я пришел к настройке, как у меня сейчас:

ErrorCode: тег dcacheClient не указан в файле конфигурации приложения. Укажите действительный тег в файле конфигурации.


Полная трассировка стека исключения, которое возникает в VelocityClient:

System.Data.Caching.CacheException Произошло сообщение = "ErrorCode: \" dcacheClient \ "тег не указан в файле конфигурации приложения. Укажите допустимый тег в файле конфигурации." Source = "CacheBaseLibrary" ErrorCode = "ERRCMC0004" StackTrace: в System.Data.Caching.ClientConfigFile.ThrowException (String errorCode, String param) в System.Data.Caching.ClientConfigReader.GetDeployementMode () в System.Data.CachingMiguration.Client. 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) в NHibernate.Caches.Velocity.VelocityClient..ctor (String regionName, свойства IDictionary`2) в C: \ Source \ Projects \ NHibernate.contrib \ trunk \ src \ NHibernate.Caches \ Velocity \ NHibernate.Caches.Velocity \ VelocityClient.cs: строка 67 InnerException:


РЕДАКТИРОВАТЬ: добавлен вывод из get-cachehost по запросу @PhilPursglove

Вывод из 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. Загрузил исходный код NHibernate.contrib из репозитория SVN по адресу https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk
  2. Открыл решение NHibernate.Caches.Everything и удалил ссылки на старые DLL-библиотеки скорости из проекта NHibernate.Caches.Velocity.
  3. Добавлены ссылки на библиотеки DLL App Fabric, которые были установлены при установке App Fabric. Это не обычный случай добавления ссылки на сборку в GAC, но в этой статье описывается, как это сделать.
  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 или что-то еще.


person s1mm0t    schedule 13.07.2010    source источник
comment
Ваш кеш работает? Что дает get-cachehost?   -  person PhilPursglove    schedule 13.07.2010
comment
@PhilPursglove, да, кеш работает, и я добавил вывод get-cachehost в исходный вопрос. Спасибо, что нашли время, чтобы прокомментировать   -  person s1mm0t    schedule 13.07.2010
comment
Рад, что ты это починил! Вы должны отправить эти изменения NHibernate обратно в магистраль, чтобы никто другой не столкнулся с этой проблемой.   -  person PhilPursglove    schedule 15.07.2010
comment
@ s1mm0t Я собираюсь использовать AppFabric в качестве кеша второго уровня. Это сработало для вас?   -  person dove    schedule 19.10.2010
comment
Да, все хорошо. Я все еще хочу написать в блоге о своем опыте   -  person s1mm0t    schedule 20.10.2010
comment
@ s1mm0t вам следует либо отправить в nhcontrib, либо зарегистрировать проблему с подробным описанием этого. хорошая работа.   -  person dove    schedule 20.10.2010
comment
@ s1mm0t Я последовал вашему примеру и получил NHibernate.Caches.Velocity.Tests, работающий с моим локальным экземпляром AppFabric. Все, кроме TestRemove, просто вроде не удаляет элемент заданный ключом. cache.Clear стирает все нормально но не удаляет   -  person dove    schedule 20.10.2010
comment
Да, я хотел бы отправить это исправление в nhcontrib, но я связался с ними, чтобы получить разрешение, но ничего не получил в ответ ...   -  person s1mm0t    schedule 22.10.2010
comment
Я должен признать, что мне не удалось запустить тесты, поэтому вполне возможно, что все тесты не пройдут с приведенным выше кодом.   -  person s1mm0t    schedule 22.10.2010
comment
@ s1mm0t я заставил их всех работать с методом удаления. Я дам тебе знать, если сделаю. Я так понимаю, вы видели, как ваш провайдер удалял вещи из кеша? Или, возможно, лучший вопрос, нормально ли он работал в качестве кеша второго уровня?   -  person dove    schedule 22.10.2010
comment
@dove Да, он отлично работает как кеш второго уровня   -  person s1mm0t    schedule 23.10.2010
comment
Я написал Айенде об этом в ноябре, он ответил, что, возможно, кеш AppFabric следует удалить из nhcontrib, но мне неясно, собирается ли он это сделать - например, @ s1mm0t, я не могу этого сделать сам!   -  person PhilPursglove    schedule 12.01.2011
comment
Привет, просто хочу сказать Спасибо !! и сообщу, что я следовал вашему решению, и оно отлично работает.   -  person Weiming    schedule 13.04.2011
comment
Привет, я обнаружил небольшую ошибку в VelocityClient.cs, в методе Remove (объектный ключ) строка удаления должна быть: cache.Remove (key.ToString (), region);   -  person Weiming    schedule 13.04.2011
comment
Привет! Спасибо ... это все, что я хотел сказать ...   -  person vIceBerg    schedule 12.05.2011
comment
Привет, я работал над вашим решением, и я добился некоторого прогресса, однако я застрял со следующей ошибкой во время выполнения при запуске моего проекта (отладки) на моем локальном компьютере: Упомянутый кеш не существует . Обратитесь к администратору или воспользуйтесь инструментом администрирования кэша, чтобы создать кэш. Есть идеи, что это может быть, я что-то пропустил в конфигурации? Если я выполняю «get-cache» в PowerShell, я получаю кеш с именем «default» без регионов.   -  person MIP    schedule 20.07.2011
comment
Не обращайте на меня внимания, я вижу, что имя кеша жестко запрограммировано в VelocityClient.cs!   -  person MIP    schedule 20.07.2011


Ответы (1)


Я думаю, здесь есть два возможных виновника:

  1. В вашем web.config под элементом hosts вы указываете localhost - я бы попробовал заменить это на фактическое имя сервера tn-staylor-02

  2. Эта трассировка стека исключений относится к CacheBaseLibrary - я мало что знаю (читай: ничего!) О NHibernate, но рискну предположить, что этот кеш не может быть построен с помощью окончательной версии AppFabric - CacheBaseLibrary была сборкой, которая появилась в CTP и бета-версиях, но я не думал, что он использовался в версии RTM. Обратите внимание, что в элементе section для dcacheclient он относится к сборке Microsoft.ApplicationServer.Caching.Core.

person PhilPursglove    schedule 13.07.2010
comment
Я безуспешно пытался использовать tn-staylor-02, но похоже, что вы что-то знаете с базовой библиотекой кеша. Я попробую заменить последние сборки и, вероятно, мне также потребуется обновить код - я дам вам знать, как у меня дела. - person s1mm0t; 13.07.2010