Внешний платёжный провайдер начал отвечать за 30 секунд вместо 200 миллисекунд. Через минуту сервис перестал отвечать вообще, включая страницы, не связанные с оплатой. Что произошло?
- Что такое каскадный отказ?
- Как медленная зависимость роняет весь сервис?
Медленная зависимость выедает общий пул потоков и соединений: каждый запрос держит поток в 150 раз дольше, и сервис перестаёт обслуживать даже страницы без оплаты.
- Таймаут на внешний вызов по наблюдаемому верхнему перцентилю
- Bulkhead — отдельный пул для каждой внешней зависимости
- Circuit breaker — перестать звать упавшую зависимость
А ещё Закон Литтла: время ×150 при том же потоке — потоков нужно ×150
Подробно
Это классическое начало каскадного отказа. Пока провайдер отвечал за двести миллисекунд, каждый поток освобождался быстро и пула хватало; при тридцати секундах каждый запрос удерживает поток в полтораста раз дольше, поэтому пул исчерпывается за считанные секунды. Дальше запросы, не имеющие к оплате никакого отношения, встают в очередь за свободным потоком — и сервис выглядит полностью недоступным. Правильный набор мер известен: таймаут на каждый внешний вызов, выставленный по наблюдаемому верхнему перцентилю с запасом, а не в тридцать секунд; изоляция ресурсов, то есть отдельный пул или ограничение числа одновременных вызовов именно к этой зависимости, чтобы её деградация не касалась остального; предохранитель, который после порога ошибок начинает отклонять вызовы мгновенно и даёт провайдеру восстановиться; и продуманная деградация — принять заказ и подтвердить оплату позже вместо ожидания. Ответ про нехватку памяти неверен, а тезис «сервис не может быть быстрее зависимости» верен лишь для операций, которые эту зависимость используют, — и именно чтобы он не распространялся на всё остальное, применяют изоляцию.
Что хотят услышать
- Механизм исчерпания общего пула.
- Таймаут, изоляция ресурсов, предохранитель.
- Почему страдают несвязанные запросы.
Частые ошибки
- Ставить один общий пул на все внешние вызовы.
- Задавать таймаут «с запасом» в десятки секунд, что равносильно его отсутствию.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Провайдер начал возвращать ошибки, и сервис перегрузился их обработкой и повторами
- ✗Не хватило памяти под ответы провайдера — нужно увеличить heap
- ✓Общий пул потоков и соединений забит ожиданием провайдера; нужны таймаут, отдельный пул и предохранитель
- ✗Так и должно быть: сервис не быстрее самой медленной зависимости
Что спросят дальше
- Как выбрать значение таймаута для конкретной зависимости?
- Чем ограничение конкурентности лучше выделенного пула потоков?
Разбор темы
- Надёжность и идемпотентность
Управляемая деградация вместо каскада, таймауты и бюджет времени запроса, безопасные ретраи и их мультипликация, идемпотентность как фундамент, предохранитель, отсеки и сброс нагрузки, transactional outbox вместо 2PC.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.