php 实现长轮询
长轮询的基本概念
长轮询(Long Polling)是一种服务器推送技术,客户端向服务器发送请求后,服务器保持连接开放直到有数据可返回或超时。相比传统轮询,长轮询减少了不必要的请求次数,提高了实时性。
PHP 实现长轮询的核心步骤
服务器端实现
创建一个PHP脚本(如long_polling.php)处理客户端请求。脚本需设置超时时间并阻塞执行,直到数据更新或超时。
<?php
// 设置脚本执行时间(避免PHP默认超时)
set_time_limit(0);
// 模拟数据检查(实际场景可能查询数据库或外部API)
$lastUpdate = isset($_GET['timestamp']) ? (int)$_GET['timestamp'] : 0;
$currentTime = time();
// 阻塞等待数据更新(示例最多等待10秒)
while ($currentTime - $lastUpdate < 10) {
// 检查数据是否更新(此处用随机数模拟)
if (rand(0, 100) > 95) { // 5%概率触发更新
$response = [
'status' => 'update',
'data' => 'New data at ' . date('H:i:s'),
'timestamp' => $currentTime
];
echo json_encode($response);
exit;
}
sleep(1); // 降低CPU占用
$currentTime = time();
}
// 超时返回空响应
echo json_encode(['status' => 'timeout']);
?>
客户端实现 使用JavaScript发起异步请求,并在收到响应后立即发起新请求。
function longPoll() {
fetch('long_polling.php?timestamp=' + lastTimestamp)
.then(response => response.json())
.then(data => {
if (data.status === 'update') {
console.log('Received:', data.data);
lastTimestamp = data.timestamp;
}
longPoll(); // 递归调用保持长轮询
})
.catch(error => {
console.error('Error:', error);
setTimeout(longPoll, 5000); // 错误时延迟重试
});
}
let lastTimestamp = 0;
longPoll(); // 启动长轮询
优化与注意事项
性能优化
- 使用共享内存(如APCu)或数据库存储状态,避免多进程重复计算。
- 对于高并发场景,考虑使用Redis的发布/订阅功能替代纯PHP轮询。
错误处理
- 客户端需处理网络中断和服务器错误,实现自动重连机制。
- 服务器端记录异常日志,避免无限阻塞消耗资源。
超时控制
- 服务器端
set_time_limit(0)需配合max_execution_time的PHP配置调整。 - 客户端根据业务需求设置合理的轮询间隔和超时时间。
实际应用场景示例
- 即时聊天系统:消息到达时立即推送给客户端。
- 实时通知:如订单状态变更、系统告警等。
- 股票价格更新:低频但需实时性的数据推送。
通过以上方法,PHP可实现高效的长轮询机制,平衡实时性与服务器资源消耗。实际部署时需根据具体业务需求调整参数和架构。







