异步命令和Task.WhenAny等待在StackExchange.Redis中超时异常 [英] Timeout exception after async commands and Task.WhenAny awaits in StackExchange.Redis
问题描述
我正在经历所谓的超时执行HGET公司:产品:设置,inst:1,队列:8,qu = 0,qs = 8,qc = 0,wr = 0/0,in = 79/1 超时异常
这是奇怪的,因为相同的Redis实例在同一台机器中存储数据,但它是一个特定的应用程序,例外。 更新:实际上,同一个应用程序,上面的一行接收来自Redis的数据。问题在于 HGET
。
此外,我将多路复用器配置的超时时间增加到6秒,没有运气
此外,我检查了 IDatabase
实例有 IsConnected
with true
value。
如何解释这些错误消息,以及整个超时背后的问题?
某些背景...
我已成功修正了一些代码部分获取一个数据库(即 multiplex.GetDatabase()
)。
虽然多路复用器具有每个 AppDomain
的实例,如StackExchange.Redis文档中所述,许多控制组件的反转在他们自己的代码中创建了许多 IDatabase
的实例。也就是说, IDatabase
实例不共享。
实际代码正在执行 ListRightPopLeftPush
,之后,它实例化了在组件定制期间读取散列键的控制组件的反转。在执行所谓的 ListRightPopLeftPush
之前实例化整个组件,那么整个 HashGet
不会抛出超时异常
似乎甚至当 ListRightPopLeftPush
从其他 IDatabase
实例,在执行读取操作时,它会在下一个 IDatabase
实例中产生某种问题。
无论如何,我的修复没有回答这个问题。我刚刚添加了更详细的信息,让我们找到问题和自己的解决方案。
更新
无论如何,上述修复不会修复对Redis的进一步读取访问。我在进一步的电话中收到相同的超时异常。而现在在异常消息中发现的 c code code code $ c $ =h2_lin>解决方案
根据长时间的聊天讨论,以及大量的挖掘,看起来像在一些晦涩的场景中,TPL正在呃采取专门的阅读器线程,当我们正在做这样的事情,如 .TrySetResult
(我们经常做)。如果您进行同步调用,则会导致即时死锁,因为如果忙碌等待任务完成(由本身完成),则无法处理任何套接字数据。我们实际上具有代码,专门用于防止这种情况 ,但是在其他一些情况下,实际上这种解决方式看起来就像是强制发生。哪个是可怕的我会看到我能找到什么但是基本上,问题在于目前 ,某些有限场景, TaskCompletionSource.TrySetResult
正在为TPL运行同步延续。这包括 Task.WhenAny
。
I'm experiencing the so-called Timeout performing HGET company:product:settings, inst: 1, queue: 8, qu=0, qs=8, qc=0, wr=0/0, in=79/1 timeout exception.
It's strange because the same Redis instance and in the same machine is storing data, but it's a specific application which throws this exception. Update: In fact, the same application, one line above receives data from Redis. The issue is with HGET
.
Also, I've increased timeouts on multiplexer configuration to 6 seconds with no luck.
In addition, I've checked that IDatabase
instance has IsConnected
with true
value.
How to interpret these error messages and what's the issue behind the whole timeout?
Some background...
I've successfully fixed the issue changing when some code section gets a database (i.e. multiplexer.GetDatabase()
).
While multiplexer has an instance per AppDomain
as described in StackExchange.Redis documentation, many inversion of control components are creating many instances of IDatabase
in their own code. That is, IDatabase
instance isn't shared.
Actual code is performing a ListRightPopLeftPush
, and after that, it's instantiating an inversion of control component which reads a hash key during component instatiation. If instantiate the whole component before doing the so-called ListRightPopLeftPush
, then the whole HashGet
won't throw the timeout exception.
It seems like even when ListRightPopLeftPush
is executed from other IDatabase
instance, it produces some kind of issue in the next IDatabase
instance when it comes to perform read operations.
Anyway, my fix doesn't answer the question. I've just added more detailed info to let us find what's the issue and its own solution.
Update
Anyway, the above "fix" won't fix further read accesses to Redis. I'm getting the same timeout exception in further calls. And now in
paramater found in exception's message says 60/1
.
Based on a long discussion in chat, and a lot of digging, it looks like in some obscure scenarios the TPL is hijacking the dedicated reader thread when we are doing things like .TrySetResult
(which: we do often). This causes an instant deadlock if you make a synchronous call, since it can't possibly process any socket data if it is busy waiting for a task to complete (which would only ever be completed by itself). We do actually have code in place specifically to prevent this, but it looks like the workaround actually forces it to happen in some other scenarios. Which... is horrible. I will see what I can find. But basically, the problem is that currently, in some limited scenarios, TaskCompletionSource.TrySetResult
is giving power to the TPL to run synchronous continuations. This includes Task.WhenAny
.
这篇关于异步命令和Task.WhenAny等待在StackExchange.Redis中超时异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!