簡體   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