การดู : 0

04/03/2026 08:45น.

EP.114 การจัดการ Multi-device & Multi-session สำหรับ WebSocket Server

EP.114 การจัดการ Multi-device & Multi-session สำหรับ WebSocket Server

#WebSocket Server

#Real-time System

#Go

#Multi-session

#Multi-device

#WebSocket

ในแอปพลิเคชันแบบเรียลไทม์ ไม่ว่าจะเป็นระบบแชท, การแจ้งเตือน, หรือเกม ผู้ใช้ 1 คนอาจล็อกอินจากหลายอุปกรณ์ได้พร้อมกัน เช่น มือถือและเดสก์ท็อป 💻📱

 

หากระบบ WebSocket ไม่รองรับ Multi-device หรือ Multi-session อย่างถูกต้อง อาจเกิดปัญหา Sync ไม่ทัน, ข้อมูลซ้ำซ้อน หรือ session รั่ว

 

ใน EP นี้ เราจะพาคุณเรียนรู้การออกแบบระบบ WebSocket ที่

  • รองรับผู้ใช้หลายอุปกรณ์พร้อมกัน
  • จัดการ session แยกกันอย่างปลอดภัย
  • ซิงก์ข้อมูลระหว่างอุปกรณ์แบบเรียลไทม์
  • พร้อมใช้งานจริงในระดับ Production

 

🔍 ปัญหาที่พบบ่อยเมื่อมีหลาย Session

 

ปัญหาคำอธิบาย
Session ซ้ำผู้ใช้เปิดหลายอุปกรณ์พร้อมกัน ทำให้เกิดข้อความซ้ำ
Connection Leaksession เดิมไม่ถูกปิดเมื่อมีอุปกรณ์ใหม่เชื่อมต่อ
Token หมดอายุไม่จัดการ refresh token อย่างเหมาะสม ทำให้หลุดการเชื่อมต่อ
Sync ล่าช้าข้อมูลอัปเดตไม่พร้อมกันทุกอุปกรณ์

 

แนวทางที่ดี: อุปกรณ์แต่ละเครื่องควรมี session แยก แต่ Sync ข้อมูลเหมือนกัน

 

🧩 โครงสร้าง Session ใน WebSocket

 

type Session struct {
	UserID     string
	DeviceID   string
	Connection *websocket.Conn
}

var (
	activeSessions = make(map[string]map[string]*Session) // userID → deviceID → session
	mu             sync.Mutex
)

 

✅ ผู้ใช้ 1 คนสามารถมีหลายอุปกรณ์
✅ ทุกอุปกรณ์มี session แยกกัน
✅ สามารถส่งข้อความเฉพาะเครื่อง หรือ broadcast ทุก session ได้

 

🔌 ตัวอย่างการเชื่อมต่อจากหลายอุปกรณ์

 

func handleConnection(w http.ResponseWriter, r *http.Request) {
	conn, _ := upgrader.Upgrade(w, r, nil)
	userID := r.URL.Query().Get("user_id")
	deviceID := r.URL.Query().Get("device_id")

	mu.Lock()
	if activeSessions[userID] == nil {
		activeSessions[userID] = make(map[string]*Session)
	}
	activeSessions[userID][deviceID] = &Session{
		UserID:     userID,
		DeviceID:   deviceID,
		Connection: conn,
	}
	mu.Unlock()

	defer func() {
		mu.Lock()
		delete(activeSessions[userID], deviceID)
		if len(activeSessions[userID]) == 0 {
			delete(activeSessions, userID)
		}
		mu.Unlock()
		conn.Close()
	}()

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			break
		}
		log.Printf("[%s-%s]: %s", userID, deviceID, msg)
	}
}

 

✅ เมื่ออุปกรณ์ใดหลุดออก จะลบ session อัตโนมัติ
✅ ไม่มี session ค้างในระบบ

 

🔐 การตรวจสอบ Token และ Session

 

func validateToken(token string) (string, error) {
	claims := &jwt.StandardClaims{}
	_, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) {
		return []byte("SECRET_KEY"), nil
	})
	if err != nil {
		return "", err
	}
	return claims.Subject, nil
}

 

  • ทุกอุปกรณ์ควรใช้ token ของตัวเอง
  • refresh token แยกตามอุปกรณ์
  • ถ้า token หมดอายุ → ตัดการเชื่อมต่อเฉพาะเครื่องนั้น

 

🌐 การ Sync ข้อมูลระหว่างอุปกรณ์

 

func syncToAllDevices(userID string, message string) {
	mu.Lock()
	defer mu.Unlock()
	for _, session := range activeSessions[userID] {
		session.Connection.WriteMessage(websocket.TextMessage, []byte(message))
	}
}

 

✅ ส่งข้อความจากมือถือ → ขึ้นบนคอมพร้อมกัน
✅ Sync ข้ามอุปกรณ์แบบเรียลไทม์
✅ รองรับการใช้งานในระบบ Production ได้จริง

 

🧱 แนวทางระดับ Production

 

หมวดแนวทาง
Session Storageใช้ Redis หรือ DB จัดเก็บ session
Securityผูก Token กับ Device ID
SyncRedis Pub/Sub กระจายข้อมูล
Timeoutลบ session ที่ idle เกินเวลา
Monitoringติดตามจำนวนอุปกรณ์ต่อผู้ใช้

 

🚀 ท้าให้ลอง!

 

ลองเขียนระบบที่ให้ผู้ใช้ 1 คนเปิดทั้งมือถือและคอม ส่งข้อความจากเครื่องหนึ่ง → อีกเครื่องต้องอัปเดตทันที

 

ถ้าทำได้สำเร็จ คุณกำลังสร้างระบบแบบเดียวกับที่องค์กรใหญ่ใช้จริงแล้วในวันนี้ ✅

 


 

🌟 EP ถัดไป: ระบบ Multiplayer Game ขั้นสูง (EP.115)

 

ใน EP.115 เราจะพาไปสู่โลกของเกมแบบหลายผู้เล่น เรียนรู้การ sync ผู้เล่น, event, และตำแหน่งในเกมแบบ real-time ด้วย Go และ WebSocket เพื่อให้คุณพร้อมสร้างเกมหรือระบบแบบ Interactive ได้แบบมืออาชีพ! 🎮