Паттерн пула работников
Ограничивайте параллелизм
«Паттерн пула работников» — бесплатный урок Go Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.
Что такое пул worker
Пул worker запускает фиксированное число горутин, которые получают задания из общего канала. Вместо запуска одной горутины для каждой задачи Вы запускаете N worker и передаёте им работу.
- Ограничивает число параллельных операций
- Повторно использует горутины вместо создания тысяч новых
- Защищает общие ресурсы, например базы данных или программные интерфейсы
Зачем ограничивать параллелизм
Неограниченное число горутин может исчерпать память и файловые дескрипторы или перегрузить зависимую службу. Пул даёт Вам возможность управлять объёмом работы, выполняемой одновременно.
Если Вам нужно получить данные с 10000 адресов, не следует отправлять 10000 одновременных HTTP-запросов. Пул из 20 worker сохраняет нагрузку на разумном уровне.
Канал задач
Задания поступают в канал jobs. Каждый worker читает из него в цикле for range. Когда канал закрывается, цикл завершается и worker выходит.
jobs := make(chan int, 100)
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)Один worker
worker — это всего лишь функция, перебирающая канал задач. Она обрабатывает каждую задачу и записывает результат в канал результатов.
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2
}
}Запуск нескольких worker
Запустите пул простым циклом. На каждой итерации запускается одна горутина с той же функцией worker. Все они используют общие каналы задач и результатов.
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}Направленные типы каналов
Обратите внимание на <-chan int (только для получения) и chan<- int (только для отправки) в сигнатуре worker. Эти направленные типы позволяют компилятору запретить worker случайно отправлять данные в канал задач или читать данные из канала результатов.
Сбор результатов
После передачи всех заданий и закрытия канала главная горутина читает ровно столько результатов, сколько было заданий. Это синхронизирует программу и не позволяет ей завершиться раньше времени.
sum := 0
for a := 1; a <= 5; a++ {
sum += <-results
}
fmt.Println("total:", sum)Полный рабочий пул
Вот полный шаблон в одной программе: три worker удваивают пять чисел. Запустите её и посмотрите на итог.
package main
import "fmt"
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2
}
}
func main() {
jobs := make(chan int, 5)
results := make(chan int, 5)
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
total := 0
for a := 1; a <= 5; a++ {
total += <-results
}
fmt.Println("total:", total)
}Буферизованный и небуферизованный канал
Буферизованный канал задач позволяет производителю ставить работу в очередь, не блокируясь, пока буфер не заполнится. Небуферизованный канал требует непосредственной передачи: отправка блокируется, пока worker не будет готов. Буферизация сглаживает резкие всплески работы производителя.
Выбор размера пула
Для работы, ограниченной возможностями CPU, задавайте размер пула близким к runtime.NumCPU(). Для работы, ограниченной IO (сетью или диском), размер можно сделать гораздо больше, поскольку worker тратят время на ожидание, а не на вычисления.
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("CPUs:", runtime.NumCPU())
}Предотвращение утечек горутин
Если забыть вызвать close(jobs), worker навсегда заблокируются на пустом канале, что приведёт к утечке. Всегда закрывайте канал задач после отправки всей работы, чтобы циклы for range завершались.
Быстрая проверка
Проверьте, насколько хорошо Вы понимаете пулы worker.
Итоги
Вы изучили шаблон пула worker:
- Запускайте фиксированное количество worker, читающих из общего канала задач
- Используйте направленные типы каналов для безопасности
- Закрывайте канал задач, чтобы завершить worker
- Собирайте результаты для синхронизации завершения
- Выбирайте размер пула в зависимости от типа нагрузки (CPU или IO)
Часто задаваемые вопросы
Урок «Паттерн пула работников» бесплатный?
Да — полный текст урока «Паттерн пула работников» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.
Чему я научусь в уроке «Паттерн пула работников»?
Ограничивайте параллелизм Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Go Academy?
Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Паттерн пула работников»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Go Academy?
Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Паттерн пула работников
- Fan-Out и Fan-In
- Этапы конвейера
- Корректное завершение