Ao usar Stackexchange Redis milhares de conexões estão sendo criadas

Acabamos de começar a usar o Cache Azure Redis da web e dos papéis dos trabalhadores. Nós descobrimos que sob o uso razoavelmente leve ~2,5 K conexões foram criadas.

Estamos a usar o StackExchange.Redis pacote nuget embrulhado num gestor de ligações

  public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public Lazy<ConnectionMultiplexer> LazyConnection
    {
        get
        {
            return new Lazy<ConnectionMultiplexer>(
                () => ConnectionMultiplexer.Connect(
                    this.configuration.SessionManagerRedisConnectionString));
        }
    }
    public ConnectionMultiplexer Connection => this.LazyConnection.Value;
}

A classe é então injectada, quando necessário, em classes dependentes utilizando Ninject como singleton

           kernel.Bind<RedisConnManager>().To<RedisConnManager>().InSingletonScope();

e depois consumido da seguinte forma

 var cache = this.redisConnManager.Connection.GetDatabase();
                key = cachable.GenerateKey();
                RedisValue result = cache.StringGet(key);
Eu verifiquei que o construtor do ConnectionManager não é chamado mais de uma vez

Devemos estar a ver tantas ligações?

Author: thepirat000, 2015-11-16

2 answers

Você está criando o objeto preguiçoso cada vez que a propriedade LazyConnection é usada. Isto é muito errado.

Você deve criar o objeto preguiçoso apenas uma vez, por exemplo no construtor:

public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
        lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(
                configuration.SessionManagerRedisConnectionString));
    }

    private Lazy<ConnectionMultiplexer> lazyConnection;

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

Mas novamente, se você está criando a classe várias vezes, você terá vários objetos preguiçosos, ergo múltiplas conexões. Você provavelmente deve codificá-lo estaticamente:

public class RedisConnManager
{
    private readonly IConfiguration configuration;

    public RedisConnManager(IConfiguration configuration)
    {
        this.configuration = configuration;
        lock (locker)
        {
            if (lazyConnection == null)
            {
                lazyConnection = new Lazy<ConnectionMultiplexer>(() => new ConnectionMultiplexer(this.configuration));
            }
        }
    }
    private static Lazy<ConnectionMultiplexer> lazyConnection;
    private static readonly object locker = new object();
    public ConnectionMultiplexer Connection { get { return lazyConnection.Value; } }
}

Agora o {[3] } é estático, assim será compartilhado por todas as instâncias da classe e será criado apenas quando. O código do mecanismo de bloqueio extra é evitar ter mais de um tópico criando o objeto preguiçoso.

Considere também tornar o campo configuration estático.

 3
Author: thepirat000, 2015-11-17 01:00:58

Ou ainda melhor se você usar um coi configure - o para criar uma única instância dele em vez de tê-lo como um adereço estático. Vai tornar os testes de unidade muito mais fáceis.

 0
Author: Ilias.P, 2021-02-05 03:07:04