think-queue队列处理消费时默认的是单个redis实例,如果单个消费处理时间很长,例如我们现在的一个项目用户导出excel报表任务,我每次导20万-500万数据的报表,平均每次任务得五分钟至30分钟,这个很容易出现redis服务端拒绝连接的错误,例如图下
因为每次处理消费时think-queue会实例化一个redis实例,在整个处理消费的上下文中都是用那一个redis实例的,但redis服务有默认连接是有有效期的,如果消费处理时间比较长,最后会因为redis实例连接过期而报错,而think-queue的redis驱动并没有掉线重连处理,这时候我们就需要改一下think-queue源代码了,例如我给消费处理添加了一个公用属性,reconnect,用于在每次处理消费时间比较长的任务调用redis实例时是否重新创建redis连接实例,当然也可以自己写掉线重连代码,不过消费任务时间比较长还是建议重新创建redis连接实例,毕竟维护redis连接很麻烦和耗资源,下面是我的消费处理代码
<?php
namespace app\spider\job;
use app\spider\library\Common;
use think\queue\Job;
class ExcelJob
{
public $reconnect=true;//是否重连,true=重新连接,false=不重连
/*
*用户导出处理
* */
public function excelTask(Job $job, $data){
if ($job->attempts() > 3) {
$job->delete();
return;
}
$dataArr=json_decode($data,true);
$exportObj=new \app\common\library\ExportData();
$result=$exportObj->handleExportTask($dataArr);
if($result['code'] == 'success'){
$job->delete();
}else{
$job->release(1);
}
unset($exportObj);
}
}
我在消费处理类添加了个reconnect公用属性,用于判断这个消费处理是不是超耗时的任务,如果是耗时的任务我每次操作redis实例时重新创建一个连接实例,其中think-queue源代码也需要改一下,需要改三个文件
- vendor\topthink\think-queue\src\queue\Job.php 文件
- vendor\topthink\think-queue\src\queue\job\Redis.php 文件
- vendor\topthink\think-queue\src\queue\connector\Redis.php 文件
先看第一个文件vendor\topthink\think-queue\src\queue\Job.php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
//