心跳与连接保活
学习使用 ping/pong 帧和应用层心跳来维持连接活跃状态,并检测失效的对端。
心跳与连接保活 是 CoddyKit 上的免费 WebSockets & Realtime Systems Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 WebSockets & Realtime Systems Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 WebSockets & Realtime Systems Programming 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Heartbeats Matter
In realtime applications, maintaining an active and healthy connection is crucial. But what happens if a connection silently drops?
- Heartbeats are small, periodic messages exchanged between connected parties.
- They act as a 'pulse check' to confirm that both the client and server are still alive and responsive.
- This helps detect 'dead' connections that haven't properly closed, preventing resources from being tied up indefinitely.
The Silent Dead Peer
Imagine a client suddenly losing network connectivity (e.g., Wi-Fi drops, device sleeps) without gracefully closing its WebSocket connection.
- The server might still think the client is connected.
- Messages sent to this 'dead' client will never arrive.
- This wastes server resources and leads to inconsistent application states.
- Heartbeats provide a way to proactively identify and terminate these unresponsive connections.
Native WebSocket Pings
The WebSocket protocol includes built-in mechanisms for heartbeats: Ping and Pong frames.
- A server (or client) can send a special
Pingframe to its peer. - Upon receiving a
Ping, the peer is expected to automatically respond with aPongframe. - These frames are lightweight control messages, not application data.
- They confirm the underlying TCP connection is still active and can transmit data.
Server Sends Ping (Node.js)
Here's how a Node.js WebSocket server can send periodic ping frames to its connected clients. The ws library handles the low-level details.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Client connected');
// Send a ping every 5 seconds
const pingInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
console.log('Server sent ping.');
}
}, 5000);
ws.on('pong', () => {
console.log('Client responded with pong!');
});
ws.on('close', () => {
console.log('Client disconnected');
clearInterval(pingInterval);
});
ws.on('error', error => {
console.error('WS error:', error);
clearInterval(pingInterval);
});
});
console.log('Server running on ws://localhost:8080');Client Pongs Automatically
When a WebSocket client (like a browser or Node.js client using ws) receives a native Ping frame:
- It automatically sends back a
Pongframe without any explicit code from you. - This makes native pings very efficient for basic connection liveness checks.
- If a
Pingis sent and noPongis received within a timeout, the server can infer the connection is dead and close it.
Beyond Native Pings
While native Ping/Pong frames are great for TCP connection liveness, they have limitations:
- They don't check if the application layer is still responsive.
- Proxies or load balancers might sometimes interfere with or not forward these control frames correctly.
- They don't provide a way to carry custom data, like a timestamp or a user ID.
This is where application-level heartbeats come in.
App Heartbeat Scenarios
Application-level heartbeats are custom messages sent over the WebSocket connection, designed to be handled by your application logic. They are useful for:
- Detecting liveness through WebSocket-unaware proxies.
- Ensuring the application itself (not just the TCP connection) is responsive.
- Implementing more sophisticated timeouts based on user activity, not just network activity.
- Allowing custom data payloads (e.g., client status, last active time).
Client App Heartbeat (Node.js)
A client can send custom 'heartbeat' messages at regular intervals. This example uses a Node.js client, but browser clients would follow a similar pattern.
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:8080');
let appHeartbeatInterval;
ws.onopen = () => {
console.log('Connected to server.');
// Send a custom heartbeat every 3 seconds
appHeartbeatInterval = setInterval(() => {
const message = JSON.stringify({
type: 'APP_HEARTBEAT',
timestamp: Date.now()
});
ws.send(message);
console.log('Client sent APP_HEARTBEAT.');
}, 3000);
};
ws.onmessage = event => {
console.log('Received:', event.data);
};
ws.onclose = () => {
console.log('Disconnected.');
clearInterval(appHeartbeatInterval);
};
ws.onerror = error => {
console.error('WS error:', error);
clearInterval(appHeartbeatInterval);
};Server Tracks App Heartbeats
The server receives these custom messages and updates a 'last seen' timestamp for each client. If a client's timestamp isn't updated for too long, the server can close the connection.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', ws => {
console.log('Client connected');
ws.lastAppHeartbeat = Date.now(); // Initialize timestamp
const checkInterval = setInterval(() => {
// If no app heartbeat in 6 seconds, assume dead
if (Date.now() - ws.lastAppHeartbeat > 6000) {
console.log('Client unresponsive (app heartbeat). Terminating.');
ws.terminate(); // Force close the connection
clearInterval(checkInterval);
}
}, 2000); // Check every 2 seconds
ws.on('message', message => {
const parsed = JSON.parse(message);
if (parsed.type === 'APP_HEARTBEAT') {
ws.lastAppHeartbeat = Date.now(); // Update timestamp
// console.log('Received custom APP_HEARTBEAT from client');
}
// Handle other messages...
});
ws.on('close', () => {
console.log('Client disconnected');
clearInterval(checkInterval);
});
ws.on('error', error => {
console.error('WS error:', error);
clearInterval(checkInterval);
});
});
console.log('Server running on ws://localhost:8080');Check Your Understanding
Select all statements that accurately describe WebSocket heartbeats and keep-alives:
Lesson Summary
We've explored the critical role of heartbeats in maintaining robust WebSocket connections:
- Native Ping/Pong frames check TCP connection liveness, with clients responding automatically.
- Application-level heartbeats provide a more robust and customizable way to ensure the application itself is responsive, especially useful with proxies.
- Both methods prevent 'dead' connections from consuming resources and improve overall system resilience.
Mastering heartbeats is essential for building stable and scalable realtime applications.
用 AI 导师学习 WebSockets & Realtime Systems Programming — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 12
- 课程
- 47
常见问题解答
「心跳与连接保活」课时是免费的吗?
是的 — 「心跳与连接保活」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 WebSockets & Realtime Systems Programming 课程的其余内容,请升级到 CoddyKit PRO。 WebSockets & Realtime Systems Programming 课程共包含 4 节课。
「心跳与连接保活」这节课中我会学到什么?
学习使用 ping/pong 帧和应用层心跳来维持连接活跃状态,并检测失效的对端。 你通过在浏览器中直接运行的动手代码来练习 WebSockets & Realtime Systems Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 WebSockets & Realtime Systems Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 WebSockets & Realtime Systems Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「心跳与连接保活」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 WebSockets & Realtime Systems Programming 课中编写并运行代码吗?
能。每节 WebSockets & Realtime Systems Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。