Повторите попытку несколько раз, когда для http-запроса истекло время ожидания с помощью polly c# - PullRequest
1 голос
/ 26 апреля 2020

Мое первоначальное намерение состояло в том, чтобы повторять попытки несколько раз, когда сам запрос истекает, например, при попытке связаться с другим микро-сервисом, который не работает в течение пары секунд в надежде, что это временный сбой. Если есть более простое решение, достаточно сделать это. Я решил вручную установить время ожидания для повторной попытки, используя политику переноса, в надежде достичь того же результата.

Я видел подобное решение, не использующее httpclientfactory здесь Использовать указанное c время ожидания, подключенное к retrypolicy , но он не работает для меня.

Мой код выглядит следующим образом:

services.AddHttpClient("retryclient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
    Policy.HandleResult<HttpResponseMessage>(r =>
        {
            return r.StatusCode == HttpStatusCode.NotFound; //(1)
        }).
.OrTransiesntHttpError().
WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
    onRetry: (exception, timespan, retryAttempt, context) =>
        { // using servs to log // });
}).WrapAsync(Policy.TimeoutAsync(1)));

Я проверил, что политика повторов работает, когда я пытаюсь получить доступ к ' not-found 'адрес без упаковки политики тайм-аута, и он работает нормально. Я также попытался использовать строку (1) с кодом состояния HttpStatusCode.RequestTimeout вместо того, чтобы не найти в моем случае, но это не работает.

Когда я использую упаковку и пытаюсь получить доступ к неработающему сервису, он выдает Polly.Timeout.TimeoutRejectedException с первой попытки, как я и ожидал, но не повторяет попытку. Я не мог найти способ повторить несколько раз, либо с установленным таймаутом для каждой попытки, либо просто когда сам запрос истекает без использования политики тайм-аута.

Редактировать: После дальнейшего чтения https://cm.engineering/transient-timeouts-and-the-retry-rabbit-hole-net-4-5-f406cebbf194 кажется, моя проблема в обработке политики. У меня нет доступа к токену отмены HttpClient. Я предполагаю, что могу это исправить, переопределив метод sendAsyn c, как показано в ссылке. Есть ли элегантный способ сделать то же самое при создании фабрики?

1 Ответ

1 голос
/ 02 мая 2020

Документация Polly на HttpClientFactory охватывает это в разделе, помеченном применением таймаутов :

Вы можете захотеть повторить политику повторения, если кто-либо попытается время вышло. Чтобы сделать это, сделайте политику повторных попыток обработкой TimeoutRejectedException, которую выдает политика тайм-аута Полли.

Итак:

services.AddHttpClient("retryclient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
    Policy.HandleResult<HttpResponseMessage>(r =>
        {
            return r.StatusCode == HttpStatusCode.NotFound; //(1)
        }).
.OrTransientHttpError()
.Or<TimeoutRejectedException>() // ** ADDED **
.WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
    onRetry: (exception, timespan, retryAttempt, context) =>
        { // using servs to log // });
})
.WrapAsync(Policy.TimeoutAsync(1)));

Полли передает CancellationToken во внутренний .SendAsync() звоните правильно; никаких изменений в этом отношении не требуется.

...