Что делать, если соединение разорвалось во время выполнения REST-запроса?

Ответ

Для устойчивости к сбоям сети необходимо реализовать стратегию устойчивых (resilient) HTTP-вызовов. Вот практические шаги:

  1. Повторные попытки (Retry): Использовать библиотеку вроде Polly для повторения неудачных запросов с экспоненциальной задержкой. Важно проверять идемпотентность операции (GET, PUT, DELETE — обычно идемпотентны; для POST нужна осторожность).

    var retryPolicy = Policy
        .Handle<HttpRequestException>()
        .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
        .WaitAndRetryAsync(3, retryAttempt => 
            TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
  2. Аварийный выключатель (Circuit Breaker): Защищает систему от лавинообразных сбоев. При частых ошибках запросы временно блокируются, давая удалённому сервису время на восстановление.

    var circuitBreakerPolicy = Policy
        .Handle<HttpRequestException>()
        .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
  3. Резервный вариант (Fallback): Предоставить альтернативные данные (например, из кеша) или понятное сообщение об ошибке, если сервис недоступен.

  4. Таймауты: Настроить разумные таймауты на уровне HttpClient (например, Timeout = TimeSpan.FromSeconds(60)), чтобы запросы не "висели" бесконечно.

  5. Логирование и мониторинг: Все такие инциденты должны логироваться для анализа стабильности интеграции.

Комбинируя эти стратегии, можно значительно повысить отказоустойчивость клиентских приложений.

Ответ 18+ 🔞

А, вот ты про то, как не сдохнуть, когда твой сервис пытается достучаться до другого сервиса, а тот лежит как бревно. Ну, это святое, сейчас разжуем.

Первое, что приходит в голову любому нормальному человеку — просто послать запрос ещё раз. Это называется «ретрай», и это как стучаться в дверь к соседу, который, возможно, просто в наушниках. Но если стучать как сумасшедший каждую секунду, можно и по ебалу получить. Поэтому делаем с умом: используем экспоненциальную задержку. Сперва ждём две секунды, потом четыре, потом восемь... Библиотека Polly для этого — просто божья роса.

var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .WaitAndRetryAsync(3, retryAttempt => 
        TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

Но тут важный нюанс, блядь! Не все операции можно тупо повторять. Если ты отправил POST-запрос на создание заказа, а потом отправил его ещё пять раз потому что таймаут, то можешь получить пять одинаковых заказов и охуеть от счастья. GET, PUT, DELETE — обычно безопасно. А POST — только если ты на 100% уверен, что на той стороне идемпотентность сделана, или у тебя есть свой механизм, чтобы дубли не плодились.

Дальше — «автомат», он же Circuit Breaker. Представь, что удалённый сервис не просто спит, а его вырубило током. И ты продолжаешь слать ему запросы, тратя свои ресурсы и надеясь на чудо. Автомат — это когда после, скажем, пяти подряд пиздецовых ошибок, ты говоришь: «Всё, сука, я пас». И следующие запросы даже не пытаешься отправить, а сразу возвращаешь ошибку. Даёшь тому сервису время отдышаться, минут 30, например.

var circuitBreakerPolicy = Policy
    .Handle<HttpRequestException>()
    .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));

Потом, через полминуты, ты осторожно пробуешь один запрос. Если ок — автомат сбрасывается, и работа идёт как обычно. Если нет — отсчёт начинается заново. Красота, ебать.

Ну и что делать, если всё окончательно легло? Нужен запасной аэродром, Fallback. Не смог получить свежие курсы валют — отдай вчерашние из кеша. Не дозвонился до основного склада — попробуй резервный. Главное, чтобы пользователь не видел просто белую страницу с криком души в консоли.

И, мать его, таймауты! Обязательно выставляй разумные лимиты на HttpClient. Не может же запрос висеть до скончания времён. Поставил, скажем, 60 секунд, и если за это время ответа нет — считай, что его и не будет. Освобождаешь поток и живёшь дальше.

И последнее, но не по важности — логируй всю эту движуху! Каждый сработавший ретрай, каждое срабатывание автомата, каждый фолбэк. Потом будешь смотреть в графики и понимать, какой из твоих «партнёров» — главный распиздяй в экосистеме, который всех подводит. Без этого ты просто летишь вслепую, а это, прости, пиздец как непрофессионально.

Вот так, комбинируя эти штуки, ты делаешь своё приложение не просто упрямым, а по-умному устойчивым. Оно перестаёт паниковать от каждой временной проблемы и достойно держит удар, как хороший боксёр.