服务器推送消息给客户端,核心是通过建立持久连接或模拟实时通信来实现,目前最推荐的方式是WebSocket,而开启消息推送的关键在于服务端和客户端的协议握手和配置。
服务器推送消息的常见方式对比
在具体实现服务器向客户端推送消息时,不同技术方案各有适用场景,选择哪一种,取决于你的业务对实时性、兼容性以及成本的要求。
WebSocket:全双工实时通信
WebSocket是当前最主流的服务器推送方案,它在客户端和服务器之间建立一条持久的TCP连接,两端可以随时互相发送数据,业内专家指出,WebSocket在实时性要求高的场景(如在线聊天、协同编辑、游戏)中几乎成为标配。
优点:真正的双向通信,延迟低,头部开销小,支持二进制帧。
缺点:需要服务器和浏览器同时支持,部分老旧环境(如IE10以下)不兼容,但现代浏览器都已支持。
SSE(Server-Sent Events):单向推送利器
SSE是HTML5标准的一部分,专门用于服务器向客户端单向推送文本数据,它基于HTTP协议,使用简单,不需要像WebSocket那样额外升级协议。
优点:实现简单,原生支持断线重连,自动识别消息ID,适合推送通知、实时行情等单向信息流。
缺点:只能从服务器到客户端,不支持客户端发送数据;连接数有限制(浏览器通常限制同域名6个);不支持二进制数据。
长轮询:兼容性方案
长轮询是早期技术,客户端发起请求后服务器保持连接直到有数据返回或超时,然后客户端立即再次发起请求,它在WebSocket普及前被广泛使用,如今主要用于需要兼容老旧浏览器的场景。
优点:几乎兼容所有浏览器和服务器,不需要额外协议升级。
缺点:实时性较差,每次请求都携带HTTP头部,带宽消耗大,服务器压力高。
| 方案 | 通信方向 | 实时性 | 浏览器兼容性 | 典型场景 |
|---|---|---|---|---|
| WebSocket | 全双工 | 极高 | 现代浏览器 | 聊天、游戏、实时协作 |
| SSE | 单向(服务器→客户端) | 高 | 除IE外的现代浏览器 | 通知、行情、日志推送 |
| 长轮询 | 半双工(模拟) | 中等 | 全兼容 | 兼容老旧环境的实时功能 |
如何开启消息推送:从零开始配置
不论你选择哪种方案,开启消息推送都涉及服务端和客户端两端的配置,以下以最常见的WebSocket和SSE为例,给出具体操作步骤。
服务端开启消息推送(以Node.js和Spring Boot为例)
Node.js 使用 ws 库搭建 WebSocket 服务
- 安装包:
npm install ws - 创建服务:
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', function connection(ws) { ws.on('message', function incoming(data) { // 接收客户端消息 console.log('received: %s', data); }); ws.send('你好,连接已建立'); }); - 启动后,客户端通过
new WebSocket('ws://localhost:8080')连接。
Spring Boot 开启 WebSocket 消息推送
- 添加依赖:
spring-boot-starter-websocket - 配置类:
@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyHandler(), "/ws").setAllowedOrigins(""); } } - 实现处理器,重写
afterConnectionEstablished和handleTextMessage方法。
SSE 服务端实现(Spring Boot)
使用 SseEmitter 即可:
@GetMapping("/subscribe")
public SseEmitter subscribe() {
SseEmitter emitter = new SseEmitter(0L); // 0L表示不超时
// 保存emitter,用于后续推送
return emitter;
}
推送时调用 emitter.send(data) 即可。
客户端如何接收推送消息
WebSocket 客户端(浏览器端)
const socket = new WebSocket('ws://your-server.com/ws');
socket.onopen = function() {
console.log('连接已建立');
};
socket.onmessage = function(event) {
console.log('收到消息:', event.data);
};
socket.onclose = function() {
console.log('连接关闭');
};

