外观
WebSocket 适合什么场景?
WebSocket 是一条可双向发送数据的长连接。服务器有事件时可以主动推给浏览器,不用客户端反复轮询。适合聊天、协作光标、行情和需要低延迟推送的后台。只是偶尔拉一次数据,用普通 HTTP。
原理
握手从 HTTP 开始:Upgrade: websocket。服务器用 101 同意切换,之后帧不再是 HTTP 报文。地址是 ws: 或 wss:,页面是 HTTPS 时要用 wss:。
浏览器 API 是 new WebSocket(url)。onopen、onmessage、onclose、onerror。发送文本或二进制。关闭要带上码和原因,页面卸载时关掉,避免连接残留。
它不是「永远不断」。中间网络会掐空闲连接,应用层要有心跳和重连,重连要退避,并且带上上次的序号或游标,避免消息重复或漏掉。身份放在首条消息或握手时的 Cookie 里,不要把长期令牌写进可以被日志记下的 URL。
轮询和 SSE 是替代方案。服务器推文本事件、浏览器只订阅时,SSE 更简单,走的是普通 HTTP。需要浏览器也频繁上行时再用 WebSocket。
追问
和 HTTP/2 的关系?
WebSocket 有自己的帧,不依赖 HTTP/2 的流。一条 WebSocket 通常是一条连接。很多小推送如果能放进 SSE 或按需请求,就不要为每个组件开一条套接字。
怎么做水平扩展?
连接落在某一台机器上。别的机器要推消息时,需要发布订阅把消息转到持有这条连接的进程。不能假设进程内存里能找到所有用户。
易错点
- 用短轮询的频率去打 WebSocket 的接口,连接数和心跳把服务器打满。
- 断线后立即无限重连。
- 把 WebSocket 当加密方案。明文
ws:可以被窃听,生产用wss:。