繁体   English   中英

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

[英]How to reconnect redis client after redis server reboot/scale

我有一个 azure 应用程序服务(基于 Docker),它使用 Redis 作为缓存 memory。当我重新启动/扩展 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 :空闲,in:0,serverEndpoint:未指定/redis-server-com:6380,mgr:10 个中的 10 个可用,clientName:wallet-api,IOCP:(忙= 0,空闲= 1000,最小= 4,最大= 1000 ), WORKER: (Busy=1,Free=32766,Min=4,Max=32767), v: 2.0.601.3402 (请查看这篇文章了解一些可能导致超时的常见客户端问题: https:/ /stackexchange.github.io/StackExchange.Redis/超时

从 azure 应用程序服务重新连接 redis 服务器最多需要 15 分钟,但是如果我在应用程序启动后立即重新启动应用程序服务,则 redis 客户端连接已成功建立。 从文档来看,ConnectionMultiplexor object 应该管理重新连接,但看起来他没有在做他的工作。

这里是 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 个异常,我猜每个连接一个:

SocketFailure on redis-server.com:6380/Interactive, Idle/Faulted, last: GET, origin: ReadFromPipe, outstanding: 52, last-read: 982s ago, last-write: 6s ago, unanswered-write: 938s ago, keep -alive: 60s, state: ConnectedEstablished, mgr: 9 of 10 available, in: 0, last-heartbeat: 0s ago, last-mbeat: 0s ago, global: 0s ago, v: 2.0.601.3402 <--- 无法从传输连接读取数据:连接超时。 <--- 连接超时

redis-server.com:6380/订阅上的 SocketFailure,空闲/故障,最后:PING,来源:ReadFromPipe,未完成:16,最后读取:998 秒前,最后写入:36 秒前,保持活动:60 秒,state: ConnectedEstablished, mgr: 9 of 10 available, in: 0, last-heartbeat: 0s ago, last-mbeat: 0s ago, global: 0s ago, v: 2.0.601.3402 <--- 无法从传输连接读取数据:连接超时。 <--- 连接超时

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

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

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

更新

看完这篇博文,修改源码,将项目从.net core 1.0升级到3.1。

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

您可以下载我的示例代码

私人的

我建议您使用Reconnecting with Lazy pattern

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM