การดู : 0

12/04/2026 18:17น.

EP.86 การจัดการการเชื่อมต่อใน WebSocket ด้วย Redis Pub/Sub

EP.86 การจัดการการเชื่อมต่อใน WebSocket ด้วย Redis Pub/Sub

#Go

#Golang

#WebSocket

#Redis

#Redis Pub/Sub

เมื่อแอปพลิเคชันแบบ Real-time ขยายตัว ผู้ใช้งานเพิ่มขึ้น การรัน WebSocket Server เพียงเครื่องเดียวอาจไม่เพียงพอ — ทำให้เกิดความจำเป็นต้อง แยกเซิร์ฟเวอร์ WebSocket ออกเป็นหลายเครื่อง (multi-instance) เพื่อรองรับปริมาณการใช้งานขนาดใหญ่

 

ใน EP นี้ เราจะพาคุณเรียนรู้การใช้ Redis Pub/Sub เพื่อประสานการทำงานระหว่าง WebSocket Server หลายเครื่อง ให้ผู้ใช้ที่เชื่อมต่อกับเซิร์ฟเวอร์ใด ๆ ก็สามารถ ส่ง-รับข้อความร่วมกันได้แบบ Real-time

 

🔄 ทำไมต้องใช้ Redis Pub/Sub?

 

โดยปกติ WebSocket Server จะเก็บเฉพาะ connection ของ client ที่เชื่อมต่อกับตนเองเท่านั้น หากมีหลาย instance ผู้ใช้ที่อยู่บนเซิร์ฟเวอร์ A จะ ไม่สามารถส่งข้อความไปถึง ผู้ใช้ที่อยู่บนเซิร์ฟเวอร์ B ได้

 

Redis Pub/Sub ช่วยแก้ปัญหานี้ด้วยการทำตัวเป็น Message Broker ระหว่าง WebSocket Servers:

  • Publisher: เมื่อ client ส่งข้อความเข้าเซิร์ฟเวอร์ → เซิร์ฟเวอร์นั้น publish ข้อความไปยัง Redis channel
  • Subscriber: ทุก instance ของ WebSocket Server subscribe channel เดียวกัน และส่งข้อความนั้นไปยัง client ของตนเอง

 

✅ ผลลัพธ์:

  • ผู้ใช้ทุกคนได้รับข้อความเหมือนกัน ไม่ว่าจะต่อเข้าที่เครื่องไหน
  • ระบบสามารถ scale แนวนอน (horizontal scaling) ได้ง่าย

 

🧪 ตัวอย่างโค้ด Go + Redis Pub/Sub

 

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"

    "github.com/go-redis/redis/v8"
    "github.com/gorilla/websocket"
)

var (
    upgrader = websocket.Upgrader{
        CheckOrigin: func(r *http.Request) bool { return true },
    }
    clients = make(map[*websocket.Conn]bool)
    ctx     = context.Background()
)

func main() {
    rdb := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })

    go subscribeRedis(rdb)

    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        conn, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            log.Println("Upgrade error:", err)
            return
        }
        defer conn.Close()
        clients[conn] = true

        for {
            _, msg, err := conn.ReadMessage()
            if err != nil {
                log.Println("ReadMessage error:", err)
                delete(clients, conn)
                break
            }

            // Publish message to Redis
            if err := rdb.Publish(ctx, "chat_channel", msg).Err(); err != nil {
                log.Println("Publish error:", err)
            }
        }
    })

    log.Println("WebSocket server started on :8080")
    http.ListenAndServe(":8080", nil)
}

func subscribeRedis(rdb *redis.Client) {
    sub := rdb.Subscribe(ctx, "chat_channel")
    ch := sub.Channel()

    for msg := range ch {
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, []byte(msg.Payload)); err != nil {
                log.Println("WriteMessage error:", err)
                client.Close()
                delete(clients, client)
            }
        }
    }
}

 

🔍 อธิบายโค้ด

 

ส่วนรายละเอียด
clients mapเก็บ WebSocket connections ของผู้ใช้ที่เชื่อมต่อกับ instance นี้
rdb.Publishเมื่อมี client ส่งข้อความเข้ามา → ส่งไปยัง Redis channel
subscribeRedis()รับข้อความจาก Redis แล้วกระจายให้ client ที่เชื่อมต่อกับเครื่องนี้

 

💡 ประโยชน์ของการใช้ Redis Pub/Sub

 

  • ✅ รองรับ Multi-instance WebSocket Server
  • ✅ ขยายระบบแบบ Horizontal Scaling ได้ง่าย
  • ✅ รองรับผู้ใช้งานจำนวนมาก โดยไม่สูญเสียการสื่อสาร
  • ✅ ไม่ต้องให้เครื่อง server แต่ละตัวรู้จักกันโดยตรง

 


 

🚀 ท้าให้ลอง!

 

  • สร้างระบบ WebSocket Server หลาย instance (เช่น รันหลาย process หรือหลาย container)
  • เชื่อมต่อ Redis Pub/Sub เป็นตัวกลาง
  • ทดสอบว่า client ที่เชื่อมต่อกับคนละ server สามารถคุยกันได้จริง

 

🔜 Next EP:

 

EP.87: การป้องกัน DDoS ใน WebSocket Server

เราจะไปต่อกับการ ป้องกันการโจมตี เช่น DDoS, connection flood, และ malformed frame attacks เพื่อให้ระบบ WebSocket ของคุณพร้อมสำหรับงานจริง

 

อ่านบทความ 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/