我正在尝试使用polly设置超时策略。
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
timeoutPolicy().GetAwaiter().GetResult();
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
Console.ReadKey();
}
static async Task timeoutPolicy()
{
AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(), CancellationToken.None);
}
static Task<HttpResponseMessage> LongOperation()
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
Thread.Sleep(5000); // Sleep 5 seconds
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
});
}
我希望在1秒钟后引发异常,因为这是我设置的超时上限。但是目前,不会引发任何异常,并且LongOperation()方法会在大约5秒钟后正常返回。
为什么在这种情况下超时策略不起作用?
答案 0 :(得分:0)
现在您正在使用Optimistic
超时,该超时期望您调用的代理尊重并响应取消令牌。您的代表不需要,在这种情况下,您需要使用Pessimistic
超时来确保您的呼叫者不会等待经过定义的超时。
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1, TimeoutStrategy.Pessimistic); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(), CancellationToken.None);
}
文档Optimistic
中所述的Polly Timeout是默认设置。
正如@moutain旅行者已经指出的那样,乐观的超时要求您通过并与超时取消合作。使用HttpClient
的api调用已经解决了这个问题,但是在此示例示例中,您的代码将如下所示:
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1, TimeoutStrategy.Optimistic); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(ct), CancellationToken.None);
}
static Task<HttpResponseMessage> LongOperation(CancellationToken token)
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
var longTask = Task.Delay(5000);
while (!longTask.IsCompleted)
{
token.ThrowIfCancellationRequested();
}
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
});
}
答案 1 :(得分:0)
为什么在这种情况下超时策略不起作用?
Polly的TimeoutPolicy
存在两种模式:
TimeoutStrategy.Optimistic
期望受管代表对co-operative cancellation by CancellationToken做出回应。TimeoutStrategy.Pessimistic
允许调用代码放弃等待 不响应合作取消的代表。乐观模式是默认模式,因此您发布的代码使用此模式。但是(a)所发布代码中的LongOperation()
不能响应合作取消;因此该政策不会超时。
具有异步策略的悲观模式为intentionally designed only to govern delegates which conform to the normal async pattern。发布的Thread.Sleep()
中的LongOperation()
是完全同步的;因此您的示例仅通过切换到TimeoutStrategy.Pessimistic
就不会超时。
TimeoutStrategy.Optimistic
是通过HttpClient
进行呼叫的最佳模拟,因为这些呼叫确实会响应CancellationToken
。
可以通过await Task.Delay(...)
兑现CancellationToken
,like this来模拟异步超时策略的长时间操作超时模式:
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Polly;
using Polly.Timeout;
public class Program
{
public static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
try {
timeoutPolicy().GetAwaiter().GetResult();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
}
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(ct), CancellationToken.None);
}
static async Task<HttpResponseMessage> LongOperation(CancellationToken token)
{
await Task.Delay(5000, token);
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
}
}