GetClient调用上的Redis Timeout Expired消息

时间:2013-10-23 14:32:37

标签: redis servicestack.redis redisclient

我讨厌那些“没有足够信息”的问题。所以我会尝试提供详细信息。在这种情况下,它是代码。

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

有三个类:

DbOperationContext.cs https://gist.github.com/glikoz/7119628

PerRequestLifeTimeManager.cs https://gist.github.com/glikoz/7119699

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

我们正在使用Redis和Unity ..

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

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

我们检查了这些:

  • 问题配置问题

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

  • 是否有任何架构问题

有什么想法吗?有类似的故事吗?

感谢。

额外信息1

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

1 个答案:

答案 0 :(得分:10)

我继续调试此问题,并在我的平台上修复了许多内容以避免此异常。以下是我为解决这个问题所做的工作:

执行摘要:

遇到此异常的人应该检查:

  1. PooledRedisClientsManager(IRedisClientsManager)在单一范围内注册
  2. RedisMqServer(IMessageService)在单一范围内注册
  3. 从上述任何一个中返回的任何已使用的RedisClient都已​​妥善处置,以确保合并的客户端不会过时。
  4. 我的问题的解决方案:

    首先,PooledRedisClient because it has no more pooled connections available抛出此异常。

    我正在StructureMap IoC容器中注册所有必需的Redis内容(不像作者的情况那样是统一的)。感谢this post我被提醒说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被正确处理是非常重要的,否则我们会遇到可怕的“Timeout Expired”(感谢this post)。我有以下帮助程序代码将消息发送到队列:

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

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