1、查看 log 表,其 message 字段内容如下:
yii/web/NotFoundHttpException: The task ID of the channel's article: 2209, does not exist in /mcloud/www/channel-pub-api/common/components/queue/PubArticleEventHandler.php:93 Stack trace: #0 [internal function]: common/components/queue/PubArticleEventHandler::afterError(Object(yii/queue/ErrorEvent)) #1 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/base/Component.php(627): call_user_func(Array, Object(yii/queue/ErrorEvent)) #2 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/Queue.php(246): yii/base/Component->trigger('afterError', Object(yii/queue/ErrorEvent)) #3 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/cli/Command.php(198): yii/queue/Queue->handleError('159', Object(wx/jobs/PubArticleJob), '300', '1085', Object(Symfony/Component/Process/Exception/ProcessFailedException)) #4 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/cli/Command.php(125): yii/queue/cli/Command->handleMessage('159', 'O:21:"wx//jobs//P...', '300', '1085') #5 [internal function]: yii/queue/cli/Command->yii/queue/cli/{closure}('159', 'O:21:"wx//jobs//P...', '300', '1085') #6 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/cli/Queue.php(144): call_user_func(Object(Closure), '159', 'O:21:"wx//jobs//P...', '300', '1085') #7 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/drivers/redis/Queue.php(61): yii/queue/cli/Queue->handleMessage('159', 'O:21:"wx//jobs//P...', '300', '1085') #8 [internal function]: yii/queue/redis/Queue->yii/queue/redis/{closure}(Object(Closure)) #9 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/cli/Queue.php(117): call_user_func(Object(Closure), Object(Closure)) #10 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/drivers/redis/Queue.php(68): yii/queue/cli/Queue->runWorker(Object(Closure)) #11 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2-queue/src/drivers/redis/Command.php(76): yii/queue/redis/Queue->run(true, 3) #12 [internal function]: yii/queue/redis/Command->actionListen(3) #13 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array) #14 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/base/Controller.php(157): yii/base/InlineAction->runWithParams(Array) #15 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/console/Controller.php(148): yii/base/Controller->runAction('listen', Array) #16 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/base/Module.php(528): yii/console/Controller->runAction('listen', Array) #17 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/console/Application.php(180): yii/base/Module->runAction('pub-article-que...', Array) #18 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/console/Application.php(147): yii/console/Application->runAction('pub-article-que...', Array) #19 /mcloud/www/channel-pub-api/vendor/yiisoft/yii2/base/Application.php(386): yii/console/Application->handleRequest(Object(yii/console/Request)) #20 /mcloud/www/channel-pub-api/yii(23): yii/base/Application->run() #21 {main}
2、分析发现,发布文章队列事件处理器,发布文章队列的作业执行失败后,common/components/queue/PubArticleEventHandler::afterError(ExecEvent $event),在此方法中抛出异常,一旦抛出异常,进而便会导致此发布文章队列的状态一直处于:reserved,因此,应该尽可能避免在此方法中抛出异常
<?php /** * Created by PhpStorm. * User: Qiang Wang * Date: 2018/10/23 * Time: 19:36 */ namespace common/components/queue; use Yii; use common/services/TaskService; use common/services/ChannelAppTaskService; use common/services/ArticleTypeService; use yii/base/Component; use yii/queue/ExecEvent; use yii/web/NotFoundHttpException; use yii/web/UnprocessableEntityHttpException; /** * Class PubArticleEventHandler * @package common/components/queue * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class PubArticleEventHandler extends Component { /** * @param ExecEvent $event * @throws NotFoundHttpException 如果未找到数据模型,将抛出 404 HTTP 异常 * @throws UnprocessableEntityHttpException 如果找到数据模型,状态未启用,将抛出 422 HTTP 异常 */ public static function afterExec(ExecEvent $event) { $channelAppTaskId = $event->job->channelAppTaskId; // 基于ID查找状态为未禁用的单个数据模型(渠道的应用的任务) $channelAppTaskDisabledNoItem = ChannelAppTaskService::findModelDisabledNoById($channelAppTaskId); // 基于ID查找状态为启用的单个数据模型(任务) $taskEnabledItem = TaskService::findModelEnabledById($channelAppTaskDisabledNoItem->task_id); $serviceClass = 'common/services//' . str_replace(' ', '', ucwords(str_replace('_', ' ', $taskEnabledItem->channel_type_code))) . 'ArticleService'; // 例:common/services/QqCwArticleService $articleModel = 'common/logics//' . str_replace(' ', '', ucwords(str_replace('_', ' ', $taskEnabledItem->channel_code))) . 'Article'; // 例:common/logics/QqArticle // 基于任务ID查找单个数据模型(渠道的文章) $articleModelItem = $articleModel::find()->where(['task_id' => $taskEnabledItem->id])->isDeletedNo()->one(); // 如果未找到数据模型,将抛出 404 HTTP 异常 if (!isset($articleModelItem)) { throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202091'), ['task_id' => $taskEnabledItem->id])), 202091); } /* 判断状态,如果未启用,将抛出 422 HTTP 异常 */ if ($articleModelItem->status !== $articleModelItem::STATUS_ENABLED) { throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202092'), ['task_id' => $taskEnabledItem->id])), 202092); } // 基于ID查找状态为启用的单个数据模型(文章类型) $articleTypeEnabledItem = ArticleTypeService::findModelEnabledById($articleModelItem->article_type_id); $serviceAction = 'pubArticle' . str_replace(' ', '', ucwords(str_replace('_', ' ', $articleTypeEnabledItem->code))) . 'ExecHandler'; // 例:pubArticleVideoExecHandler $serviceClass::$serviceAction($channelAppTaskId); } /** * @param ExecEvent $event * @throws NotFoundHttpException 如果未找到数据模型,将抛出 404 HTTP 异常 * @throws UnprocessableEntityHttpException 如果找到数据模型,状态未启用,将抛出 422 HTTP 异常 */ public static function afterError(ExecEvent $event) { $channelAppTaskId = $event->job->channelAppTaskId; // 基于ID查找状态为未禁用的单个数据模型(渠道的应用的任务) $channelAppTaskDisabledNoItem = ChannelAppTaskService::findModelDisabledNoById($channelAppTaskId); // 基于ID查找状态为启用的单个数据模型(任务) $taskEnabledItem = TaskService::findModelEnabledById($channelAppTaskDisabledNoItem->task_id); $serviceClass = 'common/services//' . str_replace(' ', '', ucwords(str_replace('_', ' ', $taskEnabledItem->channel_type_code))) . 'ArticleService'; // 例:common/services/QqCwArticleService $articleModel = 'common/logics//' . str_replace(' ', '', ucwords(str_replace('_', ' ', $taskEnabledItem->channel_code))) . 'Article'; // 例:common/logics/QqArticle // 基于任务ID查找单个数据模型(渠道的文章) $articleModelItem = $articleModel::find()->where(['task_id' => $taskEnabledItem->id])->isDeletedNo()->one(); // 如果未找到数据模型,将抛出 404 HTTP 异常 if (!isset($articleModelItem)) { throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202091'), ['task_id' => $taskEnabledItem->id])), 202091); } /* 判断状态,如果未启用,将抛出 422 HTTP 异常 */ if ($articleModelItem->status !== $articleModelItem::STATUS_ENABLED) { throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202092'), ['task_id' => $taskEnabledItem->id])), 202092); } // 基于ID查找状态为启用的单个数据模型(文章类型) $articleTypeEnabledItem = ArticleTypeService::findModelEnabledById($articleModelItem->article_type_id); $serviceAction = 'pubArticle' . str_replace(' ', '', ucwords(str_replace('_', ' ', $articleTypeEnabledItem->code))) . 'ErrorHandler'; // 例:pubArticleVideoErrorHandler $serviceClass::$serviceAction($channelAppTaskId, $event->error); } }
3、Yii2 队列扩展,Redis 驱动中,info 命令打印关于队列状态的信息时,reserved 状态的队列数量为 33,如图1
[root@cc121bb54862 /]# cd /mcloud/www/channel-pub-api/ [root@cc121bb54862 channel-pub-api]# ./yii copy-asset-queue/info --color=0 Jobs - waiting: 0 - delayed: 0 - reserved: 0 - done: 146 [root@cc121bb54862 channel-pub-api]# ./yii upload-asset-queue/info --color=0 Jobs - waiting: 0 - delayed: 0 - reserved: 0 - done: 0 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 20 - delayed: 0 - reserved: 33 - done: 162 [root@cc121bb54862 channel-pub-api]# ./yii source-callback-queue/info --color=0 Jobs - waiting: 0 - delayed: 0 - reserved: 0 - done: 166
4、由于 Supervisor 仅启动 1 个 queue/listen,因此,一旦某一队列处于 reserved,则其他队列只好一直处于 waiting 状态,所以,临时决定 remove 命令删除作业,以启动程序的继续正常运转,查看 log 表,其 message 字段内容,可以确定队列 ID 值为:159,info 命令打印关于队列状态的信息时,reserved 状态的队列数量减少 1,done 状态的队列数量增加 1,符合预期,如图2
[root@cc121bb54862 /]# cd /mcloud/www/channel-pub-api/ [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 20 - delayed: 0 - reserved: 33 - done: 162 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/remove 159 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 20 - delayed: 0 - reserved: 32 - done: 163
5、基于以上流程,重复地分别执行 remove 命令删除作业,等待一段时间后,info 命令打印关于队列状态的信息时,reserved 状态的队列数量持续减少中,done 状态的队列数量持续增加中,符合预期
[root@cc121bb54862 /]# cd /mcloud/www/channel-pub-api/ [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 18 - delayed: 0 - reserved: 33 - done: 164 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/remove 184 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 17 - delayed: 0 - reserved: 33 - done: 165 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/remove 175 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 18 - delayed: 0 - reserved: 30 - done: 167 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/remove 141 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 18 - delayed: 0 - reserved: 29 - done: 168 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/remove 168 [root@cc121bb54862 channel-pub-api]# ./yii pub-article-queue/info --color=0 Jobs - waiting: 17 - delayed: 0 - reserved: 29 - done: 169
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/250498.html