Redis服务器重启/缩放后如何重新连接Redis客户端 [英] How to reconnect redis client after redis server reboot/scale

查看:123
本文介绍了Redis服务器重启/缩放后如何重新连接Redis客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Redis作为缓存的Azure应用服务(基于Docker).重新引导/缩放Redis服务器时,Azure应用程序服务中的Redis客户端失去与服务器的连接,并引发以下异常:

超时等待响应(出站= 0KiB,入站= 0KiB,经过2852ms,超时为2000ms),命令= SETEX,下一条:GET测试,inst:0,qu:0,qs:45,aw:False,rs:ReadAsync,ws:空闲,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(请查看本文,了解一些可能导致超时的常见客户端问题:

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

redis-server.com上的SocketFailure:6380/Interactive,Idle/Faulted,last:GET,origin:ReadFromPipe,杰出:52,last-read:982s ago,last-write:6s ago,unanswer-write:938sago,keep-alive:60s,状态:ConnectedFounded,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上的SocketFailure:6380/订阅,空闲/故障,上次:PING,来源:ReadFromPipe,未完成:16,上次阅读:998s前,上次写入:36s前,keep-alive:60s,状态:ConnectedFounded,mgr:9(共10个),可用:0,last-heartbeat:0s之前,last-mbeat:0s之前,global:0s之前,v:2.0.601.3402< ---无法读取数据传输连接:连接超时.< ---连接超时

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

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

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

解决方案

更新

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

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

您可以下载我的示例代码.

重要

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

> ConnectionMultiplexer如何处理断开连接?对您有用.

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:

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)

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. From documentation, ConnectionMultiplexor object should manage reconnection, but it does not look like he is doing his job.

Here the redis client code:

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:

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:

Just before to establish connection again, I got the following 2 exceptions, I guess one for each connection:

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. <--- 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. <--- Connection timed out

Why connection is not refreshed? Is there any way to improve reconnection? 15min is too much for a production environment.

UPDATE 03/09/2020. 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). Checking netstat (netstat -ptona) with a plain connection, redis client reconnect successfully. However checking again with SSL enabled, connection keeps established but there is no response from redis server.

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.

解决方案

UPDATE

After read this blog, I modify the source code, upgrade the project from .net core 1.0 to 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.

And the answer in How does ConnectionMultiplexer deal with disconnects?, will useful to you.

这篇关于Redis服务器重启/缩放后如何重新连接Redis客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