如何在redis服务器重新启动/缩放后重新连接redis客户端

wn9m85ua  于 2021-06-08  发布在  Redis
关注(0)|答案(1)|浏览(431)

我有一个azure应用服务(基于docker),它使用redis作为缓存。当我重新启动/缩放redis服务器时,azure应用程序服务内的redis客户端与服务器失去连接,并引发以下异常:
等待响应超时(outbound=0kib,inbound=0kib,经过2852ms,超时为2000ms),command=setex,next:get test,inst:0,qu:0,qs:45,aw:false,rs:readasync,ws:idle,in:0,serverendpoint:unspecified/redis server-com:6380,mgr:10/10可用,clientname:wallet api,iocp:(忙=0,空闲=1000,最小=4,最大=1000),worker:(忙=1,free=32766,min=4,max=32767),v:2.0.601.3402(请参阅本文了解一些可能导致超时的常见客户端问题:https://stackexchange.github.io/stackexchange.redis/timeouts)
从azure应用程序服务重新连接redis服务器需要15分钟,但如果我在应用程序启动后立即重新启动应用程序服务,则redis客户端连接将成功建立。从文档中可以看出,connectionmultiplexor对象应该管理重新连接,但它看起来不像是在做他的工作。
redis客户端代码如下:

public class RedisStore : IRedisStore, IDisposable
{

    private readonly ConfigurationOptions _options;
    private static IConnectionMultiplexer _connection;

    public RedisStore(RedisConfiguration redisConfiguration)
    {
        _options = ConfigurationOptions.Parse(redisConfiguration.ConnectionString);
        _options.ReconnectRetryPolicy = new ExponentialRetry(redisConfiguration.RetryFromMilliSeconds);
    }

    async Task IRedisStore.InitializeConnection()
    {
        if (_connection == null)
        {
            _connection = await ConnectionMultiplexer.ConnectAsync(_options);
        }
    }

    async Task<T> IRedisStore.SetGet<T>(string key)
    {
        var value = await _connection.GetDatabase().StringGetAsync(key);

        if (value.IsNull)
            return default(T);

        return JsonConvert.DeserializeObject<T>(value);
    }

    async Task IRedisStore.SetStore<T>(string key, T value)
    {
        var serialized = JsonConvert.SerializeObject(value);
        await _connection.GetDatabase().StringSetAsync(key, serialized);
    }

    void IDisposable.Dispose()
    {
        _connection.Dispose();
    }
}

redis连接是从引导代码初始化的:

private async Task InitializeRedis()
    {
        var redis = Container.GetInstance<IRedisStore>();
        await redis.InitializeConnection();
    }

另外,当应用程序服务抛出redis超时异常时,netstat显示redis连接已建立:

在再次建立连接之前,我得到了以下两个例外,我猜每个连接都有一个例外:
redis服务器上的socketfailure。com:6380/interactive,空闲/出现故障,最后一次:get,原点:readfrompipe,未完成:52,最后一次读取:982s前,最后一次写入:6s前,未应答的写入:938s前,保持活动状态:60s,状态:connectedestablished,mgr:9/10可用,in:0,最后一次心跳:0s前,最后一次mbeat:0s前,全局:0s前,v:2.0.601.3402<---无法从传输连接读取数据:连接超时。<--连接超时
redis服务器上的socketfailure。com:6380/subscription,空闲/故障,上次:ping,源:readfrompipe,未完成:16,上次读取:998s前,上次写入:36s前,保持活动状态:60s,状态:connectedestablished,mgr:9/10可用,in:0,上次心跳:0s前,上次mbeat:0s前,全局:0s前,v:2.0.601.3402<---无法从传输连接读取数据:连接超时。<--连接超时
为什么不刷新连接?有没有办法改善重连?15分钟对于生产环境来说太多了。
更新日期:03/09/2020。我做了一个快速测试,用同一个客户端重新启动redis服务器,但是使用了通过ssl的安全连接(端口6380)和普通连接(端口6379)。用普通连接检查netstat(netstat-ptona),redis客户端重新连接成功。但是,在启用ssl的情况下再次检查时,连接保持建立,但redis服务器没有响应。
可能的解决方法:它看起来像与框架相关的东西。正如@json pan在回复中所建议的,我将尝试升级到netcore3.1并强制应用程序定期刷新连接。

uurity8g

uurity8g1#

更新
读完这个博客后,我修改了源代码,将项目从.NETCore1.0升级到3.1。
我建议您可以在项目中尝试或修改它,以测试重新连接时间。
你可以下载我的示例代码。
私下的
我建议你用懒模式重新连接。
而connectionmultiplexer如何处理断开连接?中的答案将对您有用。

相关问题