美文网首页
supervisor队列异常bug

supervisor队列异常bug

作者: 鸿雁长飞光不度 | 来源:发表于2018-12-03 14:57 被阅读0次

服务器的队列使用了top-queue,用来异步的处理耗时任务,包括支付回调,批量上传课程,队列采用了listen模式,在listen模式下队列会启动一个主进程负责定期扫任务数据表发现需要执行的任务,然后创建worker进程来处理。处理完毕后会删除表里面的任务,然后子进程会退出。但是如果在处理任务过程中,代码触发了异常主进程会退出,导致以后不能再处理新的任务。解决办法有两种,可以手动的用try catch的方法手动捕获异常,记录下来,但是不抛出。此外还可以用supervisor把listen模式的主进程设置为常驻进程,它会在监听到主进程退出的时候强制重启,二者结合来保证队列正常执行。

实际遇到了一个问题,经常被反馈用户付款后课程依旧不能观看,说明付款任务没有被执行,查看数据库任务表发现果然没有执行,登录服务器通过ps命令查看think相关进程信息。

top-queue.png

会发现进程相关信息都在,但是任务已经不再执行。所以我只能在终端输入

 php think queue:listen --queue topcms &

这样任务才会继续。但是不能每次都这样,每次发现问题的时候必须手动重启是非常伤的。所以要查下为什么进程在但是任务不执行的问题,鉴于supervisor是一个非常成熟的常驻进程管理器,出问题的情况不大,问题应该在我们。

在输入完

php think queue:listen --queue topcms &

生成新的后台进程,等任务表信息跑完后,我准备删除所有和队列相关的进程,看看supervisor是不是保证重新生成,否则就是有问题的。

ps -ef | grep think | grep -v grep | cut -c 9-15 | xargs kill -9 #删除所有的队列进程

然后我再次通过ps查看进程,发现队列相关进程依旧存在,说明重新生成了,但是任务表的任务确实不被执行,此时我看到supervisor配置的地方有日志路径,也许信息在里面。

日志路径.png

打开日志文件包含了大量文件权限访问错误信息

supervisor日志.png

说明所有的进程在重启过程中遇到了文件访问权限问题,结合实际情况进入相关文件目录

错误提示文件相关目录.png

可以发现有些文件的身份是apache,有些是root。这里仅仅看cli相关的文件,cli表示是命令行下相关操作生成的文件,这里原因就很明白了,supervisor生成的进程身份是apache,如果文件已经存在,而且是root,是访问会出错的。而且这些日志是以天为单位的。然后我删除了今天的相关文件,重新删除所有队列进程,发现supervisor重新生成后已经可以正常的处理任务了。

现在就可以解释大部分现象了。

1.为什么我需要手动执行listen进程生成命令,才能继续执行?

队列相关进程有两种,一种是supervisor管理的身份为apache的,另一种是命令输入的,身份为root,命令行输入的进程为后端进程。静默的执行和apache相同操作。

因为日志文件以天为单位,如果某一天的日志,先由apache相关进程触发生成,在代码抛出异常导致进程中断的时候,supervisor可以生成新的进程,处理任务,此时root身份的队列进程存在可有可无。如果当天的日志文件是有root相关进程生成的话,说明root身份进程一定存在,并且正常执行了任务,此时supervisor管理的那些依然会有权限访问问题,导致身份为apache队列进程不断的退出重启,死循环。但是因为此时root身份队列进程在,能够处理任务,在没有触发异常导致root身份进程退出的情况下,一切表现正常,但是一旦触发异常,root进程退出后,就不会被重启,此时supervisor的进程也在死循环里面。
对外表现是任务表任务不被执行,我如果在服务器上面重新输入命令,相当于重新拉起了root进程,它有访问日志权限,可以继续执行。文件的身份取决于当天第一个执行队列任务的权限的身份。

再次推测下,假设supervisor进程因为日志日志权限没生成,当天表现又正常的话,说明是root进程在做任务,因为supervisor进程没有生成,在第二天生成相关新的日志文件的进程一定是root,文件权限也是root。supervisor依旧不能生成,所以有理由相信,在我第一次因为任务表不执行的情况下,手动输入命令开始,supervisor就再也没有起过作用,一直在不断的死循环重启。

2.root身份的队列进程是怎么来的?

一定是手动输入命令导致的,因为出问题我就输入命令,实际上执行任务的一定是root。问题在第一个root命令怎么出现的,是因为supervisor不起作用我才手动输入的?还是因为我手动输入后,导致上面描述的supervisor失效,每次触发异常都要手动重启的局面呢?这个要看过去日志cli相关文件的所属者,然后才能看出来,但是过去的日志文件已经被清理了,但是目前几天的身份都是root。只记得好久以前服务器重启的时候,根据反馈发现任务表不执行,当时可能supervisor这个管理者进程当时并没有被加入到linux系统重启后自动生成的选项里导致的,后来加入到系统启动项了。当时我为了尽快的解决问题,手动输入了一次命令,才引发后面的事情。

3.怎么杜绝类似事情再次发生?

可以把supervisor管理的进程身份改成root,但是可能有潜在的安全问题,另一个就是把所有的root的进程删掉,然后确保日志文件不存在或者所属这位apache,保证supervisor重启进程正常且任务执行进程都为apache,这样出了问题依赖supervisor自身重启来实现。这样只要不在手动执行命令的情况下是正常的,手动输入命令的话,就要看apache进程能否抢占在root进程前生成日志文件,一旦抢占不过结果和现在一样。所以恢复后就要禁止输入命令启动任务了。目前就是采用了这样的办法。为了更安全,可以考虑把日志文件的权限放开些。让其他的身份的进程也有可读写权限。这部分需要改框架代码,目前没有改。

file.png

相关文章

网友评论

      本文标题:supervisor队列异常bug

      本文链接:https://www.haomeiwen.com/subject/gbmjcqtx.html