Workerman通过事件驱动的非阻塞I/O模型高效维持长连接,结合客户端与服务器端双向心跳机制,定时发送心跳包并检测响应,防止NAT或防火墙导致的连接“假死”,同时通过定时清理未活跃连接、设置合理心跳间隔与超时时间、避免阻塞操作和内存泄漏,确保长连接的稳定性与可靠性。

Workerman维持长连接的核心在于其事件驱动的非阻塞I/O模型,它能高效地管理大量并发连接而不会为每个连接创建独立进程或线程。而心跳包机制,则是在这个基础上,通过客户端和服务器端定时发送特定数据包来主动检测连接的活性,防止因网络中间设备(如NAT、防火墙)超时断开或客户端异常关闭导致连接“假死”,从而确保长连接的真正可靠性。
要让Workerman保持长连接并有效处理心跳,我们需要在服务器端和客户端都做好相应的策略。
Workerman本身就擅长处理长连接,这得益于它的事件循环和非阻塞I/O。但光有这些还不够,网络环境复杂多变,NAT超时、防火墙策略、客户端突然断电等都可能导致TCP连接在应用层看起来还活着,实际上已经无法通信。这时候,心跳机制就显得尤为关键。
服务器端的核心实现:
立即进入“豆包AI人工智官网入口”;
立即学习“豆包AI人工智能在线问答入口”;
onConnect
lastMessageTime
onMessage
lastMessageTime
lastMessageTime
客户端的核心实现(以WebSocket为例):
{"type":"ping"}通过这种双向的心跳机制,无论是客户端还是服务器端,都能及时发现并处理失效连接,从而维护一个稳定、可靠的长连接环境。
在我看来,理解Workerman的长连接,首先得从它的底层基石——事件驱动与非阻塞I/O说起。它不是为每个连接都开一个线程或进程,那样资源消耗太大了。Workerman利用的是像
Epoll
这种模式天然就适合长连接,因为连接建立后,它就一直存在于Workerman的事件循环中,直到被显式关闭或者网络中断。它不需要频繁地建立、关闭TCP连接,大大减少了三次握手和四次挥手的开销。
但即便如此,长连接也并非没有陷阱,甚至可以说,很多性能问题和稳定性隐患都藏在这些地方:
onMessage
onConnect
onMessage
ulimit -n
这些陷阱,很多时候不是Workerman本身的问题,而是我们在使用它时对底层机制理解不够深入,或者没有充分考虑到复杂的网络环境和编程习惯造成的。
心跳包的实现,在我看来,核心在于“双向确认”和“超时处理”。它不仅仅是服务器发给客户端,或者客户端发给服务器,而是两者都需要有发送和接收心跳的能力,并且能够根据超时情况做出判断。
服务器端实现策略:
Workerman服务器端的心跳逻辑通常是这样的:
记录连接活动时间:
use Workerman\Worker;
use Workerman\Timer;
$worker = new Worker('websocket://0.0.0.0:2346');
// 设置每个连接的属性,记录最后一次活跃时间
$worker->onConnect = function($connection) {
$connection->lastMessageTime = time();
};
// 当收到任何消息时,更新活跃时间
$worker->onMessage = function($connection, $data) {
$connection->lastMessageTime = time();
// ... 处理业务逻辑 ...
// 如果是心跳请求,可以回复一个心跳响应
if ($data === '{"type":"ping"}') {
$connection->send('{"type":"pong"}');
}
};定时器检测与清理: 这是服务器端主动清理“假死”连接的关键。
// 在Worker启动后设置一个定时器
$worker->onWorkerStart = function($worker) {
// 每55秒检测一次所有连接
Timer::add(55, function() use ($worker) {
$now = time();
foreach ($worker->connections as $connection) {
// 如果连接超过60秒没有收到任何消息,就认为它已经断开
if ($now - $connection->lastMessageTime > 60) {
echo "Connection " . $connection->id . " timed out, closing.\n";
$connection->close();
}
}
});
};这里我把心跳检测的间隔设为55秒,超时时间设为60秒。这样,如果客户端的心跳周期是30秒,那么即使有一次心跳丢失,服务器也不会立即关闭连接,给了一定的容错空间。
客户端实现策略(以JavaScript WebSocket为例):
客户端的心跳逻辑,通常会涉及到定时发送、接收响应和断线重连。
let ws = null;
let pingTimer = null;
let pongTimer = null;
const heartbeatInterval = 30 * 1000; // 30秒发送一次心跳
const heartbeatTimeout = 60 * 1000; // 60秒内没收到消息就认为断线
function connectWebSocket() {
ws = new WebSocket("ws://localhost:2346");
ws.onopen = function() {
console.log("WebSocket connected.");
startHeartbeat(); // 连接成功后启动心跳
};
ws.onmessage = function(event) {
console.log("Received: " + event.data);
resetPongTimer(); // 收到任何消息都重置pong计时器
const msg = JSON.parse(event.data);
if (msg.type === "pong") {
// 这是服务器的心跳响应,不需要额外处理,resetPongTimer已经做了
}
// ... 处理其他业务消息 ...
};
ws.onclose = function() {
console.log("WebSocket disconnected. Reconnecting in 5 seconds...");
stopHeartbeat(); // 连接关闭,停止心跳
setTimeout(connectWebSocket, 5000); // 尝试重连
};
ws.onerror = function(error) {
console.error("WebSocket error: " + error);
ws.close(); // 发生错误也尝试关闭并重连
};
}
function startHeartbeat() {
// 启动ping定时器
pingTimer = setInterval(() => {
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: "ping" }));
console.log("Sent ping.");
// 每次发送ping后,启动或重置pong计时器,确保在指定时间内收到响应
resetPongTimer();
}
}, heartbeatInterval);
// 第一次连接成功后,也立即启动pong计时器
resetPongTimer();
}
function resetPongTimer() {
clearTimeout(pongTimer);
pongTimer = setTimeout(() => {
console.warn("No message received from server for too long. Closing connection.");
if (ws && ws.readyState === WebSocket.OPEN) {
ws.close(); // 超时未收到消息,主动关闭连接,触发onclose进行重连
}
}, heartbeatTimeout);
}
function stopHeartbeat() {
clearInterval(pingTimer);
clearTimeout(pongTimer);
pingTimer = null;
pongTimer = null;
}
// 首次连接
connectWebSocket();这里的客户端代码,核心是两个定时器:
pingTimer
pongTimer
pong
pongTimer
在实际生产环境中,仅仅实现心跳机制是不够的,我们还需要深入考虑其性能和稳定性。我个人觉得,这不仅仅是代码层面的优化,更多的是一种系统设计的哲学。
心跳间隔与超时时间的权衡:
pong
心跳数据包的大小与内容:
{"type":"ping"}{"type":"pong"}异常处理与重连策略:
内存优化:
onConnect
onMessage
安全性考量:
集群部署下的长连接管理:
在我看来,长连接和心跳机制的优化是一个持续的过程,它要求我们不仅了解Workerman的原理,更要对网络环境、操作系统限制以及客户端行为有深刻的洞察。没有一劳永逸的方案,只有不断地监控、调整和迭代。
以上就是Workerman怎么保持长连接?Workerman心跳包如何实现?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号