Почему соединения с Azure Redis Cache настолько высоки?

Я использую кэш-память Azure Redis в сценарии высокой нагрузки для одной машины, запрашивающей кеш. Эта машина грубо получает и устанавливает около 20 единиц в секунду. В дневное время это увеличивается, в ночное время это меньше.

Пока все работает нормально. Сегодня я понял, что показатель "Connected Clients" чрезвычайно высок, хотя у меня только 1 клиент, который просто постоянно получает и устанавливает элементы. Вот скриншот показателя, который я имею в виду: Redis Cache Connected Clients

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

public class RedisCache<TValue> : ICache<TValue>
{
    private IDatabase cache;
    private ConnectionMultiplexer connectionMultiplexer;

    public RedisCache()
    {
        ConfigurationOptions config = new ConfigurationOptions();
        config.EndPoints.Add(GlobalConfig.Instance.GetConfig("RedisCacheUrl"));
        config.Password = GlobalConfig.Instance.GetConfig("RedisCachePassword");
        config.ConnectRetry = int.MaxValue; // retry connection if broken
        config.KeepAlive = 60; // keep connection alive (ping every minute)
        config.Ssl = true;
        config.SyncTimeout = 8000; // 8 seconds timeout for each get/set/remove operation
        config.ConnectTimeout = 20000; // 20 seconds to connect to the cache

        connectionMultiplexer = ConnectionMultiplexer.Connect(config);
        cache = connectionMultiplexer.GetDatabase();
    }

    public virtual bool Add(string key, TValue item)
    {
        return cache.StringSet(key, RawSerializationHelper.Serialize(item));
    }

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

Ответ 1

У StackExchange.Redis было состояние гонки, которое может привести к утечкам соединений при некоторых условиях. Это было исправлено в версии 1.0.333 или новее.

Если вы хотите подтвердить, что это проблема, которую вы нажимаете, получите дамп аварийной ситуации вашего клиентского приложения и посмотрите на объекты в куче в отладчике. Найдите большое количество объектов StackExchange.Redis.ServerEndPoint.

Кроме того, у нескольких пользователей были ошибки в их коде, которые привели к утечке объектов подключения. Это часто происходит потому, что их код пытается воссоздать объект ConnectionMultiplexer, если они видят сбои или отключенное состояние. Нет необходимости воссоздавать ConnectionMultiplexer, поскольку он имеет внутреннюю логику для воссоздания соединения по мере необходимости. Просто убедитесь, что в строке подключения abortConnect установлено значение false.

Если вы решили повторно создать объект подключения, обязательно удалите старый объект, прежде чем выпустить все ссылки на него.

Ниже приведен шаблон, который мы рекомендуем:


        private static Lazy lazyConnection = new Lazy(() => {
            return ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
        });

        public static ConnectionMultiplexer Connection {
            get {
                return lazyConnection.Value;
            }
        }