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/tech/pnotes/250498.html
