Ответ
Паттерн Worker Pool (пул воркеров) — это один из основных подходов к организации конкурентности в Go. Его суть заключается в создании фиксированного числа горутин-воркеров, которые обрабатывают задачи из общей очереди (канала).
Это позволяет контролировать количество одновременно выполняемых операций, предотвращая исчерпание системных ресурсов (памяти, CPU).
Как это работает:
- Создается канал для задач (
jobs
) и канал для результатов (results
). - Запускается заранее определенное количество горутин-воркеров.
- Каждый воркер в цикле читает задачу из канала
jobs
, выполняет её и отправляет результат в каналresults
. - Когда все задачи отправлены в
jobs
, канал закрывается (close(jobs)
). Воркеры завершат работу, когда каналjobs
опустеет.
Пример:
// worker — это горутина, которая получает задачи из канала jobs и отправляет результат в results.
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
// Имитация сложной работы
// time.Sleep(time.Second)
results <- j * 2
}
}
func main() {
const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)
// Запускаем 3 воркера. Больше воркеров не будет создано.
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Отправляем 5 задач в очередь.
for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs) // Важно закрыть канал, чтобы воркеры завершили работу.
// Собираем результаты.
for a := 1; a <= numJobs; a++ {
<-results
}
}
Преимущества:
- Контроль параллелизма: Ограничивает количество одновременно работающих горутин, защищая систему от перегрузки.
- Переиспользование ресурсов: Горутины не создаются для каждой задачи, а переиспользуются, что снижает накладные расходы.
Недостатки:
- Сложность реализации: Требует аккуратной работы с каналами и синхронизацией.
- Статический размер пула: Размер пула обычно определяется заранее. Динамическое изменение размера пула усложняет код.
Паттерн широко используется в задачах с высокой конкуренцией: обработка HTTP-запросов, парсинг больших объемов данных, обработка сообщений из очередей (Kafka, RabbitMQ).