【问题标题】:StackExchange.Redis timeoutStackExchange.Redis 超时
【发布时间】:2019-01-10 02:49:27
【问题描述】:

生产环境在 Azure 上,使用 Redis Cache Standard 2.5GB

示例 1

System.Web.HttpUnhandledException (0x80004005): 类型异常 'System.Web.HttpUnhandledException' 被抛出。 ---> StackExchange.Redis.RedisTimeoutException:执行 SETNX 超时 User.313123,inst:49,mgr:不活动,err:从不,队列:0,qu:0,qs: 0, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, clientName: PRD-VM-WEB-2, serverEndpoint:未指定/Construct3.redis.cache.windows.net:6380, keyHashSlot:15649,IOCP:(忙=0,空闲=1000,最小=1,最大=1000),工人: (忙碌=1,空闲=32766,Min=1,Max=32767) (请看这个 有关可能导致超时的一些常见客户端问题的文章: http://stackexchange.github.io/StackExchange.Redis/Timeouts) 在 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](消息 消息,ResultProcessor1 processor, ServerEndPoint server) in c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs:line 2120 at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor1 处理器,ServerEndPoint 服务器)在 c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\RedisBase.cs:line 81

示例 2

StackExchange.Redis.RedisTimeoutException:执行 GET 超时 ForumTopic.33831, inst: 1, mgr: Inactive, err: never, queue: 2, qu: 0, qs:2,qc:0,wr:0,wq:0,in:0,ar:0,clientName:PRD-VM-WEB-2, serverEndpoint:未指定/Construct3.redis.cache.windows.net:6380, keyHashSlot:5851,IOCP:(忙=0,空闲=1000,最小=1,最大=1000),工人: (忙碌=1,空闲=32766,Min=1,Max=32767) (请看这个 有关可能导致超时的一些常见客户端问题的文章: http://stackexchange.github.io/StackExchange.Redis/Timeouts) 在 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](消息 消息,ResultProcessor1 processor, ServerEndPoint server) in c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs:line 2120 at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor1 处理器,ServerEndPoint 服务器)在 c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\RedisBase.cs:line 81 在 StackExchange.Redis.RedisDatabase.StringGet(RedisKey 键, CommandFlags 标志)在 c:\code\StackExchange.Redis\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs:line 1647 在 C3.Code.Controls.Application.Caching.Distributed.DistributedCacheController.Get[T](String 缓存键)在 C:\Construct.net\Source\C3Alpha2\Code\Controls\Application\Caching\Distributed\DistributedCacheController.cs:line 115 在 C3.Code.Controls.Application.Caching.Manager.Manager.Get[T](字符串 key, Func`1 getFromExternFunction, Boolean skipLocalCaches) in C:\Construct.net\Source\C3Alpha2\Code\Controls\Application\Caching\Manager\Manager.cs:line 159 在 C3.PageControls.Forums.TopicRender.Page_Load(对象发件人, EventArgs e) 在 C:\Construct.net\Source\C3Alpha2\PageControls\Forums\TopicRender.ascx.cs:line 40 在 System.Web.UI.Control.OnLoad(EventArgs e) 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Page.ProcessRequestMain(布尔值 includeStagesBeforeAsyncPoint,布尔型 includeStagesAfterAsyncPoint)

这些错误是零星的,一天几次。

这是 Azure 网络问题,还是我可以减少的问题?查看错误中的数字似乎没有什么异常,服务器负载似乎从未超过 Azure 报告的 7%。

Redis 连接

internal static class RedisController
{
    private static readonly object GetConnectionLock = new object();
    public static ConnectionMultiplexer GetConnection()
    {
        if (Global.RedisConnection == null)
        {
            lock (GetConnectionLock)
            {
                if (Global.RedisConnection == null)
                {
                    Global.RedisConnection = ConnectionMultiplexer.Connect(
                        Settings.Deployment.RedisConnectionString);
                }
            }
        }
        return Global.RedisConnection;
    }

【问题讨论】:

  • 有几个步骤可以调查 Azure Redis 超时问题,它可能会有所帮助:azure.microsoft.com/en-us/blog/…
  • 你每秒发出多少个请求?我想知道是否有速率限制来防止可疑的 DoS 攻击。您是否尝试过在另一个服务上运行它? aws, rackspace, local,看看你是否还有超时?
  • @varlogtim 无法在另一个基础架构上测试它,因为它正在投入生产 - 开发服务器从未见过这个错误(我也在开发中使用 Redis)。
  • @TomGullen - 你能把代码 sn-p 贴在你打开 redis 客户端的地方吗?
  • 我开始认为这只是 StackExchange.Redis 客户端的一个错误。我有the same problem 并没有得到任何地方。它在我们的生产服务器上造成了很多问题。

标签: azure redis timeout stackexchange.redis


【解决方案1】:

打开网络流量监视器以确认/拒绝 blip。有一个解决问题的方法,但只是一个粗略的方法。选项 1 - 尝试在 azure 中重新启动托管的 redis 实例。

【讨论】:

    【解决方案2】:

    懒惰连接

    作为最佳实践,请确保您使用以下模式连接到 StackExchange Redis 客户端:

    private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
        return ConnectionMultiplexer.Connect("cachename.redis.cache.windows.net,ssl=true,abortConnect=false,password=password");
    });
    
    public static ConnectionMultiplexer Connection {
        get {
            return lazyConnection.Value;
        }
    }
    

    如果上述方法不起作用,Source 1 中描述了更多调试路线,涉及区域、带宽和 NuGet 包版本等。

    IO 线程

    另一个选项可能是增加最小 IO 线程。通常建议将 IOCP 和 WORKER 线程的最小配置值设置为大于默认值。对于这个值应该是什么,没有一刀切的指导,因为一个应用程序的正确值对于另一个应用程序来说太高/太低。一个好的起点是 200 或 300,然后根据需要进行测试和调整。

    如何配置此设置:

    • ASP.NET 中,使用 machine.config 中 &lt;processModel&gt; 配置元素下的 minIoThreads 配置设置。根据 Microsoft 的说法,您无法通过编辑 web.config 来更改每个站点的此值(即使您过去可以这样做),因此您在此处选择的值是所有 .NET 站点将使用的值。请注意,如果您将 autoConfig 设置为 false,则不需要添加每个属性,只需输入 autoConfig="false" 并覆盖该值即可: &lt;processModel autoConfig="false" minIoThreads="250" /&gt;

    重要提示:此配置元素中指定的值是每个核心的设置。例如,如果您有一台 4 核机器并希望在运行时将 minIOThreads 设置为 200,则可以使用 &lt;processModel minIoThreads="50"/&gt;

    来源:

    1. Microsoft Azure - Investigating timeout exceptions in StackExchange.Redis for Azure Redis Cache
    2. StackExchange.Redis

    【讨论】:

    • 我们已经更新了这个方法,但它对我们没有任何改变,仍然是相同的错误频率。
    • 为什么不在Asp net(框架)中使用ThreadPool.SetMinThreads()?
    【解决方案3】:

    我的猜测是网络稳定性存在问题 - 因此超时。

    由于没有人提到responseTimeout 的增加,我会玩弄它。默认值为 50ms,可以轻松达到。我会在 200ms 左右尝试一下,看看这是否有助于处理消息。

    取自configuration options

    responseTimeout={int}   ResponseTimeout     SyncTimeout     Time (ms) to decide whether the socket is unhealthy
    

    在 github 上打开了多个问题。结合所有的可能是#871 The "network stability" / 2.0 / "pipelines" rollup issue

    还有一件事:您是否尝试过使用ConnectionMultiplexer.ConnectAsync() 而不是ConnectionMultiplexer.Connect()

    14.12.2021 - 更新

    stackexchange.redis v2.2.4中:给出如下

    'responseTimeout':警告 CS0618 'ConfigurationOptions.ResponseTimeout' 已过时:'此设置没有 不再有任何影响,不应使用

    更新由MX313发送

    【讨论】:

    • 仅供参考:在 stackexchange.redis v2.2.4 中:为 'responseTimeout' 给出以下内容:警告 CS0618 'ConfigurationOptions.ResponseTimeout' 已过时:'此设置不再有效,不应用过'
    【解决方案4】:

    有 3 种情况会导致超时,很难知道哪种情况在起作用:

    1. 图书馆绊倒了;特别是,存在与 TLS 实现以及我们如何处理库的 v1.* 版本中的读取循环相关的已知问题 - 我们已经为 v2 投入了 很多 时间的工作。 *(但是:并非更新到 v2 总是微不足道的,尤其是当您将该库用作依赖于特定版本的其他代码的一部分时)
    2. 服务器/网络正在跳闸;这是一个非常现实的可能性 - 如果它是服务器端的,查看“slowlog”会有所帮助,但我没有任何可见性
    3. 服务器和网络都很好,图书馆正在尽其所能,但是客户端和服务器之间有一些巨大的斑点在延迟其他操作;这是我正在做的更改以帮助识别现在,如果这表明它本身是一个常见问题,我们可能会考虑更好地利用并发连接(这不会增加带宽,但可以减少阻塞操作的延迟) - 这将是 v2 唯一的更改,注意

    【讨论】:

    • 感谢您的帮助,马克。通过在Application_StartThreadPool.SetMinThreads(200, 200); 中将 WorkerThreads 和 CompletionPortThreads 设置为 200(我假设的默认值是 1),我们已经设法将错误从每天约 50-100 个减少到零,猜猜这适合第 2 类吗?
    • @TomGullen 嗯...这可能是“第 4 类”:) 顺便说一句 - 我昨天添加了一些新的支持来帮助识别/标注“第 3 类” - github.com/StackExchange/StackExchange.Redis/commit/…
    • 感谢您一如既往的帮助 Marc 和精彩的图书馆!很高兴,从我过去 2 天的观察结果来看,这似乎已经解决了。正如旁注一样,Azure 支持已经分析了服务器/网络性能,并确认在引发错误时没有异常行为。
    猜你喜欢
    • 2015-08-15
    • 1970-01-01
    • 2019-05-07
    • 2017-04-06
    • 2015-08-28
    • 2017-08-14
    • 2016-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多