Какие методы отказоустойчивости используются в сетевом взаимодействии
Что проверяют
Знаете ли вы стандартные паттерны устойчивости и как они собираются в .NET, а не только слово «ретрай». Следом спрашивают, какие запросы можно повторять и в каком порядке ставить политики.
Как отвечать
Перечислите приёмы с условиями применения:
- таймауты: у каждого вызова свой предел, плюс
CancellationTokenсквозь всю цепочку. УHttpClientпо умолчаниюTimeoutравен 100 секундам, для межсервисных вызовов это слишком много; - retry с экспоненциальной задержкой и джиттером: только на временные ошибки (сетевые исключения, 5xx, 408, 429) и только для идемпотентных операций. Для
POSTнужен ключ идемпотентности; - circuit breaker: после серии сбоев вызовы какое-то время не отправляются вовсе, чтобы не добивать упавший сервис и не держать потоки;
- bulkhead и rate limiter: ограничение параллельных запросов к одной зависимости, чтобы её деградация не съела ресурсы всего сервиса;
- fallback и hedging: запасной ответ из кэша или параллельный запрос к другой реплике, если первый задерживается;
- failover и балансировка: несколько экземпляров за балансировщиком, health checks, повтор на другой узел.
В коде это Polly v8: ResiliencePipelineBuilder с AddRetry, AddCircuitBreaker, AddTimeout. Для HttpClient есть пакет Microsoft.Extensions.Http.Resilience: AddStandardResilienceHandler() на клиенте из IHttpClientFactory подключает готовую цепочку из ограничителя запросов, общего таймаута, ретраев, предохранителя и таймаута на попытку. Сам IHttpClientFactory закрывает ещё две сетевые проблемы: исчерпание сокетов при new HttpClient() на каждый запрос и устаревший DNS у клиента, который живёт вечно.
Где спотыкаются
Ретраят всё подряд, включая неидемпотентный POST оплаты. Первый запрос дошёл, ответ потерялся, и деньги списаны дважды.
Ставят ретраи без джиттера на множество клиентов. После сбоя все повторяют запросы синхронно и снова кладут только что поднявшийся сервис.
Путают порядок политик. Таймаут на попытку должен стоять внутри ретрая, а общий таймаут снаружи, иначе один зависший запрос съедает весь бюджет времени и до повторов дело не доходит.