การดู : 0

12/04/2026 18:16น.

EP.102 การใช้ Goroutines และ Worker Pool สำหรับการจัดการ Concurrent Connections

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 เข้า jobs channel
  • ให้ 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/