简体   繁体   English

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

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

I have an azure app service (based on Docker) that uses Redis as a cache memory. When I reboot/scale redis server, redis client inside azure app service lose connection with server and throws the following exception:我有一个 azure 应用程序服务(基于 Docker),它使用 Redis 作为缓存 memory。当我重新启动/扩展 redis 服务器时,azure 应用程序服务中的 redis 客户端失去与服务器的连接并抛出以下异常:

Timeout awaiting response (outbound=0KiB, inbound=0KiB, 2852ms elapsed, timeout is 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 of 10 available, 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 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts )超时等待响应(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/超时

It takes up to 15min to reconnect with redis server from azure app service, however if I restart app service as soon as app is up, redis client connection is established successfully.从 azure 应用程序服务重新连接 redis 服务器最多需要 15 分钟,但是如果我在应用程序启动后立即重新启动应用程序服务,则 redis 客户端连接已成功建立。 From documentation, ConnectionMultiplexor object should manage reconnection, but it does not look like he is doing his job.从文档来看,ConnectionMultiplexor object 应该管理重新连接,但看起来他没有在做他的工作。

Here the redis client code:这里是 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();
    }
}

The redis connection is initialized from bootstrap code: redis 连接是从引导代码初始化的:

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

Also, while app service is throwing redis timeout exceptions,.netstat displayed that redis connection is established:此外,当应用服务抛出 redis 超时异常时,.netstat 显示 redis 连接已建立:

在此处输入图像描述

Just before to establish connection again, I got the following 2 exceptions, I guess one for each connection:就在再次建立连接之前,我得到了以下 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 <--- Unable to read data from the transport connection: Connection timed out. 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 <--- 无法从传输连接读取数据:连接超时。 <--- Connection timed out <--- 连接超时

SocketFailure on redis-server.com:6380/Subscription, Idle/Faulted, last: PING, origin: ReadFromPipe, outstanding: 16, last-read: 998s ago, last-write: 36s 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 <--- Unable to read data from the transport connection: Connection timed out. 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 <--- 无法从传输连接读取数据:连接超时。 <--- Connection timed out <--- 连接超时

Why connection is not refreshed?为什么不刷新连接? Is there any way to improve reconnection?有什么方法可以改善重新连接吗? 15min is too much for a production environment. 15 分钟对于生产环境来说太多了。

UPDATE 03/09/2020 . 2020 年 3 月 9 日更新 I did a quick test rebooting redis server with same client but using a secured connection via SSL (port 6380) and a plain connection (port 6379).我做了一个快速测试,使用相同的客户端重新启动 redis 服务器,但使用通过 SSL(端口 6380)和普通连接(端口 6379)的安全连接。 Checking.netstat ( netstat -ptona ) with a plain connection, redis client reconnect successfully.使用普通连接检查 netstat ( netstat -ptona ),redis 客户端重新连接成功。 However checking again with SSL enabled, connection keeps established but there is no response from redis server.然而,在启用 SSL 的情况下再次检查,连接保持建立但没有来自 redis 服务器的响应。

Possible workaround : It looks like something related to framework.可能的解决方法:它看起来像是与框架相关的东西。 As @Json Pan suggested in his reply, I will try upgrading to.netcore 3.1 and force app to refresh connection periodically.正如@Json Pan 在他的回复中建议的那样,我将尝试升级到.netcore 3.1 并强制应用程序定期刷新连接。

UPDATE更新

After read this blog, I modify the source code, upgrade the project from .net core 1.0 to 3.1.看完这篇博文,修改源码,将项目从.net core 1.0升级到3.1。

I suggest you can try it or modify it in your project, to test reconnect time.我建议您可以在您的项目中尝试或修改它,以测试重新连接时间。

You can download my sample code .您可以下载我的示例代码

PRIVIOUS私人的

I recommand you use Reconnecting with Lazy pattern .我建议您使用Reconnecting with Lazy pattern

And the answer in How does ConnectionMultiplexer deal with disconnects? ConnectionMultiplexer 如何处理断开连接中的答案? , will useful to you. ,对你有用。

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

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