我正在尝试创建的是一个读取/解析来自十几个外部网站的数据的系统。
举个例子,假设我想创建一个解析特定用户个人资料页面上的Twitter帖子的系统。我想为十几个用户做这件事。
此外,我希望为每个用户运行单独的作业。因此,如果有12个用户,我需要运行12个作业。
当作业完成时(即当它解析了页面上所有用户的帖子时),我需要重新开始作业(为了解析任何新帖子)。
所以最后,如果有12个用户,我应该有12个不断运行的工作,解析这12个用户中的任何一个发布的新帖子。
据我所知,有两种方法可以做到这一点。第一个是使用cron jobs,第二个是使用Laravel的queuing system。
解决此问题的最佳方法是什么? Cron工作或队列?我该如何正确实施?
使用cron作业,我能想到的两个问题是crons基于时间运行,而不是基于作业完成,这意味着如果作业完成,则必须等到cron作业再次被调用(对于例如,每5分钟一次)。另一个问题是重叠。如果工作没有及时完成但是cron再次调用该工作怎么办?
这是我当前队列作业实现的简化版本,但是,我注意到我的CPU使用率跃升到75-90%之间:
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Models\Page;
class PageParser extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
protected $page;
public function __construct(Page $page)
{
$this->page = $page;
}
public function handle()
{
// Parsing done here, removed for simplicity
$this->delete();
dispatch(new PageParser($this->page));
}
}
答案 0 :(得分:0)
我没试过这个,但我认为你可以创建一个递归的工作。
这个递归作业将执行它所需的所有代码,然后,在执行结束时,它将创建一个新作业并将其推送到队列中 - 一旦队列准备就绪就会开始运行
如果作业在任何时候失败,您将不会创建新作业,因此您不会同时运行任何相同用户的作业。失败的工作将简单地重试 - 如果成功,将创造一份新工作。
答案 1 :(得分:0)
您可以使用组合。创建一个像&#39; RetrieveDataCommand&#39;管他呢。此命令应该将作业推送到每个用户的队列,该队列将检索该用户的数据(如果需要,可能还有一个单独的作业用于实际处理?)。这项工作应该考虑来自&#39;来自&#39;参数是一个时间戳,如果以前的&#39;命令已运行。当它运行时,它会检索$ from到now()的所有用户的所有数据。
然后,您可以让cron作业每10秒运行一次命令或其他任何操作。 $ cn可以通过在cron运行命令后立即存储(在缓存/ DB /半持久的东西中)当前时间的时间戳来计算,这样下一个命令可以在运行时查看它,然后覆盖它以进行下一次运行。或者只是现在()减去cron间隔,尽管灵活性较差。
然后,您可以从作业中删除自删除和发送内容