12/04/2026 18:16น.

EP.102 การใช้ Goroutines และ Worker Pool สำหรับการจัดการ Concurrent Connections
#Goroutines
#Golang
#Go
#Worker Pool
#WebSocket Server
ในระบบ WebSocket ที่ต้องรองรับผู้ใช้งานจำนวนมาก การจัดการ Goroutines และ Worker Pool อย่างมีประสิทธิภาพ เป็นกุญแจสำคัญที่จะทำให้ระบบของคุณ เร็ว, เสถียร, และไม่พังเมื่อโดนโหลดหนัก
บทความนี้จะพาคุณไปเรียนรู้แนวคิด พร้อมตัวอย่างโค้ด Go ที่ใช้งานได้จริง
🌀 1. ใช้ Goroutines รับมือกับการเชื่อมต่อจำนวนมาก
เมื่อมีการเชื่อมต่อจากผู้ใช้งานเข้ามา แต่ละการเชื่อมต่อควรถูกแยกไปจัดการใน Goroutine ของตัวเอง:
- ป้องกันการ block ของ main thread
- เพิ่มความสามารถในการรองรับ concurrent connections
✅ ตัวอย่าง: แยก Goroutine สำหรับแต่ละ WebSocket connection
package main
import (
"fmt"
"net/http"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
func handleConnection(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
http.Error(w, "Upgrade error", http.StatusInternalServerError)
return
}
defer conn.Close()
go func(c *websocket.Conn) {
for {
_, msg, err := c.ReadMessage()
if err != nil {
fmt.Println("Connection closed:", err)
break
}
fmt.Println("Received:", string(msg))
}
}(conn)
}
func main() {
http.HandleFunc("/ws", handleConnection)
fmt.Println("WebSocket Server running on :8080")
http.ListenAndServe(":8080", nil)
}
🧱 2. ใช้ Worker Pool เพื่อควบคุมจำนวน Goroutines
Goroutine แม้จะเบา แต่ถ้าไม่ควบคุมจำนวนก็สามารถ กิน Memory จนระบบล่มได้
การใช้ Worker Pool ช่วยให้:
- ประหยัดทรัพยากร
- ควบคุมจำนวน Goroutines ได้ชัดเจน
- เหมาะกับการจัดการ Task จำนวนมากที่มาทีละ batch
✅ ตัวอย่าง: Worker Pool รับข้อความจาก jobs queue
type Job struct {
Message string
}
var jobs = make(chan Job, 100)
var results = make(chan string, 100)
func worker(id int, jobs <-chan Job, results chan<- string) {
for j := range jobs {
fmt.Printf("Worker %d processing: %s\n", id, j.Message)
results <- fmt.Sprintf("Done: %s", j.Message)
}
}
func main() {
// Start 5 workers
for w := 1; w <= 5; w++ {
go worker(w, jobs, results)
}
// Push 20 jobs
for i := 0; i < 20; i++ {
jobs <- Job{Message: fmt.Sprintf("Message %d", i)}
}
close(jobs)
// Collect results
for i := 0; i < 20; i++ {
fmt.Println(<-results)
}
}
⚙️ 3. Best Practices
✅ ใช้ Worker Pool ร่วมกับ WebSocket ได้อย่างไร?
- ใช้ Goroutine ต่อการเชื่อมต่อ
- เมื่อมีข้อความจากผู้ใช้ → push เข้า
jobschannel - ให้ worker รับไปประมวลผล แล้วส่งต่อผลกลับ client
🛡️ ข้อควรระวัง
- อย่าปล่อย Goroutine รั่ว → ต้องมีการ
recover()และจัดการ error เสมอ - จำกัดจำนวน Goroutines ด้วย semaphore / pool
- ใช้
buffered channelเพื่อรองรับ traffic spike
🔍 Monitoring
- ใช้
runtime.NumGoroutine()เพื่อตรวจสอบจำนวน Goroutines ปัจจุบัน - ใช้
pprofสำหรับ profiling memory และ performance - ตั้ง metric monitor connection count, job queue length, success/fail rate
🎯 Challenge สำหรับคุณ
ลองสร้าง WebSocket Server ที่:
✅ รองรับผู้ใช้งาน 1,000 คนพร้อมกัน
✅ ใช้ Worker Pool จัดการข้อความ
✅ Monitor Goroutines, Memory และ Throughput
✅ ทดสอบระบบด้วย Locust หรือ Artillery
🔚 สรุป
เทคนิคการใช้ Goroutines + Worker Pool:
- ปรับปรุง concurrency
- ป้องกัน resource exhaustion
- พร้อมใช้งานจริงใน Production
WebSocket Server ของคุณจะกลายเป็นระบบที่พร้อมรับมือกับ โหลดหนักๆ ได้อย่างมั่นใจ
🔜 Next EP:
EP.103 – การปรับปรุง Latency ด้วย Binary Protocol และ Protobuf
อ่านบทความ Series อื่นๆ
🔵 Facebook: https://www.facebook.com/superdev.academy.th
🔴 YouTube : Superdev Academy
📸 Instagram: Superdev Academy
🎬 TikTok: https://www.tiktok.com/@superdevacademy?lang=th-TH
🌐 Website: https://www.superdevacademy.com/