执行3分钟后触发503错误,首次数据同步流程受阻求助
解决方案与变通方法
1. 用CodeIgniter 4队列实现异步分批同步(核心方案)
浏览器和Hostinger共享主机都不支持长时间运行的前端触发请求,必须把同步任务拆成后台异步执行:
步骤1:配置数据库队列
在app/Config/Queue.php里设置驱动为数据库:public $default = 'database'; public $database = [ 'driver' => 'CodeIgniter\Queue\Database\DatabaseHandler', 'table' => 'jobs', 'queue' => 'default', 'timeout' => 60, ];运行迁移创建任务表:
php spark migrate --all步骤2:创建同步任务类
在app/Tasks下新建SyncApiTask.php:<?php namespace App\Tasks; use CodeIgniter\Queue\BaseTask; use CodeIgniter\Queue\TaskInterface; class SyncApiTask extends BaseTask implements TaskInterface { protected $maxAttempts = 3; public function run(array $data) { $start = $data['start']; $end = $data['end']; // 处理当前批次的API请求 for ($i = $start; $i <= $end; $i++) { // 这里写你的API请求逻辑 // ... // 间隔1.01秒,避免触发每分钟60次限制 usleep(1010000); } // 最后一个批次完成后获取并保存token if ($end >= 1000) { $token = $this->getAccessRefreshToken(); // 将token存入数据库或配置文件 // ... } } private function getAccessRefreshToken() { // 这里写获取token的逻辑 // ... } }步骤3:前端触发任务入队
控制器里写一个接口,把1000次请求拆成17个批次(每批60条),依次加入队列,每个任务延迟1分钟执行:public function startSync() { $total = 1000; $perBatch = 60; $batches = ceil($total / $perBatch); for ($i = 0; $i < $batches; $i++) { $start = $i * $perBatch + 1; $end = min(($i + 1) * $perBatch, $total); $delay = $i * 60; service('queue')->later($delay, 'App\Tasks\SyncApiTask', ['start' => $start, 'end' => $end]); } return $this->response->setJSON(['status' => 'success', 'msg' => '同步已启动,预计17分钟左右完成']); }步骤4:配置Cron Job触发队列
在Hostinger控制面板的Cron Jobs中添加每分钟执行的命令:php /home/你的用户名/public_html/spark queue:work --queue=default --timeout=60这样每分钟会处理一个批次的请求,刚好匹配API的频率限制。
2. 分阶段同步+前端轮询(轻量替代方案)
如果不想用队列,可以把同步拆成多个短请求,前端自动轮询执行:
控制器接口
public function syncBatch($batch = 1) { $perBatch = 60; $start = ($batch - 1) * $perBatch + 1; $end = min($batch * $perBatch, 1000); // 处理当前批次请求 for ($i = $start; $i <= $end; $i++) { // API请求逻辑 // ... usleep(1010000); } $totalBatches = ceil(1000 / $perBatch); $isLast = $batch >= $totalBatches; if ($isLast) { // 最后一批完成后获取token $token = $this->getAccessRefreshToken(); return $this->response->setJSON(['status' => 'done', 'msg' => '同步完成', 'token' => $token]); } return $this->response->setJSON(['status' => 'progress', 'current' => $batch, 'total' => $totalBatches]); }前端JS代码
let currentBatch = 1; const totalBatches = Math.ceil(1000 / 60); function runBatch() { fetch(`/sync/batch/${currentBatch}`) .then(res => res.json()) .then(data => { if (data.status === 'progress') { console.log(`已完成第${data.current}/${data.total}批`); currentBatch++; // 间隔1分钟发起下一批请求 setTimeout(runBatch, 60000); } else { alert(data.msg); } }) .catch(err => console.error(err)); } // 绑定同步按钮点击事件 document.getElementById('syncBtn').addEventListener('click', runBatch);
3. 关键注意事项
- Hostinger共享主机的HTTP连接超时默认在180秒左右,任何超过3分钟的前端直接请求都会被断开,必须拆成短任务。
- 不要过度依赖
max_execution_time修改,Hostinger服务器层面有额外限制,异步/分阶段是唯一可靠的解决方式。 - API请求间隔必须控制在1秒以上,建议用
usleep(1010000)保证每分钟请求不超过59次,避免触发503限制。
内容的提问来源于stack exchange,提问作者oelimoe
相关产品推荐
相关产品推荐

