我一直在调试这个问题,并在我的平台上修复了很多东西以避免这个异常。这是我为解决该问题所做的工作:
执行摘要:
遇到此异常的人应检查:
- PooledRedisClientsManager (IRedisClientsManager) 在单例范围内注册
- RedisMqServer (IMessageService) 在单例范围内注册
- 从上述任一方法返回的任何已使用 RedisClient 都已正确处理,以确保池化客户端不会过期。
我的问题的解决方案:
首先,这个异常是由 PooledRedisClient 抛出的,因为它没有更多可用的池连接。
我在 StructureMap IoC 容器中注册了所有必需的 Redis 内容(不像作者的情况那样统一)。感谢这篇文章,我被提醒 PooledRedisClientManager 应该是单例 - 我还决定将 RedisMqServer 注册为单例:
ObjectFactory.Configure(x =>
{
// register the message queue stuff as Singletons in this AppDomain
x.For<IRedisClientsManager>()
.Singleton()
.Use(BuildRedisClientsManager);
x.For<IMessageService>()
.Singleton()
.Use<RedisMqServer>()
.Ctor<IRedisClientsManager>().Is(i => i.GetInstance<IRedisClientsManager>())
.Ctor<int>("retryCount").Is(2)
.Ctor<TimeSpan?>().Is(TimeSpan.FromSeconds(5));
// Retrieve a new message factory from the singleton IMessageService
x.For<IMessageFactory>()
.Use(i => i.GetInstance<IMessageService>().MessageFactory);
});
我的“BuildRedisClientManager”函数如下所示:
private static IRedisClientsManager BuildRedisClientsManager()
{
var appSettings = new AppSettings();
var redisClients = appSettings.Get("redis-servers", "redis.local:6379").Split(',');
var redisFactory = new PooledRedisClientManager(redisClients);
redisFactory.ConnectTimeout = 5;
redisFactory.IdleTimeOutSecs = 30;
redisFactory.PoolTimeout = 3;
return redisFactory;
}
然后,在产生消息时,正确处理使用的 RedisClient 非常重要,否则我们会遇到可怕的“超时过期”(感谢这篇文章)。我有以下帮助代码向队列发送消息:
public static void PublishMessage<T>(T msg)
{
try
{
using (var producer = GetMessageProducer())
{
producer.Publish<T>(msg);
}
}
catch (Exception ex)
{
// TODO: Log or whatever... I'm not throwing to avoid showing users that we have a broken MQ
}
}
private static IMessageQueueClient GetMessageProducer()
{
var producer = ObjectFactory.GetInstance<IMessageService>() as RedisMqServer;
var client = producer.CreateMessageQueueClient();
return client;
}
我希望这也有助于解决您的问题。