StackExchange.Redis - 无法解释的超时异常问题

Nic*_*aef 4 c# redis stackexchange.redis azure-redis-cache .net-core

我们在 .NET Core 3.1 与 Azure Redis 缓存的集成中遇到了问题。抛出的异常是

执行请求时发生未处理的异常。","@l":"错误","@x":"StackExchange.Redis.RedisTimeoutException: 等待响应超时(出站 = 1403KiB,入站 = 5657KiB,已过去 15000 毫秒,超时为15000ms),command=EVAL,下一个:EVAL,inst:0,qu:0,qs:709,aw:True,rs:ReadAsync,ws:写入,in:0,serverEndpoint:redis-scr-mns-dev.redis .cache.windows.net:6380,mc:1/1/0,mgr:10 个可用,共 10 个可用,clientName:xxxxxxxxxxxx,IOCP:(忙碌 = 0,空闲 = 1000,最小 = 4,最大 = 1000),工作人员: (Busy=7,Free=32760,Min=4,Max=32767), v: 2.1.58.34321(请查看这篇文章,了解一些可能导致超时的常见客户端问题: https://stackexchange.github .io/StackExchange.Redis/超时

是的,我已经阅读了这篇文章,我们正在使用 StackExchange.Redis NuGet 包,最新版本可用。我们已经采取的步骤是

  • 使用多个值设置最小线程池计数 (ThreadPool.SetMinThreads(short.MaxValue, short.MaxValue);)
  • Redis超时值从默认的 5 秒增加到 15 秒(老实说,更高的值并不能解决这个问题,因为您将进一步阅读:))

你问的设置是什么?

  • .NET Core 3.1 REST API在最新的 IIS 上运行,在具有 16GB RAM 的 4 核 Windows 服务器上设置 3 个工作线程(在有关 CPU 或内存的监控中没有看到任何极端情况)
  • 连接到Azure Redis 缓存。目前正在运行具有高网络带宽和 23GB 内存的Basic C5(之前的带宽较低,因此我们尝试扩展此内存)
  • 最后将请求推送到 Azure 服务总线(没有问题)

一个批处理进程正在运行并处理几个 10000 个 API 调用(多个 API),其中上述调用因超时异常而导致 Redis 缓存崩溃。其他 api 运行正确并且没有超时,但当前正在连接到不同的 Redis 缓存(只是为了隔离此 api 的行为)所有 api 和/或批处理程序都使用具有缓存实现的自定义 NuGet 包,因此我们确保这不是 1 个 api(所有共享代码)中的实现问题。

我们如何使用缓存呢?好吧,通过依赖注入,我们注入 ISharedCacheStore,这只是我们自己的接口,我们放在 IDistributedCache 之上,以确保只有异步调用可用,以及 RedisCache,这是使用 Redis 的实现(ISharedCacheStore 供将来使用其他缓存机制)我们使用Microsoft.Extensions.Caching.StackExchangeRedis,版本 3.1.5,启动时的注册是

 services.Configure<CacheConfiguration>(options => configuration?.GetSection("CacheConfiguration").Bind(options))
            .AddStackExchangeRedisCache(s =>
                {
                    s.Configuration = connectionString;
                })
            .AddTransient<IRedisCache, RedisCache>()
            .AddTransient<ISharedCacheStore, SharedCacheStore>();
Run Code Online (Sandbox Code Playgroud)

老实说,我们没有想法。我们没有发现 Azure 中的 Redis 缓存实例存在问题,因为当我们遇到超时时,该实例甚至还没有接近顶部。较低定价计划的服务器负载达到约 80%,而较高定价计划的服务器负载甚至未达到当前计划的 10%。

根据 Insights 的说法,我们运行时每分钟有 4000 次缓存命中,导致大约 10% 的服务器负载。

更新:值得一提的是,批处理和 API 目前在本地环境中运行,而不是在云中。计划在未来几个月内迁移到云。这也适用于其他 api 连接到 Redis 缓存并且不会出现问题

比较

  • 另一个 Azure Redis 缓存每分钟获得 45K 次点击,没有出现任何问题(来自本地)
  • 这个已经达到了超时标准,甚至达到了每分钟 10K 次点击

Mar*_*ell 6

这里有几种可能的情况:

  1. 我不知道那EVAL是做什么的;可能正在执行的 Lua 导致了阻塞;唯一确定的方法是查看SLOWLOG,但我不知道这是否在 Azure redis 上公开
  2. 可能是您的有效负载使可用带宽饱和 - 我不知道您正在传输什么
  3. 它可能只是网络/套接字停顿/中断;它们会发生,尤其是在云环境中 - 并且(相对)高的延迟使得这尤其痛苦
  4. 我们希望启用一个新的可选池化(而不是复用)模型;从理论上讲,这可以避免大量积压(概念验证效果很好),这意味着即使套接字发生故障:也只有一个调用受到影响,而不是导致一连串的故障;这方面的限制因素是我们的时间(而且,这需要与 Redis 提供商的任何许可影响进行平衡;例如,并发连接是否有上限)
  5. 这可能只是库代码中的一个错误;如果是这样,我们在这里看不到它,但我们不使用与您相同的设置;我们尽我们所能,但很难诊断我们没有看到的问题,这些问题只出现在别人的成本设置中,我们无法轻易复制;最后加上:这不是我们的日常工作:(

我不认为这里有一个简单的“添加这一行,一切都变得很棒”的答案。这些都是重要的大规模远程场景,需要进行大量调查。简单地说:Azure 人员不会为我们的时间付费。