我在servicestack API中使用ServiceStack.Redis池化客户端,经过几个小时的流量大约3000rpm后,我从池管理器收到连接超时异常。实施如下:
在AppStart中:
container.Register<IRedisClientsManager>(
p => new RedisManagerPool(Configuration.Config.Instance.RedisConfig.Server)
{
MaxPoolSize = 10000,
PoolTimeoutMs = 2000
}).ReusedWithin(ReuseScope.Container);
在服务中:
Pool = (RedisManagerPool) GetResolver().TryResolve<IRedisClientsManager>();
RedisClient = (RedisClient)Pool.GetClient();
....
RedisClient.Dispose();
我还尝试使用Pool.DisposeClient(RedisClient)处理客户端,以便将客户端返回到池中,但我看到了相同的结果。
我还检查了Redis服务器,但没有CPU使用,内存使用,0拒绝连接等问题。
如果有人遇到这个,你能告诉我吗?
谢谢
答案 0 :(得分:3)
我不会有一个大的池大小,保持 10000 打开连接似乎比没有任何连接池更糟糕。
您也不需要指定ReuseScope.Container
,因为默认情况下使用的单例是管理器/工厂的正确范围,所以我首先尝试默认配置:
container.Register<IRedisClientsManager>(c =>
new RedisManagerPool(Configuration.Config.Instance.RedisConfig.Server));
池超时异常表明连接池已填满,并且池超时内没有任何连接被释放(即处置)。
我建议使用RedisManagerPool
that's on MyGet的最新v4.0.34有一个备用池策略,一旦连接池已满,将创建新的非托管池实例,而不是在池超时后锁定和抛出已经到达。
同样在您的服务中,您可以在首次访问时使用base.Redis
since it automatically creates an instance访问Redis客户端,并在执行服务后处置,即:
public class Service : IDisposable
{
private IRedisClient redis;
public virtual IRedisClient Redis
{
get { return redis ?? (redis = TryResolve<IRedisClientsManager>().GetClient()); }
}
//...
public virtual void Dispose()
{
if (redis != null)
redis.Dispose();
}
}
这有助于确保在每次请求后妥善处理Redis客户端。