Polly повторить попытку с другим URL - PullRequest
1 голос
/ 29 мая 2020

Я пытаюсь создать решение с помощью polly, где я запрашиваю другой api.
У меня есть список URL-адресов нескольких экземпляров одной и той же службы.
Я хочу, чтобы при сбое первого запроса другой автоматически запускался со следующего URL-адреса из моего списка.

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

 public static void ConfigureUserServiceClient(this IServiceCollection services)
    {

        _userServiceUri = new Uri("https://localhost:5001");

        services.AddHttpClient("someService", client =>
        {
            client.BaseAddress = _userServiceUri;
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        }).AddPolicyHandler(retryPolicy());
    }

    private static IAsyncPolicy<HttpResponseMessage> retryPolicy()
    {
        return Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.RequestTimeout)
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
            onRetry: (result, span, ctx) =>
            {
                _userServiceUri = new Uri("https://localhost:5002");
            });
    }

1 Ответ

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

Вам следует рассмотреть возможность использования политики Fallback .

Примерно так:

private static HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
    var addressIterator = GetUrls().GetEnumerator();

    var retryLikePolicy = Policy<string>
        .Handle<HttpRequestException>()
        .FallbackAsync(fallbackAction: async (ct) =>
        {
            if (addressIterator.MoveNext())
               return await GetData(addressIterator.Current);
            return null;
        });

    addressIterator.MoveNext();
    var data = await retryLikePolicy.ExecuteAsync(
       async () => await GetData(addressIterator.Current));

    Console.WriteLine("End");
}

static async Task<string> GetData(string uri)
{
    Console.WriteLine(uri);
    var response = await client.GetAsync(uri);
    return await response.Content.ReadAsStringAsync();
}

static IEnumerable<string> GetUrls()
{
    yield return "http://localhost:5500/index.html";
    yield return "http://localhost:5600/index.html";
    yield return "http://localhost:5700/index.html";
}

Обратите внимание, что этот код предназначен только для демонстрации.

...