Skip to content

ADR-0001. WebSocket mở rộng theo chiều ngang qua một bus Redis pub/sub duy nhất

TrườngGiá trị
StatusAccepted
Date2026-03-28
DecidersPhat Nguyen
Supersedes-

Bối cảnh

  • Cập nhật thời gian thực (order, payment) phải đến được client POS/Admin bất kể instance Signal nào đang giữ socket.
  • Kết nối WebSocket gắn chặt với một process; trạng thái client trong bộ nhớ không thể chia sẻ giữa các replica.
  • Các service khác (Sale, Payment) phải đẩy được dữ liệu tới client mà không tự dựng WebSocket server riêng.
  • Chúng ta muốn một điểm biên thời gian thực duy nhất, không phải một WebSocket server nhúng trong mọi service.

Quyết định

Chúng ta sẽ chạy Signal là WebSocket server duy nhất và định tuyến mọi luồng phân phối xuyên instance / xuyên service qua một bus Redis pub/sub duy nhất.

  • Signal chứa WebSocketServerHelper (subscribe + publish); producer chỉ giữ một WebSocketEmitter nhẹ (chỉ publish).
  • sendToClient gửi cục bộ nếu client nằm trên instance này, nếu không sẽ publish lại lên Redis cho instance đang sở hữu client đó.
  • broadcast / sendToRoom luôn publish lên Redis để mỗi instance phân phối tới các client khớp ở phía cục bộ của nó.
  • Redis chạy ở chế độ single hoặc cluster (APP_ENV_WEBSOCKET_REDIS_*); mọi bên tham gia phải dùng chung một instance.

Hệ quả

ƯuNhược
Replica không trạng thái - mở rộng theo chiều ngang sau TraefikRedis trở thành phụ thuộc cứng / điểm lỗi đơn cho fan-out
Producer giữ gọn nhẹ (chỉ emitter, không có WS server)Phân phối xuyên instance chỉ ở mức cố gắng tối đa (bỏ qua nếu không instance nào subscribe)
Một điểm biên thời gian thực duy nhất để bảo mật và vận hànhMọi publisher phải cấu hình trỏ về cùng một Redis y hệt

Phương án đã cân nhắc

Phương ánƯuNhượcVì sao loại
WS server nhúng trong mỗi serviceKhông cần bus dùng chungN server cần bảo mật; client phải quản lý N socketVận hành nặng nề, lặp lại auth/mã hoá
Phiên gắn chặt (sticky), không busĐơn giảnPhá vỡ broadcast + phân phối xuyên instanceKhông đáp ứng yêu cầu "đến được mọi client"
Dùng Kafka làm bus phân phốiĐã có sẵnĐộ trễ cao hơn, không thiết kế cho fan-out pub/sub tức thờiRedis pub/sub phù hợp phân phối trực tiếp hơn

Tham chiếu

  • signal/src/components/websocket.component.ts (NxWebSocketComponent, bindEmitter)
  • signal/src/services/signal-event.service.ts (định tuyến cục bộ/từ xa của sendToClient)
  • Operations - fan-out đa instance

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.