Skip to content
12 / 15

Ограничение параллелизма и обратное давление в Go

Go делает запуск горутины настолько дешёвым, что легко написать for _, item := range million { go handle(item) } — и получить исчерпанные соединения, отказ внешнего сервиса и OOM. Ограничивать нужно на трёх уровнях. Параллелизм — сколько задач выполняется одновременно: семафор на буферизованном канале, errgroup.SetLimit или пул воркеров. Частота — сколько запросов в секунду: golang.org/x/time/rate с алгоритмом «дырявого ведра», а не самодельные счётчики. Очередь — что делать, когда работа приходит быстрее, чем обрабатывается: именно здесь возникает обратное давление. Правильный ответ обычно не «увеличить буфер», а «отказать быстро»: неограниченная очередь превращает перегрузку в рост задержки и памяти, пока не придёт OOM, тогда как быстрый отказ позволяет клиенту отступить и повторить. На стороне клиента к этому добавляют предохранитель, чтобы не долбить уже упавший сервис.

Ограничение параллелизма и обратное давление в Go | JScriptiser