Polly имеет TimeoutPolicy, направленную на именно этот сценарий.
Polly's TimeoutStrategy.Optimistic
находится рядом с ответом @ ThiagoCustodio, но он также правильно устанавливает CancellationTokenSource
. Однако клиент C# RabbitMQ не имеет (на момент написания) предложения перегрузки BasicPublish()
, принимающей CancellationToken
, поэтому этот подход не имеет отношения к делу.
Полл TimeoutStrategy.Pessimistic
направлен на сценариях, такие как BasicPublish()
, где вы хотите ввести тайм-аут на делегат, который не делает имеет поддержки CancellationToken
.
Полл TimeoutStrategy.Pessimistic
:
[1] позволяет вызывающий поток к тайм-ауту на (уйти от ожидания) исполнения, даже тогда, когда выполняются делегат не поддерживает отмену.
[2] делает это за счет дополнительной задачи/потока (в синхронных исполнениях) и управляет этим для вас.
[3] также captures the timed-out Task
(задача, с которой вы ушли). Это может быть ценным для каротажа и является essential, чтобы избежать UnobservedTaskExceptions - особенно в .NET4.0, где UnobservedTaskException can bring down your entire process.
Простой пример:
Policy.Timeout(TimeSpan.FromSeconds(10), TimeoutStrategy.Pessimistic).Execute(() => BasicPublish(...));
Полный пример правильно избегая UnobservedTaskException
S:
Policy timeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(10), TimeoutStrategy.Pessimistic, (context, timespan, task) =>
{
task.ContinueWith(t => { // ContinueWith important!: the abandoned task may very well still be executing, when the caller times out on waiting for it!
if (t.IsFaulted)
{
logger.Error($"{context.PolicyKey} at {context.ExecutionKey}: execution timed out after {timespan.TotalSeconds} seconds, eventually terminated with: {t.Exception}.");
}
else
{
// extra logic (if desired) for tasks which complete, despite the caller having 'walked away' earlier due to timeout.
}
});
});
timeoutPolicy.Execute(() => BasicPublish(...));
Чтобы избежать создания слишком много параллельных нерешенных задач/потоков в случае, когда RabbitMQ становится недоступным, вы можете использовать Bulkhead Isolation policy, чтобы ограничить распараллеливание и/или CircuitBreaker, чтобы предотвратить прохождение вызовов в течение периода, на вы обнаружите определенный уровень сбоев. Их можно комбинировать с TimeoutPolicy, используя PolicyWrap
.
Вы можете использовать 'async' /' await' с .NET4.0 с помощью пакета [Microsoft.BCL.Async] (https://www.nuget.org/packages/Microsoft.Bcl.Async/). –