GetClient调用上的Redis Timeout Expired消息

ozz*_*ozz 7 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命令检查了它)

nov*_*ver 10

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

执行摘要:

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

  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);
 });
Run Code Online (Sandbox Code Playgroud)

我的"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;
 }
Run Code Online (Sandbox Code Playgroud)

然后,当涉及到生成消息时,使用RedisClient被正确处理是非常重要的,否则我们会遇到可怕的"Timeout Expired"(感谢这篇文章).我有以下帮助程序代码将消息发送到队列:

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;
}
Run Code Online (Sandbox Code Playgroud)

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