Ответ
Polly — это библиотека для .NET, реализующая шаблоны устойчивости приложений (Resilience Patterns). Она позволяет элегантно обрабатывать временные сбои, ограничивать нагрузку и управлять временем выполнения операций.
Основные политики (Policies):
- Retry (Повторные попытки): Повторяет операцию при возникновении указанных исключений.
- Circuit Breaker (Автоматический выключатель): Временно блокирует выполнение операций при высокой частоте ошибок, чтобы дать удалённой системе восстановиться.
- Timeout (Таймаут): Прерывает выполнение операции, если она длится дольше заданного времени.
- Bulkhead (Переборка): Изолирует пулы ресурсов, чтобы сбой в одной части системы не исчерпал все ресурсы (например, все потоки).
- Fallback (Резервный вариант): Предоставляет альтернативное значение или действие при сбое.
- Cache (Кэширование): Кэширует результаты вызовов (требует отдельного пакета
Polly.Caching).
Практический пример: Комбинирование Retry и Circuit Breaker для HTTP-вызова
using Polly;
using Polly.Extensions.Http;
// 1. Политика повторных попыток с экспоненциальной задержкой
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError() // Обрабатывает 5xx, 408, 502, 503, 504
.WaitAndRetryAsync(3, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // Задержка: 2, 4, 8 сек.
// 2. Политика автоматического выключателя
var circuitBreakerPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); // Размыкает цепь после 5 ошибок за 30 сек.
// 3. Объединение политик в стратегию
var resiliencePipeline = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);
// 4. Использование
await resiliencePipeline.ExecuteAsync(async () =>
{
var response = await _httpClient.GetAsync("https://api.example.com/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
});
Преимущества использования Polly:
- Декларативный подход: Политики определяются отдельно от бизнес-логики.
- Гибкость: Политики можно комбинировать и повторно использовать.
- Асинхронная поддержка: Полная поддержка
async/await. - Интеграция с
IHttpClientFactory: Легко встраивается в конвейер обработки HTTP-запросов в ASP.NET Core.
Ответ 18+ 🔞
Смотри, есть такая библиотека Polly для .NET — она типа как бронежилет для твоего кода, когда он общается с внешним миром. Если что-то падает, глючит или тупит, она не даёт всему разъебаться моментально. Вместо этого включает мозги и пытается всё починить по уму.
Чем она умеет заниматься, эта умница:
- Retry (Повторять): Упала операция — ну ебнулось и ебнулось. А Polly возьмёт и попробует ещё разок, и ещё. Особенно если ошибка временная, типа сетевого глюка.
- Circuit Breaker (Предохранитель): Если ошибки посыпались как из ведра, она хлоп — и разрывает цепь. Перестаёт долбить удалённую систему, даёт ей отдышаться, а то ведь реально можно добить. Через время осторожно пробует снова.
- Timeout (Таймаут): Если операция зависла и думает дольше, чем тебе нужно, Polly её просто прервёт. Не будет ждать, пока все твои потоки упрутся в потолок.
- Bulkhead (Переборка): Это чтобы изолировать проблемы. Представь, что один сервис сдох и начал жрать все твои потоки. С этой политикой он сожрёт только свой выделенный лимит, а остальная система будет жить.
- Fallback (Запасной аэродром): Всё накрылось? Не беда. Можно вернуть какое-то дефолтное значение или выполнить простенькую резервную процедуру. Лишь бы пользователь не увидел жёлтый экран смерти.
- Cache (Кэш): Ну это если брать отдельный пакет — может запоминать результаты, чтобы не ходить за одним и тем же сто раз.
Вот как это может выглядеть в деле, когда нужно отправить HTTP-запрос и не сойти с ума:
using Polly;
using Polly.Extensions.Http;
// 1. Делаем политику повторных попыток. Упал запрос — ждём и пробуем снова.
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError() // Ловит временные ошибки вроде 500-х кодов или таймаутов
.WaitAndRetryAsync(3, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); // Ждём 2, потом 4, потом 8 секунд. Экспоненциальная back-off заебок.
// 2. Политика предохранителя. Если ошибок много, прекращаем пытаться нафиг.
var circuitBreakerPolicy = HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); // Если 5 ошибок подряд — разрываем цепь на 30 секунд.
// 3. Комбинируем эти две штуки в одну мощную стратегию.
var resiliencePipeline = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);
// 4. Используем эту банду.
await resiliencePipeline.ExecuteAsync(async () =>
{
var response = await _httpClient.GetAsync("https://api.example.com/data");
response.EnsureSuccessStatusCode(); // Если опять ошибка, политики вступят в игру.
return await response.Content.ReadAsStringAsync();
});
И почему это вообще охуенно:
- Всё красиво и отдельно: Ты описываешь правила устойчивости в одном месте, а бизнес-логика — в другом. Не превращается в спагетти-код.
- Гибкость: Эти политики как лего — собираешь любую комбинацию под свою задачу.
- Асинхронность: Всё работает нормально с
async/await, не блокирует потоки. - Дружит с IHttpClientFactory: В ASP.NET Core встраивается в обработку HTTP-запросов буквально парой строк. Удобно, блядь.