0
0
Lập trình
Admin Team
Admin Teamtechmely

SSE - Sự kiện gửi từ máy chủ trong Golang

Đăng vào 5 tháng trước

• 5 phút đọc

Giới thiệu

Nếu bạn từng muốn máy chủ của mình đẩy cập nhật trực tiếp đến trình duyệt mà không cần client liên tục kiểm tra, Server-Sent Events (SSE) là một giải pháp đơn giản và hiệu quả. Bài viết này sẽ khám phá SSE là gì, cách triển khai nó trong Golang, và lý do tại sao phía client cần sử dụng EventSource.

SSE là gì?

SSE là một tiêu chuẩn cho phép máy chủ gửi cập nhật liên tục qua một kết nối HTTP duy nhất đến client. Khác với WebSockets, SSE là một chiều — máy chủ gửi dữ liệu, nhưng client không thể gửi tin nhắn trở lại trên cùng một kết nối.

Ứng dụng phổ biến:

  • Bảng điều khiển trực tiếp và hệ thống giám sát.
  • Thông báo trò chuyện hoặc cập nhật nguồn tin xã hội.
  • Nhật ký thời gian thực hoặc bảng giá cổ phiếu.

Tạo máy chủ SSE trong Go

Dưới đây là cách triển khai một máy chủ SSE cơ bản bằng Go:

go Copy
package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/gorilla/mux"
)

func main() {
    router := mux.NewRouter()
    server := http.Server{
        Addr:    ":8080",
        Handler: router,
    }

    router.HandleFunc("/sse", handleEvents).Methods("GET")

    fmt.Println("Máy chủ SSE đang chạy trên :8080")
    err := server.ListenAndServe()
    if err != nil {
        panic(err)
    }
}

func handleEvents(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    ticker := time.NewTicker(2 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            fmt.Fprintf(w, "data: %s\n\n", time.Now().String())
            if f, ok := w.(http.Flusher); ok { f.Flush() }
        case <-r.Context().Done():
            return
        }
    }
}

Điểm chính:

  • Content-Type: text/event-stream là bắt buộc.
  • Mỗi tin nhắn phải bắt đầu bằng data: và kết thúc bằng hai dòng mới \n\n.
  • Sử dụng http.Flusher để đẩy dữ liệu ngay lập tức mà không cần đệm.

Phía Client – EventSource

SSE được thiết kế cho trình duyệt, với API EventSource có sẵn. Điều này làm cho việc nhận sự kiện từ máy chủ trở nên rất đơn giản:

html Copy
<script>
const es = new EventSource("http://localhost:8080/sse");

es.onopen = () => console.log("Kết nối SSE thành công");
es.onmessage = e => console.log("tin nhắn:", e.data);
es.onerror = e => console.error("Lỗi SSE", e);
</script>

Một số điểm nổi bật:

  • EventSource tự động kết nối lại nếu kết nối bị mất.
  • Nó phân tích dữ liệu: tin nhắn được gửi từ máy chủ.
  • Đây là lý do client thường cần một trình duyệt hoặc môi trường JS hỗ trợ EventSource.

SSE so với WebSockets

Trong khi SSE là hoàn hảo cho việc truyền dữ liệu từ máy chủ → client, cho giao tiếp hai chiều, nơi client cũng gửi tin nhắn đến máy chủ trong thời gian thực, WebSockets phù hợp hơn.

Đặc điểm SSE WebSockets
Hướng Một chiều (server → client) Hai chiều
Giao thức Hoạt động qua HTTP/HTTPS Phức tạp hơn nhưng linh hoạt
Triển khai Đơn giản Phức tạp hơn

Lưu ý nhanh về Streaming HTTP

SSE là một loại streaming HTTP, nơi máy chủ gửi dữ liệu theo từng khối mà không đóng kết nối. Streaming HTTP không chỉ giới hạn ở trình duyệt và có thể được sử dụng trong giao tiếp giữa các máy chủ.

Xem video demo

Tôi đã tạo một video ngắn để trình bày cách triển khai SSE trong Go, bao gồm mã máy chủ và cách EventSource xử lý dữ liệu trong trình duyệt.

Kết luận

SSE là một cách nhẹ nhàng và hiệu quả để đẩy cập nhật trực tiếp từ máy chủ đến trình duyệt. Nó đơn giản hơn WebSockets khi bạn chỉ cần giao tiếp từ máy chủ đến client, làm cho nó trở nên lý tưởng cho bảng điều khiển, nhật ký và thông báo.

Câu hỏi thường gặp (FAQ)

SSE có thể sử dụng cho những ứng dụng nào?

SSE rất phù hợp cho các ứng dụng yêu cầu cập nhật liên tục như bảng điều khiển trực tiếp, thông báo, và nhật ký thời gian thực.

Có thể sử dụng SSE với các ngôn ngữ khác ngoài Go không?

Có, SSE là một tiêu chuẩn HTTP và có thể được triển khai trên nhiều ngôn ngữ khác nhau như Node.js, Python, Java, v.v.

SSE có thể thay thế WebSockets không?

SSE không thể thay thế WebSockets hoàn toàn, nhưng nó là một giải pháp tốt cho các tình huống mà chỉ cần giao tiếp từ máy chủ đến client.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào