servicestack.redis对整数响应和零长度响应的未知响应

wmtdaxz3  于 2021-06-09  发布在  Redis
关注(0)|答案(0)|浏览(575)

我在生产中使用servicestack的redis客户端时遇到错误。
对于redisclient.containskey,错误为“unknown reply on integer response:43ok”,对于redisclient.get,错误为“zero length response”。
应用程序使用redis sentinel和poolredisclientmanager。我有 Package 类来初始化redis示例和redis操作:

public class RedisFactory : IRedisFactory
      {
        private RedisSentinel redisSentinel;
        private IRedisClientsManager clientsManager;

        public void Init()
        {
        RedisConfig.DefaultRetryTimeout = RETRY_TIMEOUT; //5000ms
        RedisClientManagerConfig config = new RedisClientManagerConfig()
        {
            MaxReadPoolSize = MAX_POOL_SIZE, //40
            MaxWritePoolSize = MAX_POOL_SIZE, //40
            DefaultDb = DEFAUTL_DB
        };

        redisSentinel = new RedisSentinel(sentinelHosts, masterName: masterName)
        {
            RedisManagerFactory = (master, slaves) => new PooledRedisClientManager(master.ToList(), slaves.ToList(), config)
            {
                NamespacePrefix = NAMESPACE_PREFIX
            },
            OnFailover = manager => _log.Info($"Fail over at {DateTime.Now}"),
            OnWorkerError = ex => _log.Error($"Sentinel worker error \n {ex}"),
            OnSentinelMessageReceived = (channel, msg) => _log.Info($"Received '{channel}' on channel '{msg}' from Sentinel")

        };

        clientsManager = redisSentinel.Start();
    }

    public bool KeyExisted(string key)
    {
        Func<string, bool> keyExisted = delegate (string k)
        {
            using (var slave = clientsManager.GetReadonlyClient())
            {
                var existed = slave.ContainsKey(k);
                return existed;
            }
        };

        return Execute(nameof(keyExisted), key, keyExisted);
    }

    public T Get<T>(string key)
    {
        Func<string, T> get = delegate (string k)
        {
            using (var slave = clientsManager.GetReadonlyClient())
            {
                var value = slave.Get<T>(k);
                return value;
            }
        };

        return Execute(nameof(get), key, get);
    }

    private T Execute<T>(string operation, string key, Func<string, T> func)
    {
        int retry = 0;

        while (true)
        {
            try
            {
                return func(key);
            }
            catch (Exception ex)
            {
                _log.Error($"Redis operation: {operation} error \n {ex}");

                if (ex is RedisException)
                {
                    if (retry >= 3) 
                    {
                        throw;
                    }

                    retry++;

                }
                else
                {
                    throw;
                }
            }
        }
    }
}

Package 器在apphost中注册为单例示例

public class AppHost : AppHostBase { public override void Configure(Container container){

    var redisFactory = new RedisFactory
    {
        MaxPoolSize = AppSettings.Get("MaxPoolSize", 40),
        MaxRetryAttempts = AppSettings.Get("MaxRetryAttempts", 3),
        RetryTimeout = AppSettings.Get("RetryTimeout", 5000),
        NameSpacePrefix = AppSettings.GetString("NameSpacePrefix"),
        DefaultDB = 13
    };  redisFactory.Init(); container.Register<IRedisFactory>(redisFactory);}}

redis工厂使用

public class MyService
    {
        private IRedisFactory cacheClient = HostContext.TryResolve<IRedisFactory>();    

        public object SomeMethod(string key) => cacheClient.Get<object>(key);
    }

我有一个redisfactory::execute中的重试函数。我注意到第一次尝试将抛出如下异常,但第二次尝试将成功。

ServiceStack.Redis.RedisResponseException: Unknown reply on integer response: 43OK
   at ServiceStack.Redis.RedisNativeClient.ReadLong()
   at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
   at ServiceStack.Redis.RedisNativeClient.SendExpectLong(Byte[][] cmdWithBinaryArgs)
   at ServiceStack.Redis.RedisClient.ContainsKey(String key)
   at RedisLibrary.RedisFactory.<KeyExisted>b__30_0(String k)

 ServiceStack.Redis.RedisResponseException: Zero length response
   at ServiceStack.Redis.RedisNativeClient.ParseSingleLine(String r)
   at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
   at ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs)
   at ServiceStack.Redis.RedisClient.<>c__DisplayClass131_0`1.<Get>b__0(RedisClient r)
   at ServiceStack.Redis.RedisClient.Exec[T](Func`2 action)
   at RedisLibrary.RedisFactory.<Get>b__31_0[T](String k)

这只发生在containskey和get操作中。添加、删除或替换仍在正常工作。
需要注意的一点是,自从我们更改redis服务器配置后,在生产中发现了以下错误:
//redis服务器配置更改

Fail over – timeout redis -cluster 5000 ->15000

  Tcp-keepalive 0 ->300

  Repl -blacklog-size 10mb -> 50mb

我尝试在测试环境中用与生产环境中相同的redis配置重现这个问题,但失败了。我还一直在寻找其他类似的问题,例如在servicestack中共享相同的redis客户端。redis client unknown reply on integer response:430k,但没有任何帮助。
有人能帮我指出我的实现或redis配置有什么问题吗?谢谢你的帮助。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题