Worker Pool


🧠 1. Worker Pool là gì?

Worker Pool là một mô hình xử lý song song trong đó:

  • Có một hàng đợi công việc (jobs queue).

  • Một số lượng cố định các goroutine (workers) sẽ lấy job từ hàng đợi và xử lý.

  • Tối ưu hiệu năng & giới hạn tài nguyên – thay vì tạo hàng ngàn goroutine, bạn chỉ tạo 10-100 workers.

⚠️ Nếu không dùng Worker Pool, bạn có thể tạo quá nhiều goroutine, dẫn đến OOM (Out of Memory) hoặc CPU nghẽn.


⚙️ 2. Kiến trúc tổng quan

 +---------+        +------------+
 |  Jobs   | ---->  |  Workers   |
 +---------+        +------------+
                      |   |   |
                    Worker Goroutines

🛠️ 3. Code mẫu chuẩn Senior

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

const (
    workerCount = 5
    jobCount    = 20
)

func main() {
    rand.Seed(time.Now().UnixNano())

    jobs := make(chan int, jobCount)
    results := make(chan string, jobCount)
    var wg sync.WaitGroup

    // Start workers
    for w := 1; w <= workerCount; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    // Gửi jobs vào hàng đợi
    for j := 1; j <= jobCount; j++ {
        jobs <- j
    }
    close(jobs) // đóng channel để workers biết không còn job mới

    // Chờ tất cả worker xong
    wg.Wait()
    close(results)

    // Lấy kết quả
    for res := range results {
        fmt.Println(res)
    }
}

func worker(id int, jobs <-chan int, results chan<- string, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        // giả lập xử lý
        time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
        results <- fmt.Sprintf("Worker %d processed job %d", id, job)
    }
}

🔬 4. Giải thích chi tiết

Thành phần
Ý nghĩa

jobs chan int

Hàng đợi chứa các công việc

results chan string

Kết quả trả về sau khi xử lý

wg sync.WaitGroup

Chờ tất cả worker hoàn thành

close(jobs)

Báo cho workers biết không còn job mới

range jobs trong worker

Worker chỉ dừng lại khi jobs bị đóng


🧱 5. Ưu điểm & Khi nào dùng Worker Pool

✅ Khi dùng:

  • Tải cao, job xử lý nhiều (VD: gửi email, resize ảnh, crawl web)

  • Cần kiểm soát tài nguyên (không tạo quá nhiều goroutine)

  • Job tương đối độc lập

⚠️ Tránh dùng nếu:

  • Job quá nhỏ → overhead goroutine còn tốn hơn

  • Cần realtime thấp (delay vì chờ worker rảnh)


💣 6. Những lỗi thường gặp

Lỗi
Nguyên nhân
Cách khắc phục

wg.Done() thiếu

Worker không giảm counter → chương trình treo

Dùng defer wg.Done() sớm nhất có thể

Không close(jobs)

Workers không bao giờ kết thúc

Luôn đóng channel sau khi gửi xong jobs

Không giới hạn worker

Tạo quá nhiều goroutine

Dùng const workerCount cố định số lượng


🧠 7. Bonus – Pattern nâng cao: Context timeout

Khi bạn cần timeout job hoặc hủy giữa chừng:

func worker(ctx context.Context, ...) {
    for {
        select {
        case <-ctx.Done():
            return
        case job := <-jobs:
            // handle job
        }
    }
}

📌 Tổng kết

Kỹ năng
Mức độ

Tạo pool cơ bản

⭐⭐⭐

Xử lý WaitGroup

⭐⭐⭐⭐

Kết hợp Context

⭐⭐⭐⭐⭐

Hiểu tại sao dùng pool

⭐⭐⭐⭐⭐⭐


Last updated