การดู : 241

08/05/2026 06:52น.

EP.110 การทำ Auto-Scaling และ Load Balancing ขั้นสูง สำหรับ WebSocket Server

EP.110 การทำ Auto-Scaling และ Load Balancing ขั้นสูง สำหรับ WebSocket Server

#WebSocket Production

#Go

#Load Balancing

#Auto-Scaling

#WebSocket

เมื่อจำนวนผู้ใช้ WebSocket ของคุณเติบโตจาก "หลักร้อย" ไปสู่ "หลักหมื่น" คุณจะเริ่มพบกับปัญหาด้านโหลด การเชื่อมต่อซ้ำซ้อน และการกระจายทราฟฟิกที่ไม่สมดุลทันที ⚡

 

EP นี้จะพาคุณมาเรียนรู้การออกแบบ WebSocket Server ที่สามารถขยายตัวได้อัตโนมัติ (Auto-Scaling) และ กระจายโหลดได้อย่างมีประสิทธิภาพ (Load Balancing) โดยใช้เครื่องมือระดับ Production เช่น Kubernetes, Load Balancer, Sticky Session และ Redis Pub/Sub

 

🧩 1. ทำไมต้อง Auto-Scaling และ Load Balancing?

 

ปัญหาคำอธิบาย
Connection เกิน limitServer เดียวรับโหลดไม่ไหว
ผู้ใช้ reconnect บ่อยการกระจายโหลดไม่สมดุล
Message สูญหายขาดการสื่อสารระหว่าง WebSocket instance
Latency สูงทราฟฟิกไม่ถูกส่งไปยัง node ที่ใกล้ที่สุด

 

ระบบระดับ Production ที่รองรับผู้ใช้หลายหมื่นคนต้องสามารถ “เพิ่ม–ลดขนาด” ได้อัตโนมัติตามปริมาณโหลด

 

⚙️ 2. สถาปัตยกรรมระบบ Auto-Scaling WebSocket

 

Client
   ↓
Load Balancer (Sticky Session)
   ↓
WebSocket Server Pods (Kubernetes)
   ↓
Redis Pub/Sub (Message Sync)
   ↓
Database / Services

 

Key Component:

  • Load Balancer → กระจายผู้ใช้ไปยัง Pod ที่เหมาะสม
  • Sticky Session → รักษาการเชื่อมต่อของผู้ใช้กับ Pod เดิม
  • Redis Pub/Sub → ส่งข้อความข้าม instance แบบเรียลไทม์

 

🧠 3. ตัวอย่างโค้ด: Redis Pub/Sub Sync Messages

 

// ติดตั้ง redis & gorilla/websocket ก่อน
// go get github.com/redis/go-redis/v9
// go get github.com/gorilla/websocket

var (
	upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
	rdb      = redis.NewClient(&redis.Options{Addr: "localhost:6379"})
	ctx      = context.Background()
	clients  = make(map[*websocket.Conn]bool)
)

func handleConnections(w http.ResponseWriter, r *http.Request) {
	conn, _ := upgrader.Upgrade(w, r, nil)
	defer conn.Close()
	clients[conn] = true
	defer delete(clients, conn)

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			break
		}
		// Publish message to Redis channel
		rdb.Publish(ctx, "chat_channel", msg)
	}
}

func handleRedisMessages() {
	subscriber := rdb.Subscribe(ctx, "chat_channel")
	ch := subscriber.Channel()
	for msg := range ch {
		for client := range clients {
			client.WriteMessage(websocket.TextMessage, []byte(msg.Payload))
		}
	}
}

func main() {
	go handleRedisMessages()
	http.HandleFunc("/ws", handleConnections)
	log.Println("WebSocket Server running on :8080")
	http.ListenAndServe(":8080", nil)
}

 

✅ ทุกข้อความที่ถูกส่งจาก client ใด ๆ จะถูก publish เข้า Redis และ broadcast ไปยังทุก instance พร้อมกัน

 

🧩 4. Load Balancer + Sticky Session

 

Sticky Session มีความสำคัญอย่างยิ่งสำหรับระบบ multi-instance เพราะช่วยให้ผู้ใช้เชื่อมต่อกับ Pod เดิมได้อย่างต่อเนื่อง

 

ตัวอย่างการตั้งค่า Nginx Ingress:

annotations:
  nginx.ingress.kubernetes.io/affinity: "cookie"
  nginx.ingress.kubernetes.io/session-cookie-name: "route"
  nginx.ingress.kubernetes.io/session-cookie-hash: "sha1"

 

👉 ทำให้ connection คงที่ แม้มีการโหลดสูง ลดปัญหา reconnect และ message loss

 

☁️ 5. การตั้งค่า Auto-Scaling บน Kubernetes

 

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: websocket-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: websocket-deployment
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

 

💡 เมื่อ CPU ใช้เกิน 70% → ระบบจะเพิ่ม Pod ใหม่โดยอัตโนมัติ

 

🧠 6. Best Practices

 

หมวดแนวทาง
Scalingใช้ Horizontal Scaling (K8s HPA)
Load Balancingกำหนด Sticky Session อย่างเหมาะสม
Messagingใช้ Redis Pub/Sub เพื่อ sync message
Monitoringใช้ Prometheus + Grafana เพื่อติดตาม Resource
Resilienceมี reconnect logic และ graceful shutdown เสมอ

 

🚀 ท้าให้ลอง!

 

  • สร้าง WebSocket Server 2 instance
  • เชื่อมต่อทั้งคู่กับ Redis Pub/Sub
  • เปิด 2 browser หรือ 2 เครื่อง แล้วส่งข้อความจากฝั่งหนึ่ง

 

✅ ถ้าข้อความส่งถึงทั้งสองฝั่งทันที → ยินดีด้วย! คุณกำลังก้าวเข้าสู่โครงสร้างระบบแบบ Production ที่แท้จริง

 


 

🌟 EP ถัดไป

 

📘 EP.111: การจัดการ Message Ordering และ Event Sequence

เรียนรู้วิธีจัดลำดับข้อความใน WebSocket ให้ “ไม่หลุด” แม้ในระบบที่มีการเชื่อมต่อพร้อมกันจำนวนมาก! เพื่อให้ผู้ใช้ทุกคนได้รับ Event แบบเรียงลำดับ 100% อย่างแม่นยำ