Закон протекающих абстракций и почему он портит вам tail latency
Закон протекающих абстракций говорит о том, что любая удобная обёртка рано или поздно перестаёт скрывать свою сложность.
Tail latency — это когда запрос, обычно делающийся за 200 ms, внезапно занимает 2 s. Такое поведение ухудшает пользовательский опыт - пользователь может не дождаться и уйти. В распределённой системе эффект еще и усиливается: один затупивший вызов тянет за собой всю цепочку
Почему появляются такие задержки? Сеть потеряла пакет, TCP ушёл в backoff, DNS задумался, GC начал собирать мусор не вовремя, прокси сделал лишний ретрай. В обычном коде всё выглядит гладко, но под нагрузкой эти мелочи превращаются в p95/p99 latency
Как бороться с tail latency? Есть ряд паттернов:
- хеджированные запросы - отправляем запрос на несколько нод сразу, и берем ответ от первого
- request coalescing - одинаковый запросы "склеиваем" в один, чтоб не грузить нижние слои системы
- deadline propagation - каждый участок запроса знает сколько у него осталось времени на выполнение
- circuit breakers - если модуль стал отдавать много ошибок, можно отрезать часть запросов от него, чтоб дать ему восстановиться
- latency-aware load balancing - раскидывать нагрузку не round-robin'ом, а в зависимости от состояния нод
Каждый паттерн — отдельная история, но вместе они сильно уменьшают хвосты.
🚀 Пост Guru PHP: @msavin_dev
Post #472
176