限制队列任务的并发数量


业务场景

先说下业务场景:商业公司通常会允许客户按需生成报表,但每个用户同时只允许生成 5 份报表。

对于生成报表这种耗时的磁盘 IO 操作,我们可以将其推送到消息队列异步处理,避免用户长时间等待,为此,我们编写这个任务类的 handle 方法如下:

在这里,我们先生成报表,再更新对应的数据库状态。为了加快队列任务的消费速度,可以开启多个队列处理器进程,不过,由于一个用户同时只能生成 5 份报表,就需要限制队列处理器进程并发执行的数量。

并发限制

Laravel 提供了很多队列任务频率限制器,这里我们使用基于漏斗算法的并发频率限制器。要限制针对每个用户最多同时执行 5 个报表生成队列任务,可以这么做:

如果没有达到并发上限,就可以执行 then 回调中的报表生成代码,否则,就会延迟 10s 后再执行该任务。通过这种方式,就可以实现队列处理器进程并发执行的队列任务数量。

等待几秒

默认情况下,并发频率限制器在放弃并释放任务前会等待 3 秒,你可以通过 block 方法来控制这个等待时间:

设置超时时间

默认情况下,并发频率限制器会强制每 60s 后执行一个任务(用于控制并发槽位的锁失效,可以将其看作是队列任务默认超时时间),如果单个报表生成任务执行时间超过 60s,则会释放这个槽位然后执行下一个,这就会出现 6 份报告同时生成的情况,这是我们不想看到的。

要解决这个问题,我们可以通过 releaseAfter 方法将超时时间设置为 5 分钟:

管理尝试次数

在上述代码实现中,由于队列任务可能会多次释放回队列,你可以通过设置 tries 属性限制同一个任务的最大尝试次数:

当然,如果 ReportGenerator 抛出异常,我们也不想要继续尝试,因此可以设置 maxExceptions 值为 2:

现在就变成了同一个队列任务正常情况下最多尝试 10 次,如果出现异常,最多只尝试 2 次就终止。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 处理有访问频率限制的 API 请求

>> 下一篇: 限制队列任务的执行频率