0Pricing
WebSockets & Realtime Systems Programming · レッスン

ハートビートとキープアライブ

ping/pongフレームとアプリケーションレベルのハートビートを使って接続の有効性を維持し、応答しないピアを検出する方法を学びます。

「ハートビートとキープアライブ」はCoddyKit上の無料WebSockets & Realtime Systems Programmingレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応の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 Ping frame to its peer.
  • Upon receiving a Ping, the peer is expected to automatically respond with a Pong frame.
  • 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 Pong frame without any explicit code from you.
  • This makes native pings very efficient for basic connection liveness checks.
  • If a Ping is sent and no Pong is 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.

よくある質問

「ハートビートとキープアライブ」レッスンは無料ですか?

はい。「ハートビートとキープアライブ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、WebSockets & Realtime Systems Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 WebSockets & Realtime Systems Programmingコースには全4レッスンが含まれています。

「ハートビートとキープアライブ」で何を学びますか?

ping/pongフレームとアプリケーションレベルのハートビートを使って接続の有効性を維持し、応答しないピアを検出する方法を学びます。 ブラウザで直接実行するハンズオンコードでWebSockets & Realtime Systems Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

WebSockets & Realtime Systems Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのWebSockets & Realtime Systems Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「ハートビートとキープアライブ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このWebSockets & Realtime Systems Programmingレッスンでコードを書いて実行できますか?

はい。すべてのWebSockets & Realtime Systems Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 切断と再接続への対応
  2. 堅牢なエラー伝播と復旧
  3. ハートビートとキープアライブ
  4. メッセージ確認と配信保証
← WebSockets & Realtime Systems Programmingに戻る