Пул воркеров ограничивает одновременную работу. Но если производитель продолжает добавлять задачи быстрее обработки, очередь и память растут. Поэтому нужен backpressure: способ замедлить или остановить производителя.
Минимальный пул
jobs := make(chan Job)
results := make(chan Result, workers)
for range workers {
go worker(jobs, results)
}
for _, job := range loadJobs() {
jobs <- job
}
close(jobs)
Отправка в jobs блокируется, когда воркеры заняты. Это уже backpressure: производитель не создаёт бесконечную очередь. Буфер results не даёт воркерам зависнуть при отсутствии читателя.
WaitGroup ждёт воркеров, после чего канал результатов закрывается.
Сначала прекращают поступление задач, затем ждут воркеров. Канал результатов закрывает только тот, кто дождался всех отправителей.
Отмена и границы
Внешняя работа принимает контекст:
select {
case jobs <- job:
case <-ctx.Done():
return ctx.Err()
}
Так отменяется ожидание места в очереди. Сам worker тоже выбирает между новой задачей и ctx.Done().
Отмена не означает мгновенное прерывание. Сначала прекращают запись задач, затем ждут текущие, ограничивая ожидание дедлайном.
Неограниченная очередь опасна
Канал имеет конечный буфер, но производитель может создавать новые горутины. Поэтому ограничивают не только воркеров, но и число ожидающих отправок. Иначе память уходит в ожидание и goroutine leak.
Политика при заполнении выбирается явно:
- блокировать производителя;
- вернуть
429илиRESOURCE_EXHAUSTED; - отбросить задачу с метрикой;
- записать в ограниченное хранилище для повторной обработки.
Для денег и платежей молча отбрасывать нельзя. Для телеметрии допустимо при честном признании потерь.
Завершение
Стадии: прекратить приём, отменить ожидание, дождаться воркеров, закрыть результаты, дочитать их. Проверяют, что каждая принятая задача получила состояние: выполнена, отменена или отклонена.
Метрики: глубина очереди, время ожидания места, активные воркеры, число отказов и отмен. Без них backpressure существует только на бумаге.
Коротко
- Пул ограничивает работу, а backpressure ограничивает поступление задач.
- Отмена распространяется и на ожидание очереди, и на выполнение.
- Политика переполнения явная: ждать, отказать или сохранить.
- Принятая задача получает финальное состояние, иначе она потеряна.