如何在redis服务器重启/扩展后重新连接redis客户端

问题描述 投票:0回答:1

我有一个 Azure 应用程序服务(基于 Docker),它使用 Redis 作为缓存。当我重新启动/扩展 Redis 服务器时,azure 应用程序服务内的 Redis 客户端与服务器失去连接并引发以下异常:

等待响应超时(出站=0KiB,入站=0KiB,已过去2852ms,超时为2000ms),command=SETEX,next:GET test,inst:0,qu:0,qs:45,aw:False,rs:ReadAsync, ws:空闲,在:0,serverEndpoint:未指定/redis-server-com:6380,mgr:10个可用,共10个,clientName:wallet-api,IOCP:(Busy = 0,Free = 1000,Min = 4,Max = 1000), WORKER: (Busy=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连接已建立:

就在再次建立连接之前,我遇到了以下 2 个异常,我猜每个连接都有一个:

redis-server.com 上的 SocketFailure:6380/Interactive,空闲/故障,最后:GET,来源:ReadFromPipe,未完成:52,上次读取:982 秒前,上次写入:6 秒前,未应答写入:938 秒前,保持活动:60 秒,状态:ConnectedEstablished,mgr:10 个可用中的 9 个,在:0,最后一次心跳:0 秒前,最后一次心跳:0 秒前,全局:0 秒前,v:2.0.601.3402 <--- Unable to read data from the transport connection: Connection timed out. <--- Connection timed out

redis-server.com:6380/Subscription 上的 SocketFailure,空闲/故障,最后:PING,来源:ReadFromPipe,未完成:16,上次读取:998 秒前,上次写入:36 秒前,保持活动:60 秒,状态:ConnectedEstablished,mgr:10 个可用中的 9 个,in:0,last-heartbeat:0 秒前,last-mbeat:0 秒前,全局:0 秒前,v:2.0.601.3402 <--- Unable to read data from the transport connection: Connection timed out. <--- Connection timed out

为什么连接不刷新?有什么办法可以改善重新连接吗? 15 分钟对于生产环境来说太多了。

更新 03/09/2020。我做了一个快速测试,使用相同的客户端重新启动 Redis 服务器,但使用通过 SSL(端口 6380)的安全连接和普通连接(端口 6379)。使用普通连接检查 netstat (netstat -ptona),redis 客户端重新连接成功。然而,在启用 SSL 的情况下再次检查,连接保持建立,但 Redis 服务器没有响应。

可能的解决方法:它看起来像是与框架相关的东西。正如 @Json Pan 在他的回复中建议的那样,我将尝试升级到 netcore 3.1 并强制应用程序定期刷新连接。

redis azure-web-app-service asp.net-core-2.1 azure-redis-cache
1个回答
1
投票

更新

读完这篇博客后,我修改了源代码,将项目从.net core 1.0升级到3.1。

我建议你可以尝试一下或者在你的项目中修改它,以测试重新连接时间。

私密

我建议您使用使用惰性模式重新连接

ConnectionMultiplexer 如何处理断开连接?中的答案将对您有用。

© www.soinside.com 2019 - 2024. All rights reserved.