7

我讨厌“信息不足”的问题。所以我会尽量提供详细的信息。在这种情况下,它是代码。

服务器:64位https://github.com/MSOpenTech/redis/tree/2.6/bin/release

分为三类:

DbOperationContext.cshttps ://gist.github.com/glikoz/7119628

PerRequestLifeTimeManager.cshttps ://gist.github.com/glikoz/7119699

RedisRepository.cs https://gist.github.com/glikoz/7119769

我们正在使用 Redis 和 Unity ..

在这种情况下,我们会收到这条奇怪的消息:

“Redis Timeout 已过期。从池中获取连接之前的超时期限已过。这可能是因为所有池连接都在使用中。”;

我们检查了这些:

  • 是问题配置问题

  • 我们是否使用了错误的 RedisServer.exe

  • 有没有架构问题

任何想法?有没有类似的故事?

谢谢。

额外信息 1

服务器统计信息上没有被拒绝的连接问题(我已经通过 redis-cli.exe info 命令检查了它)

4

1 回答 1

11

我一直在调试这个问题,并在我的平台上修复了很多东西以避免这个异常。这是我为解决该问题所做的工作:

执行摘要:

遇到此异常的人应检查:

  1. PooledRedisClientsManager (IRedisClientsManager) 在单例范围内注册
  2. RedisMqServer (IMessageService) 在单例范围内注册
  3. 从上述任一方法返回的任何已使用 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;
}

我希望这也有助于解决您的问题。

于 2013-11-13T15:45:21.593 回答