JavaScript什么是WebSocket_实时通信如何搭建

12次阅读

websocket是独立于http的全双工TCP协议,非HTTP升级版;关键在稳定性、可扩展性与兜底机制,而非仅连接建立。

JavaScript什么是WebSocket_实时通信如何搭建

WebSocket 不是 HTTP 的升级版,而是独立的全双工通信协议;用它做实时通信,关键不在“怎么连”,而在“怎么稳、怎么扩、怎么兜底”。

WebSocket 是什么?和 ajax / SSE 有什么本质区别?

WebSocket 是浏览器与服务器之间建立的持久化 TCP 连接,双方可随时主动发消息。它不是轮询(AJAX),也不依赖 HTTP 长连接(SSE)——握手阶段走一次 HTTP Upgrade 请求,之后就完全脱离 HTTP 协议

常见误解:

  • 以为 new WebSocket() 成功就代表通信可靠(实际只表示握手成功,后续网络中断不会自动重连)
  • 把 WebSocket 当作“更快的 AJAX”来用(它不支持请求/响应语义,没有状态码、headers、自动重试)
  • 忽略服务端必须部署 WebSocket 兼容服务(node.jswssocket.io,或 nginxproxy_http_version 1.1 + Upgrade 转发)

前端怎么安全地创建并维持一个 WebSocket 连接?

浏览器原生 WebSocket API 极简,但缺重连、心跳、错误分类等生产必需能力。别直接裸用 new WebSocket(url)

立即学习Java免费学习笔记(深入)”;

实操建议:

  • 封装层管理生命周期:连接中、重连中、断开、失败,每种状态都显式处理
  • 必须加心跳(ping/pong):服务端没发 pong 或客户端超时未收,就主动 close() 并触发重连
  • 重连要退避:首次 1s,失败后 2s、4s、8s…最大不超过 30s,避免雪崩式重连
  • 不要在 onerror 里重连:它不区分网络错误、证书错误、服务不可达,且可能被多次触发;应以 onclose 为主判断依据

简单心跳示例(客户端):

let ws = null; let pingTimer = null;  function connect() {   ws = new WebSocket('wss://api.example.com/ws');      ws.onopen = () => {     console.log('connected');     startPing();   };    ws.onmessage = (e) => {     const data = JSON.parse(e.data);     // 处理业务消息   };    ws.onclose = () => {     console.log('disconnected, retrying...');     clearTimeout(pingTimer);     setTimeout(connect, 1000); // 简单退避   }; }  function startPing() {   if (ws.readyState === WebSocket.OPEN) {     ws.send(jsON.Stringify({ type: 'ping' }));   }   pingTimer = setTimeout(startPing, 30000); }

node.js 后端用 ws 库搭一个最小可用 WebSocket 服务要注意什么?

ws 是最轻量、最贴近协议标准的库,但它不提供房间、广播、鉴权等上层功能——这些得自己补。

关键点:

  • 必须校验 originToken:WebSocket 握手请求是 HTTP GET,可在 verifyClient 钩子中检查 req.headers.originreq.url 带的 token 参数
  • 连接数暴增时,ws.Server 默认不限制并发,需手动控制(如用 maxPayload 防大包、用 verifyClient 拒绝非法请求)
  • 发消息前务必检查 ws.readyState === WebSocket.OPEN异步操作中连接可能已断,否则会抛 InvalidStateError
  • 别用 ws.send() 直接发对象:它只接受 stringBufferjson 要先 JSON.stringify()

最小服务示例(带基础鉴权):

const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 });  wss.on('connection', (ws, req) => {   const url = new URL(req.url, 'http://localhost');   const token = url.searchParams.get('token');      if (!token || token !== 'my-secret') {     ws.close(4001, 'Invalid token');     return;   }    ws.on('message', (data) => {     try {       const msg = JSON.parse(data.toString());       console.log('received:', msg);       // 回复确认       if (ws.readyState === WebSocket.OPEN) {         ws.send(JSON.stringify({ ack: msg.id }));       }     } catch (e) {       ws.close(4002, 'Invalid JSON');     }   }); });

为什么上线后 WebSocket 经常“假连”或“秒断”?Nginx 和 TLS 是最大雷区

90% 的线上 WebSocket 故障不出现在业务逻辑,而出现在反向代理或证书配置上。

典型问题:

  • Nginx 默认不转发 Upgrade 请求:必须显式配置 proxy_set_header Upgrade $http_upgradeproxy_set_header Connection "upgrade"
  • https 下用 ws:// 会被浏览器拦截:前端必须用 wss://,且证书要有效(自签名证书需用户手动信任)
  • 某些云厂商 LB(如阿里云 SLB)默认关闭 WebSocket 支持,需单独开启“长连接”或“WebSocket 协议识别”开关
  • 移动端弱网下,TCP Keepalive 时间过长(linux 默认 7200s),导致 NAT 设备提前清空连接表;需在服务端设置 pingInterval 主动保活

Nginx 关键配置片段:

location /ws {   proxy_pass https://backend;   proxy_http_version 1.1;   proxy_set_header Upgrade $http_upgrade;   proxy_set_header Connection "upgrade";   proxy_set_header Host $host;   proxy_set_header X-Real-IP $remote_addr;   proxy_read_timeout 60; }

真正难的不是“搭起来”,而是让连接在弱网、切后台、锁屏、证书更新、服务滚动发布这些场景下依然能自动恢复——这些细节没处理好,实时性就只是幻觉。

text=ZqhQzanResources