我的应用程序有一个包含多个worker的队列。根据队列中的作业数量缩放工作人员。工作人员正在处理的作业的一个主要目的是对外部服务进行API调用以检索一些数据。外部服务使用漏桶算法(https://en.wikipedia.org/wiki/Leaky_bucket)以2个呼叫/秒的速率实现api速率限制。我的api电话不是针对单一服务,而是针对该服务的帐户。因此,速率限制仅适用于我对服务帐户进行多次api调用的情况。不同帐户之间不共享费率限制。进行api呼叫的作业数量为数千(仅一个帐户),因此存储桶将始终满,我将开始限速。
这样的问题是,如果我的作业在我点击它之前没有观察到速率限制,我可能会尝试延迟它们并在发生这种情况时将它们放回队列中,但是因为我有多个工作人员和数千个工作我可能会在无限的速率限制循环中结束。
我已经考虑过使用memcache或redis之类的东西来存储可以在工作人员之间共享的某种信息,这样在我尝试在工作中进行api调用之前我会停止,延迟工作并放置它回到队列中,这样就不会提高速率限制。这种方法的问题是每次我都会这样做,我会增加工作的尝试次数。我有每个工作的最大尝试次数。我也意识到尝试的次数不能以任何方式改变Laravel工作者,我对此很好,我相信这使得工人更加稳定和可预测。重置该尝试次数的唯一选择是删除该作业并将其重新分配为新作业(但这感觉非常混乱)。
如果有人遇到过这样的问题,您是否愿意分享在这种情况下队列实现的样子?工人是否应该在他们之间分享状态(这感觉不对)?
注意:我不认为睡觉工作人员是解决速率限制的好方法,因为我可能会对服务的不同帐户进行api调用(基于队列中的下一个作业) )因此,如果工作人员为一个帐户睡觉,而另一个帐户可以为另一个帐户服务,则会感到失去时间。
由于
答案 0 :(得分:2)
听起来您正在使用Shopify API?
我设法在Laravel 5.5中使用它来实现这一点。来自文档:
Redis::throttle('key')->allow(2)->every(1)->then(function () {
// Job logic...
}, function () {
// Could not obtain lock...
return $this->release(10);
});