Wat 是运行 .NET Core 2.1 WebApi 的最佳 Azure REDIS Stackexchange 配置和使用方法

Jon*_*rix 6 c# azure redis stackexchange.redis asp.net-core

我在两个 P3V2 实例上的 Azure 应用服务上运行 .NET Core 2.1 Web api。使用 StackExchange Redis 客户端连接到 Azure REDIS 服务 Premium P1。

目前我们的峰值负载约为每秒 7000 个 Web 请求。导致 REDIS 负载为 2.5MB/秒,最大缓存命中值为每分钟 400k(Azure 指标)。

最近我遇到了连接问题,因此我正在调查所有可用的文档: https: //learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-best-practices https:// stackexchange.github.io/StackExchange.Redis/Basics.html

没有可用的连接来服务此操作:GET 语言;无法连接到 Redis 服务器;ConnectTimeout 发生一个或多个错误。(无法连接到 Redis 服务器;ConnectTimeout)(无法连接到 Redis 服务器;ConnectTimeout)无法连接到 Redis 服务器;ConnectTimeout 无法连接到 redis 服务器;连接超时

StackExchange.Redis.RedisConnectionException:在 StackExchange.Redis.ConnectionMultiplexer.ThrowFailed (StackExchange.Redis,版本=1.2.6.0,文化=中性,PublicKeyToken=nullStackExchange.Redis,版本=1.2.6.0,文化=中性,PublicKeyToken=null:c :\ code \ StackExchange.Redis \ StackExchange.Redis \ StackExchange \ Redis \ ConnectionMultiplexer.csStackExchange.Redis,版本= 1.2.6.0,文化=中性,PublicKeyToken = null:2000)在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(系统) .Private.CoreLib,版本=4.0.0.0,文化=中性,PublicKeyToken=7cec85d7bea7798e)在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Private.CoreLib,版本=4.0.0.0,文化=中性,PublicKeyToken=7cec85d7bea7798e)在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib,版本 = 4.0.0.0,文化 = 中性,PublicKeyToken = 7cec85d7bea7798e)在 Infrastructure.Caching.CacheService+d__8`1.MoveNext

重新启动网络应用程序后,问题就解决了。在 Application Insights 中并查看失败的请求,我无法清楚地看出它是只有一个 api 实例还是在所有实例上。但看看客户端应用程序,我们认为这只是一个实例。

我的实现如下:

    public static ConnectionMultiplexer Connection => LazyConnection.Value;

    protected override IDatabase Cache => Connection.GetDatabase();

    private static readonly Lazy<ConnectionMultiplexer> LazyConnection =
        new Lazy<ConnectionMultiplexer>(() =>
        {
            var configurationOptions = CreateConfigurationOptions();
            return ConnectionMultiplexer.Connect(configurationOptions);
        });

    protected static ConfigurationOptions CreateConfigurationOptions()
    {
        var deltaBackOffInMilliseconds = TimeSpan.FromSeconds(5).Milliseconds;
        var maxDeltaBackOffInMilliseconds = TimeSpan.FromSeconds(20).Milliseconds;

        var config = new ConfigurationOptions();

        //https://learn.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#azure-redis-cache-retry-guidelines
        config.AbortOnConnectFail = false;
        config.ConnectRetry = 3;
        config.ConnectTimeout = _redisConfiguration.ConnectionTimeoutInMs;
        config.ReconnectRetryPolicy = new ExponentialRetry(deltaBackOffInMilliseconds, maxDeltaBackOffInMilliseconds);

        config.EndPoints.Add(_redisConfiguration.HostName);
        config.Password = _redisConfiguration.Password;
        config.Ssl = _redisConfiguration.Ssl;
        config.DefaultDatabase = _redisConfiguration.DatabaseId;

        return config;
    }
Run Code Online (Sandbox Code Playgroud)

问题1:异步连接

我的 Web api 是完全异步的(从控制器到 SQL 和 REDIS)。那么是否还建议从 ConnectionMultiplexer 实现 ConnectAsync 方法?

问题2:自定义强制重新连接(已回答)

由于https://github.com/StackExchange/StackExchange.Redis/issues报告了一些 SE.Redis 问题,降级回 1.2.6 应该会有所帮助,我也降级到这个版本。但它并没有解决我的连接问题。

我偶然发现了 Jon Cole 的代码示例: https: //gist.github.com/JonCole/925630df72be1351b21440625ff2671f#file-redis-lazyreconnect-cs 我将结合当前的 SE.Redis 1.2.6 来实现它版本。但我有疑问,更新(回)到最新的 SE.Redis 版本时是否仍然有必要?

编辑:乔恩·科尔给出了答案。每当遇到连接问题时,您可能仍想添加此 ForceReconnect。与您使用的 SE.Redis 版本无关。来源:https ://gist.github.com/JonCole/925630df72be1351b21440625ff2671f#gistcomment-3025550

因为网络 blips 或 -drops 很难在相同的负载下调试或重现(本地或临时环境),所以我被迫在生产中进行测试。