websocket是什么以及它要怎么用
WebSocket 实时通知机制。
在高并发、异步下单场景中,它是提升用户体验、降低轮询压力的关键组件。
接下来会从原理讲清楚,再结合“秒杀活动”落地展示完整的前后端交互与代码实现(Java Spring Boot + 前端示例)。
一、WebSocket 是什么?
WebSocket 是一种在浏览器和服务器之间建立「全双工、持久连接」的通信协议。
与传统 HTTP 不同,HTTP 是短连接、请求响应式的;而 WebSocket 建立连接后,服务器可以主动推送消息给客户端,不需要客户端轮询。
🔁 对比传统 HTTP 轮询
| 特点 | HTTP 轮询 | WebSocket |
|---|---|---|
| 连接模式 | 短连接,请求-响应 | 持久连接,双向通信 |
| 服务器能否主动发消息 | ❌ 不能 | ✅ 可以 |
| 性能 | 频繁请求,压力大 | 长连接,轻量、实时 |
| 适用场景 | 请求量小、实时性低 | 聊天、订单状态、秒杀、行情推送 |
二、在「秒杀活动」中为什么用 WebSocket?
在你的秒杀设计中:
-
用户点击“立即抢购” → 系统用 Redis + MQ 异步下单;
-
请求立即返回
"QUEUED"状态; -
后端在队列消费者落单后,才知道成功或失败。
如果不用 WebSocket:
-
用户只能轮询
GET /seckill/status?messageId=...; -
并发量高时,会造成 Web 层 + Redis + DB 压力。
如果用 WebSocket:
-
用户请求秒杀后,保持 WebSocket 长连接;
-
后端消费者落单完成时,通过 WebSocket 通道主动推送订单状态变更;
-
用户即时看到结果,不需要反复刷新。
👉 实时、节流、省资源。
三、WebSocket 在秒杀系统中的使用流程(图解)
┌──────────────────────┐
│ 浏览器端 │
│ 1. 建立 WebSocket │
│ 2. 发送秒杀请求 │
│ 3. 等待推送结果 │
└──────────┬───────────┘
│
WebSocket 连接
│
┌──────────▼──────────┐
│ 秒杀服务 (Spring) │
│ - 维护连接映射表 │
│ - 通过 MQ 消费结果 │
│ - 推送状态到客户端 │
└──────────┬───────────┘
│
MQ/Rabbit
│
┌──────────▼──────────┐
│ 消费者服务 │
│ - 创建订单 │
│ - 发送结果通知 │
└──────────────────────┘
四、详细实现(Java + 前端)
🔹 前端实现(示例)
假设前端是一个简单的 Vue / HTML 页面。
<!DOCTYPE html> <html> <head> <title>秒杀活动</title> </head> <body> <h2>秒杀活动</h2> <button id="buyBtn">立即抢购</button> <div id="status"></div> <script> const userId = "user_123"; const ws = new WebSocket(`ws://localhost:8080/ws/seckill/${userId}`); ws.onopen = () => { console.log("✅ WebSocket connected"); }; ws.onmessage = (event) => { const msg = JSON.parse(event.data); if (msg.type === "ORDER_STATUS") { document.getElementById("status").innerText = "订单状态: " + msg.status; } }; document.getElementById("buyBtn").onclick = async () => { const res = await fetch("/api/seckill/buy?eventId=1001&userId=" + userId, { method: "POST" }); const data = await res.json(); document.getElementById("status").innerText = "请求结果: " + data.status; }; </script> </body> </html>
说明:
-
页面在加载时与服务器建立 WebSocket 长连接;
-
当用户点击“立即抢购”后,发起 HTTP 下单请求;
-
后端在订单异步完成后,通过 WebSocket 主动推送消息;
-
前端即时更新显示。
🔹 后端实现(Spring Boot)
我们需要三个部分:
-
WebSocket 服务端(负责连接与推送)
-
秒杀请求 Controller(发起秒杀逻辑)
-
订单消费者(异步落单后推送结果)
1️⃣ WebSocket 配置与服务端类
// WebSocketConfig.java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new SeckillWebSocketHandler(), "/ws/seckill/{userId}") .setAllowedOrigins("*"); // 生产环境记得做白名单 } }
// SeckillWebSocketHandler.java @Component public class SeckillWebSocketHandler extends TextWebSocketHandler { // 存储所有用户连接(简单实现,可换为 Redis + Channel 分布式映射) private static final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { String userId = getUserId(session); userSessions.put(userId, session); System.out.println("用户 " + userId + " 已连接"); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { String userId = getUserId(session); userSessions.remove(userId); System.out.println("用户 " + userId + " 已断开"); } private String getUserId(WebSocketSession session) { return session.getUri().getPath().split("/ws/seckill/")[1]; } public void sendMessageToUser(String userId, String message) { WebSocketSession session = userSessions.get(userId); if (session != null && session.isOpen()) { try { session.sendMessage(new TextMessage(message)); } catch (IOException e) { e.printStackTrace(); } } } }
2️⃣ 秒杀 Controller(异步下单 + 即时返回)

浙公网安备 33010602011771号