使用 Stackexchange Redis 时,会创建数千个连接

When using Stackexchange Redis thousands of connections are being created

我们刚刚开始使用来自 Web 和辅助角色的 Azure Redis 缓存。我们发现在相当轻的使用下,创建了 ~2.5K 连接。

我们正在使用包裹在连接管理器中的 StackExchange.Redis nuget 包

  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;
}

然后 class 在需要的地方被注入依赖的 classes 使用 Ninject 作为一个单例

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

然后消费如下

 var cache = this.redisConnManager.Connection.GetDatabase();
                key = cachable.GenerateKey();
                RedisValue result = cache.StringGet(key);

我检查过 ConnectionManager 的构造函数没有被调用超过一次

我们应该看到这么多连接吗?

每次使用 LazyConnection 属性 时,您都在创建 Lazy 对象。这是非常错误的。

您应该只创建 Lazy 对象一次,例如在构造函数中:

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; } }
}

但是同样,如果您多次创建 class,您将拥有多个 Lazy 对象,因此会产生多个连接。 您可能应该对其进行静态编码:

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; } }
}

现在 lazyConnection 是静态的,因此将在 class 的所有实例之间共享,并且只会创建一次。 额外的锁机制代码是为了避免有多个线程创建惰性对象。

考虑将 configuration 字段设为静态。