【发布时间】:2015-09-30 15:29:40
【问题描述】:
我正在连接到一个网络服务,该服务只允许从同一来源同时连接到它的 MAX(可能是 1、5、10,具体取决于您的许可证)。我需要一个可以实时(非异步)对 Web 服务的请求进行排队的解决方案,确保一次只运行 MAX 请求。
我的当前设置正常工作:
$jobId = $this->queue->addJob($operation);
while ( !$this->queue->canRunJob($jobId) ) {
//error_log("Queue full, waiting");
usleep(500);
}
$this->queue->runJob($jobId);
...
$this->queue->completeJob($jobId);
这使用了一个自定义队列类,它使用一个 mysql 表来跟踪作业,并计算正在运行和挂起的作业的数量。
$this->queue->addJob 将新作业添加到数据库中,状态为“待定”
$this->queue->canRunJob($jobId) 检查有多少正在运行的作业。如果运行的作业少于 MAX 个,它将按 FIFO 顺序从列表中获取下一个待处理的作业。
PHP 脚本正在循环和休眠,直到作业可以运行。
一旦canRunJob 调用$this->queue->runJob($jobId),它将队列中的作业更新为“正在运行”并将请求发送到网络服务。
当 web 服务返回响应时,它调用 $this->queue->completeJob($jobId) 将队列中的作业更新为“已完成”。
这在 95% 的情况下都有效,但如果 Web 服务提供商陷入困境或完全瘫痪,它会慢慢导致我的服务器上的进程堆积,从而锁定 Web 和数据库连接。
寻找另一种在不循环/休眠的情况下处理这种情况的方法的建议
【问题讨论】:
-
而不是脚本循环和检查队列槽,为什么不让您的作业在完成时简单地调用“运行下一个作业”?这样就根本不需要循环脚本。也许有一个定期启动的安全脚本,以处理由于“运行下一个作业”位从未被调用而导致作业提前停止并且队列清空的情况。
-
我喜欢这个概念,但是这个工作怎么知道“等待”被调用呢?例如: 工作 1 - 创建一个新客户(进入队列并开始,因为它是唯一的工作) 工作 2 - 创建一个新客户,需要等待工作 1 完成。作业 1 可以完成并调用作业 2,但作业 2 需要知道其状态
-
这个工作不需要知道任何事情。它只是告诉您的调度代码作业结束,调度程序负责确定接下来要运行的内容。例如你的实际工作类似于
<?php do_stuff(); tell_scheduler_to_run_next_job(); ?>。
标签: php mysql web-services queue