Laravel Queues 队列应用实战

队列,顾名思义,排着队等着做事情。在生活场景中,凡是排队的人,都是带有目的性的、要完成某件事情,才去排队的,要不没有谁会闲到排队玩儿。而在软件应用层面,队列是什么,队列有什么优点,我们什么时候需要用队列,以及在实际业务场景下,如何基于队列做具体功能实现,在这篇文章中,我将用 PHP 的 Laravel 框架,逐一进行讲解和实现。

简单的后台任务 vs 队列

在纯粹的PHP环境中,我们可以使用 exec 函数来调用一个外部命令,启动一个外部进程,执行相关任务,等待其执行结束后,当前PHP脚本继续往后运行,直到其生命周期的结束。这个 exec 执行的整个过程是同步的,如若要异步的、让其在后台默默的执行,而不让当前PHP脚本进程陷入长时间等待的境地,也很好解决,只需要将 exec 执行的输出结果,进行重定向即可,关于这一点,在PHP的官方文档中明确说明了:

Laravel Queues 队列应用实战

具体实现方法,可以参考这篇博文:后台程序在处理繁重的任务时,调用外部程序异步执行的简单实现。

虽然,我们可以用上面的方法,简单几行代码实现,就可以达到目的,但是,面对稍微复杂一点点的场景,前面的方法就会弊端大显。

比如,我在调用百度AI内容审核API的时候,经常会发现返回 download image error 图片下载失败的错误信息,这就导致了虽然我们异步的执行了内容审核的任务,但不幸的是,这一次任务执行的结果失败了。我希望在失败后,还能够再一次的执行,于是我就又用 crontab 做了个定时任务,每5分钟检查所有待审的文章,交给百度AI去做内容审核,以弥补第一次审核失败时所带来的问题。如此,就能够实现这样一个较为良好的用户体验:当用户发布了文章后,系统第一次会以异步的方式,调用百度AI进行内容审核,若审核通过,则前端用户会在10秒内,看到自己发布的文章审核通过、正常发布出去了;若百度审核出现了错误信息,则交给系统的定时任务处理,这样前端用户也能够在最多5分钟后,看到自己的文章发布成功。

这是一个理想的方案,一切都那么OK,然而不幸的是,我发现百度AI内容审核接口失败的情况有些多,若文章的审核一直失败,则系统定时任务会不停的再次进行审核,结果,把我的百度AI内容审核接口的2000条图片审核的免费额度,全部耗光了!!!

那可不可以每篇文章最多只能调用3次百度AI审核接口,超过则人工审核呢?当然可以,但是这就需要再升级数据表结构,记录当前文章的审核次数,再在业务代码中,写入相应的逻辑以达到此目的。这就有些紧耦合了,你看看为了实现上述的效果,我用了 exec 异步执行任务,再用 crontab 设置了后台定时执行,最后还需要改动表结构,添加一个与业务本身毫不相干的字段,再在业务代码中加入审核次数的逻辑,才能最终完成整个过程。是不是过于烦琐和笨拙?

而以上种种,我们可以用 队列 来搞定,Laravel 框架的 Queue 队列,可以实现任务的 异步执行、失败重试、任务最大执行次数限制 等特性,很方便的实现我想要的效果。

并且之所以叫做队列,是由于我们可以把很多要执行的任务塞进队列,像排队一样按顺序依次执行,并且我们也可以让队列做限流,限制队列中任务处理的频率,以降低服务器负载的压力,像这种高级用法,并不在本文讨论之内,请自行参见官方文档。

我遇到的实际业务问题:CDN图片服务器 和 百度AI图片审核

其实,上面出现的百度AI审核接口,返回 download image error 过多的问题,倒跟百度关系不大,而是我们CDN图片源服务器的问题。由于历史原因,我们的CDN图片源服务器是Windows系统,用IIS部署的,实在是不知道什么原因,最近一年来经常处于抽风状态,感觉就像是带宽不够而被限流了。具体表现为:CDN从我们的源服务器拉取新图片时,响应时间很长,短则十秒或几十秒,长则一两分钟,甚至更长时间。这对于网页浏览来说,问题倒不是很大,因为虽然用户第一次查看新图片时,图片下载时间长点,但只要CDN缓存下了该图片,那么后续的图片显示就会秒开。但对于百度AI图片审核来说,这就是致命的:

用户发布包含图片的内容 -> 百度AI图片审核 -> 从CDN获取图片 -> 我可是新图片哦,还要从源服务器拉取,对不起,可能要等1分钟哦 -> 百度AI服务器:“垃圾,我等不了你,挂了吧” -> 响应 download image error,看到了吧,这就是症结所在。

所以,虽然没有能力从根本上解决图片源服务器的问题,但是用Laravel队列的方式,解决百度AI图片审核的问题,还是可以的。

Laravel 的队列实现

在开始代码实现之前,我们还是应该搞清楚两个概念:1、队列 2、任务。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspdzp.html