PHP实现的3分钟全局同步倒计时无用户访问无法运行问题咨询
解决方案
一、优先选择Cron定时任务方案
相比常驻后台脚本,Cron是系统原生服务,无需处理进程保活、内存泄漏问题,运维成本更低,实现逻辑如下:
1. 抽离核心业务逻辑
将原来response.php中剩余30秒触发的计算、插入数据逻辑单独剥离为独立脚本task.php,仅处理业务逻辑,不响应前端请求:
<?php // task.php 核心业务脚本,由Cron触发 $lock = fopen(__DIR__.'/task.lock', 'w'); // 加独占锁,避免并发执行导致重复插入数据 if (flock($lock, LOCK_EX | LOCK_NB)) { $current_min = (int)date('i'); $current_sec = (int)date('s'); // 校验是否为每3分钟区间的剩余30秒时刻(即2分30秒) if (($current_min % 3 == 2) && $current_sec >=30 && $current_sec <35) { // 这里放原来的计算、插入数据表的逻辑 // 业务代码... } flock($lock, LOCK_UN); } fclose($lock); ?>
2. 配置Cron定时任务
添加每分钟执行一次的Cron规则,适配不同服务器的PHP路径:
* * * * * /usr/bin/php /你的网站绝对路径/task.php >> /你的日志路径/task.log 2>&1
3. 前端倒计时同步优化
原来每秒发AJAX请求的逻辑性能差、并发风险高,直接由服务端输出当前轮次的结束时间戳,前端本地计算倒计时即可,所有用户时间天然一致:
优化后的index.php示例:
<?php $current_min = (int)date('i'); $next_slot_min = ceil($current_min/3)*3; if ($next_slot_min >=60) { $end_time = strtotime(date('Y-m-d H:i:00', strtotime('+1 hour'))); } else { $end_time = strtotime(date('Y-m-d H:'.$next_slot_min.':00')); } ?> <div id='countdown'></div> <button id="operate_btn">操作按钮</button> <script> const endTimestamp = <?php echo $end_time; ?> * 1000; const btn = document.getElementById('operate_btn'); const countDownEle = document.getElementById('countdown'); const updateCountdown = () => { const now = Date.now(); const diff = Math.max(0, endTimestamp - now); const minutes = String(Math.floor(diff / 1000 / 60)).padStart(2, '0'); const seconds = String(Math.floor(diff / 1000 % 60)).padStart(2, '0'); countDownEle.innerText = `${minutes}:${seconds}`; // 剩余30秒锁按钮 if (diff <= 30*1000) { btn.disabled = true; } // 倒计时结束刷新页面 if (diff === 0) { window.location.reload(); } } updateCountdown(); setInterval(updateCountdown, 1000); </script>
原来的response.php可以直接废弃,前端不再需要向后端请求倒计时数据。
二、现有代码安全漏洞修复
- 参数未校验漏洞:原
response.php直接使用$_POST['next_slot']无任何校验,用户可传入任意值导致时间计算错误,若后续关联数据库操作可能引发SQL注入,需添加参数校验:$end_minute = in_array((int)$_POST['next_slot'], [0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57]) ? (int)$_POST['next_slot'] : 0; - 并发重复执行漏洞:多用户同时访问时,剩余30秒会有多个请求同时触发业务逻辑,导致重复插入多条数据,需添加文件锁/Redis锁保证单进程执行。
- CSRF攻击风险:原
response.php无请求来源校验,第三方站点可构造请求恶意触发业务逻辑,需添加请求来源校验或者CSRF Token校验。 - 资源浪费问题:每秒发起一次AJAX请求,高并发下会给服务器造成极大压力,改为前端本地计算倒计时可节省99%的接口请求量。
三、常驻后台脚本方案(可选)
若不使用Cron,可编写常驻脚本配合Supervisor保活,实现逻辑为:死循环每1秒判断当前时间是否到达业务执行时机,到达则执行业务逻辑。该方案需额外维护Supervisor配置,处理进程异常退出问题,运维成本更高,非特殊需求不推荐使用。
内容的提问来源于stack exchange,提问作者user3910197
相关产品推荐
相关产品推荐

