
WebSocket là gì?
WebSocket là giao thức truyền thông hai chiều (full-duplex) qua một kết nối TCP duy nhất, cho phép server và client trao đổi dữ liệu thời gian thực mà không cần client liên tục gửi yêu cầu (polling). Khác với HTTP truyền thống dựa trên mô hình request-response, WebSocket thiết lập kết nối bền vững sau handshake ban đầu, sau đó cả hai phía có thể đẩy dữ liệu ngay lập tức.
Tại sao cần WebSocket?
Các ứng dụng hiện đại như chat, bảng giá chứng khoán, game multiplayer, hoặc bảng điều khiển IoT yêu cầu cập nhật dữ liệu trong mili-giây. HTTP polling (gửi request định kỳ) tốn băng thông, tăng độ trễ và tải server. WebSocket giải quyết bằng cách giữ kết nối mở, server đẩy (push) dữ liệu đến client ngay khi có thay đổi.
Cách WebSocket hoạt động
- Handshake: Client gửi HTTP request với header
Upgrade: websocket. Server phản hồi101 Switching Protocolsnếu chấp nhận. - Kết nối bền vững: Sau handshake, kết nối TCP vẫn mở, cả hai phía gửi frame nhị phân hoặc text.
- Ping/Pong: Cơ chế heartbeat để phát hiện kết nối đứt gãy.
- Đóng kết nối: Bất kỳ phía nào gửi frame
Close, phía kia phản hồi và đóng TCP.

So sánh WebSocket, HTTP Polling, Server-Sent Events (SSE)
| Đặc điểm | HTTP Polling | SSE | WebSocket |
|---|---|---|---|
| Chiều truyền | Client → Server | Server → Client | Hai chiều |
| Kết nối | Ngắn, lặp lại | Bền vững (một chiều) | Bền vững (hai chiều) |
| Overhead | Cao (header mỗi request) | Thấp | Rất thấp (frame 2 byte) |
| Auto-reconnect | Tự xây dựng | Có sẵn (EventSource) | Cần tự xử lý |
| Phù hợp | Cập nhật hiếm | Feed một chiều | Real-time hai chiều |
Triển khai WebSocket với JavaScript (Client)
const ws = new WebSocket('wss://api.example.com/ws');
ws.onopen = () => {
console.log('Kết nối đã mở');
ws.send(JSON.stringify({type: 'subscribe', channel: 'prices'}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Nhận:', data);
// Cập nhật UI
};
ws.onclose = () => {
console.log('Đã đóng, thử kết nối lại sau 3s...');
setTimeout(() => location.reload(), 3000);
};
ws.onerror = (err) => console.error('Lỗi:', err);
Triển khai WebSocket Server với Node.js (ws library)
const WebSocket = require('ws');
const wss = new WebSocket.Server({port: 8080});
wss.on('connection', (ws, req) => {
console.log('Client mới kết nối');
ws.on('message', (msg) => {
const data = JSON.parse(msg);
if (data.type === 'subscribe') {
ws.channel = data.channel;
}
});
// Gửi dữ liệu định kỳ (ví dụ: giá cổ phiếu)
const interval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
channel: ws.channel,
price: (Math.random() * 100).toFixed(2),
time: Date.now()
}));
}
}, 1000);
ws.on('close', () => clearInterval(interval));
});

Xử lý reconnection và scaling
Kết nối WebSocket có thể đứt do mạng, proxy, hoặc server restart. Client cần logic reconnect với exponential backoff:
function connectWithRetry(url, retries = 0) {
const ws = new WebSocket(url);
ws.onclose = () => {
const delay = Math.min(1000 * 2 ** retries, 30000);
setTimeout(() => connectWithRetry(url, retries + 1), delay);
};
return ws;
}
Với hệ thống lớn, dùng Redis Pub/Sub hoặc message queue (RabbitMQ, Kafka) để đồng bộ message giữa nhiều instance server WebSocket. Sticky sessions hoặc shared state đảm bảo message đạt đúng client.
Bảo mật WebSocket
- Luôn dùng
wss://(WebSocket over TLS) trong production. - Xác thực qua token trong handshake (header
Authorizationhoặc query param). - Validate và sanitize mọi message nhận được từ client.
- Rate limit số lượng connection và message/giây mỗi IP.
Khi nào KHÔNG nên dùng WebSocket?
- Chỉ cần cập nhật một chiều hiếm khi → SSE nhẹ hơn.
- Ứng dụng CRUD truyền thống, không real-time → REST API đủ.
- Client behind corporate proxy chặn WebSocket → cần fallback polling.
