Chiến lược giao tiếp thời gian thực: Tại sao ChatGPT chọn SSE thay vì WebSocket?

Trong các ứng dụng web hiện đại, giao tiếp thời gian thực đóng vai trò quan trọng. Giao thức HTTP truyền thống với cơ chế request/response thường yêu cầu polling định kỳ để lấy dữ liệu mới nhất, gây lãng phí tài nguyên và kém hiệu quả. Điều này đã thúc đẩy sự ra đời của các công nghệ giao tiếp mới như WebSocket và SSE (Server-Sent Events). Tuy nhiên, tại sao ChatGPT lại chọn SSE thay vì WebSocket? Hãy cùng phân tích so sánh.

So sánh WebSocket và SSE

Cả WebSocket và SSE đều cho phép giao tiếp giữa trình duyệt và máy chủ. Dưới đây là những điểm khác biệt chính:

WebSocket

WebSocket là một giao thức giao tiếp hai chiều, thiết lập kết nối liên tục giữa client và server. Nó hỗ trợ các giao thức mới hơn (ví dụ: HTTP/2) và cho phép truyền tải dữ liệu ở nhiều định dạng. WebSocket có độ trễ thấp và hiệu suất cao, phù hợp với các ứng dụng yêu cầu trao đổi dữ liệu thời gian thực.

Nhược điểm: WebSocket yêu cầu duy trì kết nối trên máy chủ. Mỗi kết nối tiêu tốn tài nguyên, do đó khó mở rộng khi có số lượng lớn kết nối đồng thời.

SSE (Server-Sent Events)

SSE là giao thức một chiều (server → client), cho phép máy chủ gửi luồng sự kiện đến trình duyệt. Nó hoạt động trên nền tảng HTTP tiêu chuẩn, không cần thiết lập kết nối liên tục.

Ưu điểm: Dễ dàng mở rộng để xử lý hàng nghìn kết nối đồng thời mà không tốn nhiều tài nguyên.

Ví dụ triển khai

Phía Frontend


const eventSource = new EventSource("https://api.example.com/chat/stream");
eventSource.onmessage = (event) => {
  console.log(event.data);
};

Phía Backend (Java Servlet)


@WebServlet("/chat/stream")
public class ChatStreamServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
      throws ServletException, IOException {
    resp.setContentType("text/event-stream");
    resp.setCharacterEncoding("UTF-8");
    PrintWriter out = resp.getWriter();

    while (true) {
      String responseData = fetchChatData();
      out.write("data: " + responseData + "\n\n");
      out.flush();
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        break;
      }
    }
  }

  private String fetchChatData() {
    // Logic lấy dữ liệu từ mô hình ngôn ngữ
    return "Dữ liệu mới từ server";
  }
}

Quy trình giao tiếp SSE

  1. Client gửi yêu cầu SSE đến server với header Accept: text/event-stream.
  2. Server phản hồi với header Content-Type: text/event-stream và mã trạng thái 200.
  3. Server gửi luồng dữ liệu sự kiện theo định dạng:
    
    event: tên_sự_kiện
    data: nội_dung_dữ_liệu
        
    Mỗi khối dữ liệu kết thúc bằng \n\n.
  4. Client nhận và xử lý dữ liệu từ luồng sự kiện.
  5. Lặp lại bước 3-4 cho đến khi kết thúc phiên giao tiếp.

Với SSE, ChatGPT tận dụng được khả năng mở rộng dễ dàng và chi phí tài nguyên thấp, phù hợp với nhu cầu gửi dữ liệu một chiều mà không yêu cầu giao tiếp hai chiều phức tạp như WebSocket.

Thẻ: SSE Server-Sent Events WebSocket giao tiếp thời gian thực HTTP streaming

Đăng vào ngày 25 tháng 6 lúc 02:16