Марк Прайс предложил свой набор из 60 вопросов (как технических, так и на софт-скилы), которые могут задать на собеседовании.
43. Устойчивость и обработка кратковременных сбоев
«Расскажите, как бы вы реализовали устойчивость и обработку кратковременных сбоев. Приведите примеры методов и инструментов, которые вы бы использовали, чтобы приложение могло корректно обрабатывать сбои и восстанавливаться после них».
Хороший ответ
При создании отказоустойчивых приложений крайне важно предвидеть и эффективно обрабатывать кратковременные сбои. Это гарантирует, что приложение останется отзывчивым и доступным даже в неблагоприятных условиях. Вот шаги и инструменты, которые я бы использовал:
- Политики повторных попыток: пакет Microsoft.Extensions.Http.Polly обеспечивает устойчивость и обработку кратковременных сбоев путём реализации политики повторных попыток. Это помогает в ситуациях, когда операции могут иногда завершаться с ошибкой из-за временных проблем, таких как проблемы с сетевым подключением или тайм-аутом сервера:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddHttpClient("ApiClient", c =>
{
c.BaseAddress = new Uri("https://apiurl.com");
})
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(10)
})
);
var app = builder.Build();
app.MapGet("/external-api",
async (IHttpClientFactory hcf) =>
{
var client = hcf.CreateClient("ApiClient");
var response = await client.GetAsync("/data");
return resp.IsSuccessStatusCode
? Results.Ok(await resp.Content.ReadAsStringAsync())
: Results.Problem();
});
app.Run();
- Паттерн Прерыватель Цепи (Circuit Breaker): предотвращает повторные сбои из-за одной и той же ошибки. Этот паттерн полезен для обработки случаев, когда продолжение выполнения действия может нанести системе больший вред. Polly также можно настроить для работы с ним:
.AddTransientHttpErrorPolicy(p =>
p.CircuitBreakerAsync(3, TimeSpan.FromMinutes(1)));
- Тайм-ауты: явные тайм-ауты для всех внешних HTTP-запросов гарантируют, что приложение не зависнет на неопределённое время, если сервис, от которого оно зависит, работает медленно или не отвечает.
- Резервные (Fallback) политики: для предоставления значений по умолчанию или упрощённых ответов в случае сбоя вызова внешнего сервиса:
.AddTransientHttpErrorPolicy(p =>
p.Or<TimeoutException>()
.FallbackAsync(
new HttpResponseMessage(HttpStatusCode.OK)
{ Content = new StringContent("Резервный ответ") })
);
Преимущества
- Благодаря эффективной обработке кратковременных сбоев приложение остается более доступным и отзывчивым.
- Обеспечивает более стабильный и надёжный пользовательский опыт.
- Помогает предотвратить каскадные сбои (например, перегрузку замедлившегося API запросами) из-за неполадок в одной части системы.
Часто встречающийся плохой ответ
«Нужно просто поставить повыше значение тайм-аута для внешних вызовов, чтобы дать сервисам достаточно времени для реагирования и снизить вероятность сбоев.»
Почему это неправильно
- Непонимание обработки ошибок: простое увеличение значений тайм-аута не устраняет первопричины кратковременных сбоев и может привести к ухудшению пользовательского опыта из-за увеличения времени ожидания.
- Отсутствие комплексной стратегии: этот подход не учитывает возможность внедрения комплексной стратегии повторных попыток, прерываний и резервных ответов для эффективной обработки различных типов сбоев.
- Потенциальная повышенная нагрузка на систему: более длительные тайм-ауты могут усугубить проблемы, занимая системные ресурсы на длительные периоды.
Эта ошибка обычно является результатом недостаточного понимания принципов обработки кратковременных ошибок или чрезмерно упрощённого подхода к обработке ошибок и исключений.
Источник: https://github.com/markjprice/tools-skills-net8/blob/main/docs/interview-qa/readme.md
