Ошибка AppRabric CreateRoutingClient

У нас есть проблема с AppFabric, которая вызывает ошибку ниже:

Exception type: ArgumentException 
Exception message: An item with the same key has already been added.
    at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
    at Microsoft.ApplicationServer.Caching.DataCacheFactory.CreateRoutingClient(String cacheName, NamedCacheConfiguration config)
    at Microsoft.ApplicationServer.Caching.DataCacheFactory.CreateNewCacheClient(DataCacheDeploymentMode mode, String cacheName, NamedCacheConfiguration config, IClientChannel channel)
    at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetCache(String cacheName)
    at Microsoft.ApplicationServer.Caching.DataCacheFactory.GetDefaultCache()
    ... our code where we are attempting to retrieve a cache item from the default cache by its key

Эта ошибка происходит редко в нашей тестовой среде (мы не нашли сценарий для воспроизведения проблемы по требованию), но, как представляется, это всегда происходит в нашей производственной среде сразу после каждого развертывания. Наши развертывания автоматизированы, и мы проверили, что шаги для развертывания в наших различных средах одинаковы.

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

  • Server1 - размещает наш .net-сайт и является нашим сервером AppFabric 1.1
  • Server2 - размещает наш веб-сайт .net.

Эти серверы сбалансированы по нагрузке. Локальное кэширование AppFabric включено в обоих приложениях. Наши тестовые и производственные серверы настроены одинаково. Мы знаем, что было бы лучше иметь AppFabric на выделенном сервере, но не думайте, что это вызовет/разрешит эту проблему.

Мы сталкиваемся с этой проблемой, так как мы не обнаружили никаких упоминаний об этом в другом месте в Интернете, и поскольку трассировка стека, похоже, указывает на то, что это проблема с самим AppFabric. В исключении упоминается вставка чего-то, но все, что мы делаем, когда это происходит, - это попытка получить кеш-память по умолчанию из DataCacheFactory, чтобы мы могли извлечь элемент из него. Итак, что означает эта ошибка и как ее разрешить?

Обновление

Вот код, который я использую, чтобы создать DataCacheFactory и вытащить данные из кеша:

private static readonly Lazy<DataCacheFactory> _DATA_CACHE_FACTORY = new Lazy<DataCacheFactory>(() => new DataCacheFactory());
private static readonly Lazy<DataCache> _CACHE = new Lazy<DataCache>(() => _DATA_CACHE_FACTORY.Value.GetDefaultCache());

public object Get(string key)
{
    return _CACHE.Value.Get(key);
}

Ответ 1

Я на 100% уверен, что дублируемая ошибка ключа генерируется плохим доступом к частному _myCache свойству DataCacheFactory. Это свойство Hashtable. Повторные вызовы Hashtable.Add("mykey","myvalue"); будут генерировать то же самое, что и ваш вид.

Я запускал несколько тестов, а вызов GetCache("default") и GetDefaultCache() назад не приводит к ошибке. Это определенно что-то странное в том, как приложение Fabric пытается заполнить это. Вот мой код, который никогда не генерировал эту ошибку. Я хотел опубликовать для ссылки, вы можете увидеть что-то, что явно отличается от того, что делает ваш код.

if (cache == null)
{
    if(factory == null)
        factory = new DataCacheFactory();

    if(string.IsNullOrWhiteSpace(cacheName))
        cacheName = ConfigurationManager.AppSettings["APP_FABRIC_CACHE_NAME"];

    cache = factory.GetCache(cacheName);
    return cache;
}

В приведенном выше примере cache и factory являются версиями private static их соответствующих типов, внутри статического класса cache.

Надеюсь, что это поможет

Ответ 2

Мы используем блокировку вокруг нашего factory создания и никогда не сталкивались с этой проблемой. Мы также используем AppFab 1.1 для нашего кластера. Я бы порекомендовал вам сделать что-то вроде этого:

lock (cacheLock)
{
    if(cacheFactory == null)
    {
        DataCacheFactoryConfiguration config = new DataCacheFactoryConfiguration(...); 
        cacheFactory = new DataCacheFactory(config);
    }
    return cacheFactory;
}