heartbeatMechanism
2024年10月18日
一、认识
WebSocket
心跳机制 是一种通过定期发送心跳消息来检查连接状态的方法。它确保客户端和服务器之间的连接保持活跃,并能够及时发现断开的连接。WebSocket
心跳机制 可以解决如下问题:
-
连接有效性: 确保连接仍然存在,防止因网络问题导致的静默断开。
-
资源管理: 及时关闭不再活跃的连接,释放服务器资源。
-
提高稳定性: 提高系统的稳定性和用户体验,避免因连接问题导致的消息丢失或延迟。
二、工作
-
定时发送心跳: 服务器(或客户端)定期发送心跳消息(如
ping
)到对方。 -
接收和回应: 接收方在收到心跳消息后,返回一个回应(如
pong
)。 -
检测连接状态: 如果在预定时间内未收到回应,发送方可以推测连接已断开并进行相应处理(如重连、关闭连接等)
三、实现
3.1 服务端
const Koa = require("koa");
const HTTP = require("http");
const WebSocket = require("ws");
const KoaRouter = require("koa-router");
const app = new Koa();
const router = new KoaRouter();
const server = HTTP.createServer(app.callback());
const wss = new WebSocket.Server({ server });
const HEARTBEAT_INTERVAL = 30000; // 心跳间隔时间
// 心跳机制,定期检查连接
function setupHeartbeat(webSocket) {
webSocket.isAlive = true; // 初始化心跳状态
const interval = setInterval(() => {
if (webSocket.isAlive === false) {
console.log("Terminating WebSocket due to no heartbeat response.");
return webSocket.terminate(); // 终止连接
}
webSocket.isAlive = false; // 设置为 false,等待响应
webSocket.ping(); // 发送 ping
}, HEARTBEAT_INTERVAL); // 每隔 HEARTBEAT_INTERVAL 秒检查一次
webSocket.on("pong", () => {
console.log("WebSockete pong received.");
webSocket.isAlive = true; // 收到心跳回应
});
webSocket.on("close", () => {
console.log("WebSocket closed 002");
clearInterval(interval); // 清除心跳检查
});
}
// WebSocket 连接处理
wss.on("connection", (ws) => {
setupHeartbeat(ws); // 设置心跳机制
ws.on("message", (message) => {
console.log("Received message:", message);
});
ws.on("close", () => {
console.log("WebSocket closed 001");
});
});
router.get("/", (ctx) => {
ctx.body = "WebSocket Server Running";
});
app.use(router.routes()).use(router.allowedMethods());
server.listen(3000, () => {
console.log("Server started on port 3000");
});
3.2 客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>WebSocket Heartbeat Example</h1>
<div id="status">Connecting...</div>
<script>
const socket = new WebSocket("ws://localhost:3000");
socket.addEventListener("open", () => {
document.getElementById("status").textContent = "Connected";
console.log("WebSocket connection established");
});
socket.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
// 不需要处理 heartbeat 相关的消息
});
socket.addEventListener("close", () => {
document.getElementById("status").textContent = "Disconnected";
console.log("WebSocket connection closed");
});
socket.addEventListener("error", (error) => {
console.error("WebSocket error:", error);
});
</script>
</body>
</html>