使用 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
字段设为静态。
我们刚刚开始使用来自 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
字段设为静态。