SSE 客户端
const eventSource = new EventSource('/subscribe');
eventSource.onmessage = function(event) {
console.log('收到推送:', event.data);
};
SSE 原生支持断线重连,如果连接断开,浏览器会自动尝试重新连接。
消息推送的验证与调试
开启消息推送后,务必验证连通性,可以使用浏览器开发者工具查看网络请求,WebSocket 连接会显示为 101 状态码切换协议,SSE 则显示为 text/event-stream 的响应,你也可以用在线工具如 WebSocket 在线测试 来快速验证服务端是否正常。
消息推送方案选择指南
选对方案,不仅能提升用户体验,还能节省服务器资源,以下从场景、成本、地域三个维度帮你决策。
根据场景选择
- 实时双向交互(聊天、远程控制):首选 WebSocket,全双工通信无延迟。
- 单向通知推送(系统通知、股价更新、日志流):SSE 足够,实现简单且资源占用小。
- 兼容老旧浏览器(如内部OA系统用IE):长轮询仍然是兜底方案,但建议逐步迁移到 WebSocket 配合 polyfill。
成本与价格考量
服务器消息推送的成本主要来自带宽和连接数,WebSocket 因为连接持久,每个客户端占用一个连接,当并发量巨大时,对服务器内存和连接数管理有要求,一些云厂商提供 WebSocket 消息推送服务,价格按连接时长和消息条数计费,在选型前建议评估日均消息量和并发峰值,对于小规模应用,自建 WebSocket 服务成本更低,但需要自行处理高可用和扩容。
地域因素
国内使用 WebSocket 和 SSE 时,需要留意服务器部署位置,如果用户主要在国内,建议选择国内主流云服务器,并确保备案域名,同时注意 WebSocket 在部分运营商网络下可能存在连接不稳定问题,可以通过心跳机制和重试策略优化,对于海外用户,则需考虑服务器节点的地域分布,以降低延迟。
消息推送常见问题与优化
连接断开与重连
WebSocket 和 SSE 都可能因网络波动而断开,SSE 有自动重连机制,但 WebSocket 需要手动实现,通用的做法是在客户端监听

onclose 事件,设置指数退避重试策略,避免频繁重连导致服务器压力。
心跳机制
长时间无消息的 WebSocket 连接可能被中间设备(如路由器、防火墙)关闭,建议每隔一段时间(如30秒)发送一个小的心跳包(ping/pong),保持连接活跃,SSE 本身没有心跳,但可以借助 Comment 字段或定时发送空数据。
安全性
- 使用
wss://代替ws://,加密传输。 - 客户端连接时校验身份(如携带 token 在 URL 参数或首条消息中)。
- 限制同一用户的最大连接数,防止恶意占用资源。
对于多数中小型项目,使用 WebSocket 配合成熟的开源库(如 socket.io、ws、Spring WebSocket)即可满足需求。服务器推送消息的最佳实践是:优先选择 WebSocket,单向推送用 SSE,老旧环境用长轮询兜底,同时做好重连、心跳和安全性配置。
服务器推送消息给客户端常见问题解答
服务器如何推送消息给客户端,不依赖第三方服务?
如果不想使用第三方推送服务,完全可以自建,只要服务器端支持 WebSocket 或 SSE 协议,自己编写处理逻辑即可,具体步骤参考上文“如何开启消息推送”部分,以 Node.js 或 Spring Boot 为例,几十行代码就能实现。
如何开启消息推送功能,需要额外购买服务器资源吗?
开启消息推送本身不需要额外购买资源,只要你的服务器能处理 HTTP 请求即可,WebSocket 和 SSE 都基于现有端口(如 80/443),但长连接会消耗更多内存和连接数,如果并发量较大,需要考虑横向扩展或多线程处理,这时可能需要对服务器进行升级或使用云服务。开启消息推送的关键在于代码层面的配置,而非硬件门槛。
长轮询和WebSocket对比,哪个更适合即时通讯?
从实时性和资源开销来看,WebSocket 明显优于长轮询,WebSocket 建立一次连接后持续通信,延迟低,服务器负载小;长轮询每次请求都携带大量头部,且频繁建立连接,在高并发场景下服务器压力大。除需兼容极老旧浏览器外,即时通讯场景应首选 WebSocket,如果你需要快速实现,可考虑使用 socket.io 这类库,它在不支持 WebSocket 的环境下会自动降级为长轮询。
