12/04/2026 18:16น.

JS2GO EP.42 Goroutine Pools และ Worker Pools ใน Go และ JavaScript
#JavaScript
#Go
#Concurrency
#Worker Pool
#Goroutine Pool
ควบคุมจำนวนงานพร้อมกันอย่างมีประสิทธิภาพ ป้องกัน resource leak และออกแบบระบบให้รองรับโหลดระดับหมื่นคำขอ/วินาที 🚀
เมื่อระบบต้องประมวลผลงานจำนวนมากพร้อมกัน เช่น
- ประมวลผลภาพ/วิดีโอ
- คำนวณหนัก (CPU-intensive)
- ส่งอีเมลครั้งละหลายพันรายการ
- ประมวลผล background jobs
- ทำ data processing จาก queue
ถ้าปล่อยให้ Goroutine หรือ Worker ถูกสร้างขึ้น “ไม่จำกัดจำนวน” → ระบบจะล่มทันทีจาก:
- 🧨 memory พุ่งจน Out Of Memory
- 🧨 CPU 100% ค้างยาว
- 🧨 routine/thread หลักหมื่นจน OS สลับ context หนักมาก
- 🧨 latency พุ่งสูงผิดปกติ
- 🧨 API endpoint ตอบช้า/ล่มทั้งระบบ
Solution คือ → “Pool”
Pool ทำหน้าที่ควบคุมว่า “รอบนี้ให้รันงานได้สูงสุดกี่งานเท่านั้น”
ส่วน Queue คือที่เก็บงานที่รอคิวเข้ามาใน Pool
⭐ 1. ทำไมระบบต้องใช้ “Pool”?
ถ้าไม่มี pool → ระบบจะเกิดปัญหานี้ทันที:
| ปัญหา | ผลกระทบ |
|---|---|
| เปิด Goroutine / Worker มากเกินไป | Memory leak |
| CPU สลับ context หนักเกิน | latency สูงขึ้นเรื่อย ๆ |
| Thread มากเกิน OS รับไม่ไหว | Server crash |
| งานค้างใน background | uptime ต่ำ, queue overflow |
Pool ทำหน้าที่เป็น “ตัวควบคุมทรัพยากรระดับระบบ” เพื่อให้ระบบเสถียรแม้มี load สูงระดับหมื่นหรือแสนงานต่อวินาที
⭐ 2. Goroutine Pool ใน Go
Go มี Goroutine ขนาดเล็ก (~2KB stack) และสร้างเร็วมาก แต่หากสร้างเป็นหมื่น/แสนก็ยังล่มได้เหมือนกัน หากไม่จำกัดจำนวน
🧪 ตัวอย่าง Goroutine Pool (แบบ Production-friendly)
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for j := range jobs {
time.Sleep(200 * time.Millisecond) // จำลองงานหนัก
results <- j * 2
fmt.Println("Worker", id, "processed job", j)
}
}
func main() {
jobs := make(chan int, 10)
results := make(chan int, 10)
var wg sync.WaitGroup
// สร้าง Pool = 3 workers
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}
// ส่งงานเข้า queue
for j := 1; j <= 9; j++ {
jobs <- j
}
close(jobs)
wg.Wait()
close(results)
for r := range results {
fmt.Println("Result:", r)
}
}
✔ จุดเด่นของ Goroutine Pool
- เบาและเร็วมาก รองรับงานพร้อมกันจำนวนมหาศาล
- channels คล้าย queue ทำให้ flow ปลอดภัย ไม่ race
- ไม่ต้องสร้าง/ทำลาย thread จำนวนมาก
- latency ต่ำมากในงาน CPU-bound หรือ pipeline processing
✔ เหมาะกับ
- Data pipeline
- CPU-heavy batch processing
- Message queue consumers
- File processing
- WebSocket Broadcasting
⭐ 3. Worker Pool ใน JavaScript (Node.js)
Node.js เป็น single-threaded แต่สามารถทำงานแบบ multi-thread ได้ผ่าน worker_threads
🧪 Worker Pool แบบใช้งานได้จริง
worker.js
const { parentPort, workerData } = require('worker_threads');
function heavyTask(num) {
return num * 2;
}
parentPort.postMessage(heavyTask(workerData));
main.js
const { Worker } = require('worker_threads');
function runWorker(num) {
return new Promise((resolve, reject) => {
const worker = new Worker('./worker.js', { workerData: num });
worker.on('message', resolve);
worker.on('error', reject);
});
}
async function main() {
const tasks = [1, 2, 3, 4, 5];
const results = await Promise.all(tasks.map(t => runWorker(t)));
console.log(results);
}
main();
✔ จุดเด่นของ Worker Pool
- ใช้ CPU ได้หลาย core
- ทำงาน CPU-heavy ได้จริง
- แยก process จาก main thread ทำให้ลด event loop lag
✔ เหมาะกับ
- Image resizing
- Video transcoding
- Big JSON parsing
- Encryption / hashing
- AI model inference
⭐ 4. เปรียบเทียบความสามารถ Go vs JavaScript
| ความสามารถ | Go (Goroutine Pool) | JavaScript (Worker Pool) |
|---|---|---|
| ความเร็ว | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| ใช้หลาย CPU core | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| Memory footprint | ต่ำมาก | ปานกลาง |
| ง่ายต่อการเขียน | ง่ายและกระชับ | ซับซ้อนกว่า |
| Scaling | สูงมาก (10k+ routines) | ปานกลาง |
| ใช้กับงานแบบ | concurrent-heavy | CPU-heavy |
สรุปสั้น ๆ:
🔥 Go → ทำงาน CPU/Concurrent หนักมากได้แบบ native
🔥 JS → ดีมากสำหรับ I/O-heavy และ CPU งานกลาง–หนักผ่าน worker threads
⭐ 5. Best Practices สำหรับระบบ Production
✔ 1) จำกัดจำนวน workers/goroutines
- Go → ใช้ buffered channel
- JS → จำกัด worker ตามจำนวน CPU core (4–8 ตัวเหมาะสมสุด)
✔ 2) ใส่ timeout เสมอ
ห้ามปล่อย network call ค้าง → เกิด zombie worker
✔ 3) Implement Graceful Shutdown
ต้องปิดสิ่งเหล่านี้ให้ครบ:
- workers
- goroutines
- channels
- file handles
- queues
✔ 4) Monitoring worker health
ป้องกัน worker ค้างโดยไม่ตอบ (silent failure)
✔ 5) ใช้ Queue system ถ้า load สูงมาก
เช่น
- Redis Streams
- RabbitMQ
- Kafka
เพื่อกระจาย load และทำ retry logic
⭐ 6. สรุปท้ายบท
Goroutine Pool (Go) และ Worker Pool (JavaScript) คือแกนสำคัญของระบบที่ต้องรองรับงานจำนวนมากในเวลาเดียวกัน ทั้งสองภาษาออกแบบแตกต่างกัน แต่ให้ผลลัพธ์ที่ยอดเยี่ยมเมื่อใช้ถูกงาน
ถ้างานของคุณคือ:
- CPU-heavy
- data pipeline
- real-time streaming
- backend ที่ต้อง uptime สูง
👉 Go คือคำตอบที่ดีที่สุด
ถ้างานของคุณคือ:
- API-first
- I/O-bound
- real-time web
- ทำงานร่วมกับ frontend ecosystem
👉 JavaScript คือทางเลือกที่ยอดเยี่ยม
🔵 EP.43 ตอนต่อไป
การทำ Rate Limiting และ Throttling ใน Go และ Node.js
พร้อมตัวอย่างโค้ด Production ของ:
- Token Bucket
- Leaky Bucket
- Sliding Window
- Middleware ใน Go + Node.js
เพื่อปกป้องระบบของคุณจากการยิง request จำนวนมากแบบอยู่รอดได้จริงในระบบ Production 🚀