Как включить политику тайм-аута с помощью polly - PullRequest
0 голосов
/ 01 апреля 2019

Я опробую политику тайм-аута с помощью 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 секунд.

Почему политика тайм-аута не работает в этом случае?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

Почему политика тайм-аута не работает в этом случае?

Полли TimeoutPolicy существует в двух режимах:

Оптимистический режим используется по умолчанию, поэтому ваш опубликованный код использует это.Но (a) LongOperation() в размещенном коде не отвечает на совместную отмену;таким образом, политика не истекает.

Пессимистический режим с асинхронными политиками специально предназначен только для управления делегатами, которые соответствуют нормальному асинхронному шаблону .Thread.Sleep() в опубликованном LongOperation() полностью синхронно;таким образом, ваш пример дополнительно не будет отключен тайм-аутом, если просто переключиться на TimeoutStrategy.Pessimistic.


TimeoutStrategy.Optimistic - это лучшее моделирование вызовов через HttpClient, поскольку эти вызовы отвечают на CancellationToken.

Оптимистичный режим тайм-аута политики асинхронного тайм-аута можно смоделировать с помощью await Task.Delay(...) для CancellationToken, следующим образом :

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
        };
    }
} 
0 голосов
/ 01 апреля 2019

Прямо сейчас вы используете Optimistic тайм-аут, который ожидает, что delgate, который вы вызываете, уважает и отвечает на токен отмены. Ваш делегат этого не делает, в этом случае вам нужно использовать 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 - значение по умолчанию.

Как уже заметил @moutain путешественник, оптимистичный тайм-аут требует, чтобы вы прошли и сотрудничали с отменой тайм-аута. Это уже обрабатывается вызовами API с использованием HttpClient, но в этом примере ваш код будет выглядеть примерно так:

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
        };

    });
} 
...