WebSocket 与实时功能实现指南:聊天、通知与实时更新

实时功能已经成为现代网站的常见需求——在线客服、实时通知、协作文档编辑。实现这些功能的核心技术是 WebSocket。

WebSocket vs SSE vs 轮询

特性 轮询 SSE WebSocket
通信方向 客户端→服务端 服务端→客户端 双向
实时性 取决于轮询间隔 即时 即时
连接开销 每次请求都有 保持长连接 保持长连接
浏览器支持 所有 除 IE 外 除 IE 外
适用场景 简单定时刷新 推送通知 双向交互

WebSocket 服务端(Node.js + ws)

npm install ws
// server.js
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });

const clients = new Set();

server.on('connection', (ws) => {
  clients.add(ws);
  console.log('Client connected. Total:', clients.size);

  // 接收消息
  ws.on('message', (message) => {
    const data = JSON.parse(message);
    
    // 广播给所有客户端
    clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({
          type: 'message',
          user: data.user,
          content: data.content,
          time: new Date().toISOString()
        }));
      }
    });
  });

  // 断开连接
  ws.on('close', () => {
    clients.delete(ws);
    console.log('Client disconnected. Total:', clients.size);
  });
});

console.log('WebSocket server running on port 8080');

WebSocket 客户端

// 连接到 WebSocket 服务
const ws = new WebSocket('wss://example.com/ws');

// 连接打开
ws.addEventListener('open', () => {
  console.log('Connected');
  
  // 发送消息
  ws.send(JSON.stringify({
    user: 'Alice',
    content: 'Hello everyone!'
  }));
});

// 接收消息
ws.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  displayMessage(data.user, data.content);
});

// 连接关闭
ws.addEventListener('close', () => {
  console.log('Disconnected');
  // 自动重连(简单实现)
  setTimeout(() => {
    window.location.reload();
  }, 3000);
});

// 错误处理
ws.addEventListener('error', (error) => {
  console.error('WebSocket error:', error);
});

SSE(Server-Sent Events)方案

如果只需要服务端推送(不需要客户端发送),SSE 是更简单的选择:

// 服务端(Node.js)
app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
  });

  // 每秒推送当前时间
  setInterval(() => {
    res.write(`data: ${JSON.stringify({ time: new Date().toISOString() })}\n\n`);
  }, 1000);
});
// 客户端
const eventSource = new EventSource('/events');
eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Server time:', data.time);
};

部署注意事项

  1. Nginx 代理 WebSocket — 需要配置 Upgrade header
  2. 自动重连机制 — WebSocket 连接可能意外断开
  3. 连接管理 — 记录在线用户数,限制连接数
  4. 扩展性 — 多服务器环境需使用 Redis Pub/Sub 转发消息

16IDC 观察

如果你只需要服务端推送通知(如新评论、订单状态更新),SSE 比 WebSocket 更简单、兼容性更好。如果需要双向交互(如在线客服、协作编辑),WebSocket 是唯一选择。