การดู : 0

12/04/2026 18:17น.

EP.72 การสร้างระบบการบันทึกและจัดเก็บข้อมูลการสนทนา (Message Logging) ใน WebSocket

EP.72 การสร้างระบบการบันทึกและจัดเก็บข้อมูลการสนทนา (Message Logging) ใน WebSocket

#Real-Time Chat

#แชทเก็บประวัติ

#PostgreSQL

#ระบบแชท

#Message Logging

#Go

#WebSocket

ใน EP.72 นี้ เราจะพูดถึงการสร้างระบบการบันทึกและจัดเก็บข้อมูลการสนทนาใน WebSocket Chat ซึ่งระบบนี้จะช่วยให้สามารถเก็บข้อมูลการสนทนาแบบเรียลไทม์ที่ส่งไปและมาจาก WebSocket Server พร้อมทั้งจัดเก็บข้อความไว้ในฐานข้อมูล เพื่อให้ผู้ใช้สามารถเข้าถึงประวัติการสนทนาได้ภายหลัง

การจัดเก็บข้อมูลการสนทนาเป็นส่วนสำคัญสำหรับการติดตามประวัติการใช้งาน, การตรวจสอบเหตุการณ์ต่าง ๆ, และการนำข้อมูลไปใช้วิเคราะห์หรืออ้างอิงในอนาคต นอกจากนี้ยังช่วยในการตรวจสอบพฤติกรรมของผู้ใช้ และเพิ่มความปลอดภัยของระบบแชทโดยรวม

 

ทำไมต้องใช้ระบบการบันทึกและจัดเก็บข้อมูลการสนทนาใน WebSocket?

 

ระบบ Message Logging มีประโยชน์หลายด้าน ได้แก่:

  • บันทึกข้อมูลการสนทนา: เก็บข้อความจากผู้ใช้แต่ละคนแบบต่อเนื่อง เพื่อสามารถนำมาดูย้อนหลังได้
  • ตรวจสอบประวัติ: ตรวจสอบว่าใครส่งข้อความอะไร เมื่อใด และในบริบทใด
  • เพิ่มความปลอดภัย: ติดตามกิจกรรมในห้องแชท ช่วยป้องกันพฤติกรรมที่ไม่เหมาะสม
  • ป้องกันข้อมูลสูญหาย: หากระบบมีปัญหา ข้อความที่สำคัญจะไม่สูญหายเพราะถูกจัดเก็บไว้ในฐานข้อมูล

 

โครงสร้างของระบบการบันทึกและจัดเก็บข้อมูลการสนทนา

 

ระบบนี้ประกอบด้วยส่วนหลัก 3 ส่วน:

  1. การจัดเก็บข้อความลงฐานข้อมูล
    เก็บข้อมูล เช่น ผู้ส่ง, ข้อความ, เวลา และห้องแชท (ถ้ามี)
  2. การรับข้อความจาก WebSocket
    เมื่อ WebSocket Server รับข้อความจาก Client จะทำการบันทึกทันที
  3. การดึงข้อความย้อนหลัง
    เมื่อผู้ใช้ต้องการดูประวัติการสนทนา ระบบสามารถดึงข้อมูลมาแสดงได้อย่างรวดเร็ว

 

การเพิ่มระบบการบันทึกข้อมูลใน WebSocket Server

 

เราจะเริ่มต้นด้วยการตั้งค่า WebSocket Server และเชื่อมต่อกับฐานข้อมูล PostgreSQL เพื่อบันทึกข้อความจาก Client ที่ส่งเข้ามา

1. การตั้งค่า WebSocket Server

package main

import (
    "database/sql"
    "log"
    "net/http"
    "sync"
    "time"

    "github.com/gorilla/websocket"
    _ "github.com/lib/pq"
)

var (
    clients   = make(map[*websocket.Conn]bool)
    clientsMu sync.Mutex
    broadcast = make(chan Message)
    db        *sql.DB
)

type Message struct {
    User    string    `json:"user"`
    Message string    `json:"message"`
    Time    time.Time `json:"time"`
}

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func init() {
    var err error
    db, err = sql.Open("postgres", "user=username dbname=websocket_chat sslmode=disable")
    if err != nil {
        log.Fatal("Database connection error:", err)
    }
}

func handleConnections(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()

    clientsMu.Lock()
    clients[conn] = true
    clientsMu.Unlock()

    for {
        var msg Message
        if err := conn.ReadJSON(&msg); err != nil {
            log.Println("Read error:", err)
            clientsMu.Lock()
            delete(clients, conn)
            clientsMu.Unlock()
            break
        }

        msg.Time = time.Now()
        saveMessage(msg)
        broadcast <- msg
    }
}

func saveMessage(msg Message) {
    _, err := db.Exec("INSERT INTO messages (user, message, time) VALUES ($1, $2, $3)", msg.User, msg.Message, msg.Time)
    if err != nil {
        log.Println("Save message error:", err)
    }
}

func handleMessages() {
    for msg := range broadcast {
        clientsMu.Lock()
        for client := range clients {
            if err := client.WriteJSON(msg); err != nil {
                log.Println("Broadcast error:", err)
                client.Close()
                delete(clients, client)
            }
        }
        clientsMu.Unlock()
    }
}

func main() {
    http.HandleFunc("/ws", handleConnections)
    go handleMessages()

    log.Println("Server started on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

 

2. การตั้งค่าฐานข้อมูล (PostgreSQL)

สร้างตารางเพื่อเก็บข้อความที่ถูกส่งผ่าน WebSocket:

CREATE TABLE messages (
    id SERIAL PRIMARY KEY,
    user VARCHAR(100),
    message TEXT,
    time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

 

3. การดึงข้อมูลจากฐานข้อมูล

func getMessages() ([]Message, error) {
    rows, err := db.Query("SELECT user, message, time FROM messages ORDER BY time DESC")
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var messages []Message
    for rows.Next() {
        var msg Message
        if err := rows.Scan(&msg.User, &msg.Message, &msg.Time); err != nil {
            return nil, err
        }
        messages = append(messages, msg)
    }
    return messages, nil
}

 

การทดสอบระบบการบันทึกข้อมูลการสนทนา

การทดสอบควรครอบคลุม:

  • ✅ การบันทึกข้อความ: เมื่อผู้ใช้ส่งข้อความ ข้อมูลต้องถูกเก็บในฐานข้อมูลทันที
  • ✅ การดึงข้อความย้อนหลัง: สามารถดึงข้อความจากฐานข้อมูลกลับมาแสดงได้ครบถ้วน
  • ✅ ประสิทธิภาพเมื่อโหลดสูง: ทดสอบการรองรับผู้ใช้จำนวนมาก และข้อความจำนวนมาก

 


 

ท้าให้ลอง!

เพิ่มฟีเจอร์ “การค้นหาข้อความ” จากฐานข้อมูล โดยให้ผู้ใช้สามารถค้นหาคีย์เวิร์ดจากประวัติการสนทนาได้แบบเรียลไทม์ 🔍

 

EP ถัดไป:

ใน EP.73 เราจะมาดู การปรับปรุงการเชื่อมต่อ WebSocket ด้วย WebSocket Compression เพื่อเพิ่มประสิทธิภาพในการส่งข้อมูล ลด Bandwidth และปรับปรุงประสบการณ์ของผู้ใช้!

 

อ่านบทความ Series อื่นๆ

🔵 Facebook: Superdev School  (Superdev)

📸 Instagram: superdevschool

🎬 TikTok: superdevschool

🌐 Website: www.superdev.school