백그라운드에서 장기 작업을 실행하기 위한 솔루션

藏色散人
풀어 주다: 2019-09-23 09:28:40
앞으로
4316명이 탐색했습니다.

해결된 문제:

● 시간이 오래 걸립니다.

● 각 끝에서 피드백을 위해 관련 작업 진행 상황을 검색할 수 없습니다.

● 작업을 사용자 정의한 후 결과를 피드백합니다.

● Laravel이 프로그램을 어떻게 만들 수 있는지 알려주세요. 시간 초과 기간 동안 백그라운드에서 실행됩니다. 코드가 길까요?

프로세스에 대한 간략한 설명

● 비동기 대기열을 사용하여 관련 작업 실행

● 보조 메소드를 사용하여 작업 생성/진행

● 노출된 인터페이스를 통해 관련 진행 상황 피드백

어시스턴트 클래스의 소스 코드는 다음과 같습니다. 다음과 같이

<?php
// +----------------------------------------------------------------------
// | Do what we can do
// +----------------------------------------------------------------------
// | Date  : 2019/9/11 - 9:25 AM
// +----------------------------------------------------------------------
// | Author: seebyyu <seebyyu@gmail.com> :)
// +----------------------------------------------------------------------
namespace App\Lib\Support;
trait MissionFrom
{
    /**
     * 标记前缀 模块名称#业务模块#板块标记
     *
     * @var string
     */
    public $prefix = &#39;school:task:default&#39;;
    /**
     * 任务详情
     * @var array
     */
    public $original = [];
    /**
     * Redis 链接
     *
     * The Redis factory implementation.
     *
     * @var \Illuminate\Redis\Connections\Connection
     */
    protected $redis;
    /**
     * 任务存在有效期
     *
     * @var int
     */
    protected $seconds = 600;
    /**
     * 创建任务
     *
     * @param string $sheet
     * @param int $len 总长度
     * @return string
     */
    public function createTask($sheet = &#39;&#39;, $len = 100)
    {
        $sheet = $sheet ?: $this->sheet();
        $detail = [
            //  开始时间
            &#39;begin&#39; => time(),
            //  标记号
            &#39;sheet&#39; => $sheet,
            //  总长度
            &#39;total_len&#39; => $len,
            //  当前长度
            &#39;schedule&#39; => 0
        ];
        //  主体信息
        $this->connect()->setex($this->prefix. &#39;:&#39;. $sheet, $this->seconds, serialize($detail));
        //  初始化任务进度
        $this->connect()->setex($this->prefix. &#39;:schedule:&#39;. $sheet, $this->seconds, 1);
        return $sheet;
    }
    /**
     * 设置任务内容
     *
     * @param $sheet
     * @param $value
     * @return MissionFrom
     */
    public function setTaskContent($sheet, $value)
    {
        if( $this->connect()->exists($this->prefix. &#39;:&#39;. $sheet)){
            $this->connect()->setex($this->prefix. &#39;:content:&#39;. $sheet, $this->seconds, serialize($value));
        }
        return $this;
    }
    /**
     * 获取任务内容
     *
     * @param $sheet
     * @return MissionFrom
     */
    public function getTaskContent($sheet)
    {
        return empty($data = $this->connect()->get($this->prefix. &#39;:content:&#39;. $sheet)) ? null : unserialize($data);
    }
    /**
     * 设置任务前缀
     *
     * @param string $prefix
     * @return $this
     */
    public function setPrefix($prefix = &#39;&#39;)
    {
        $this->prefix = &#39;school:task:&#39;. ($prefix ?: &#39;default&#39;);
        return $this;
    }
    /**
     * 任务详情
     *
     * @param string $sheet
     * @return array
     */
    public function taskDetail($sheet = &#39;&#39;)
    {
        $detail = $this->connect()->get($key = ($this->prefix. &#39;:&#39;. $sheet));
        if( !empty($detail)){
            $this->original = array_merge( unserialize($detail), [
                &#39;schedule&#39; => (int)$this->getSchedule($sheet),
                &#39;content&#39; => $this->getTaskContent($sheet)
            ]);
        }
        return (array) $this->original;
    }
    /**
     * 进度递增
     *
     * @param string $sheet
     * @return int
     */
    public function increments($sheet = &#39;&#39;)
    {
        $inc = 0;
        if( !empty($detail = $this->taskDetail($sheet)) &&
            $detail[&#39;schedule&#39;] < $detail[&#39;total_len&#39;]){
            $inc = $this->connect()->incr($this->prefix. &#39;:schedule:&#39;. $sheet);
        }
        return $detail[&#39;schedule&#39;] ?? $inc;
    }
    /**
     * 获取任务进度
     *
     * @param string $sheet
     * @return string
     */
    public function getSchedule($sheet = &#39;&#39;)
    {
        return $this->connect()->exists($key = ($this->prefix. &#39;:schedule:&#39;. $sheet)) ? $this->connect()->get($key) : 0;
    }
    /**
     * 生成任务单号
     */
    private static function sheet()
    {
        return md5(\Hash::make(date(&#39;YmdHis&#39;)));
    }
    /**
     * 所有任务进度
     *
     * @return array
     */
    public function taskAll()
    {
        $task_group_list = [];
        //  分组
        foreach( (array)$this->connect()->keys(&#39;school:task:*&#39;) as $task) {
            if( count($task_item = explode(&#39;:&#39;, $task)) == 4){
                list($model, $model_name, $business, $key) = $task_item;
                $task_group_list[$business][] = $this->setPrefix($business)->taskDetail($key);
            }
        }
        return $task_group_list;
    }
    /**
     * @return \Illuminate\Foundation\Application|mixed
     */
    public function connect()
    {
        return app(&#39;redis.connection&#39;);
    }
}
로그인 후 복사

호출 프로세스 다음과 같이 e

<?php
namespace App\Jobs;
use App\Lib\Support\MissionFrom;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
/**
 * Excel 导入
 *
 * Class importExcel
 * @package App\Jobs
 */
class importExcel implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MissionFrom;
    /**
     * 任务运行的超时时间。
     *
     * @var int
     */
    public $timeout = 300;
    /**
     * @var string
     */
    public $sheet;
    /**
     * importExcel constructor.
     * @param $sheet
     */
    public function __construct($sheet = &#39;&#39;)
    {
        $this->sheet = $sheet;
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //  自定义业务前缀
        $prefix = &#39;export_students&#39;;
        //  创建任务进度
        $this->sheet = $this->setPrefix($prefix)->createTask($this->sheet, 20);
        //  开始执行任务
        echo &#39;任务开始:&#39;. $this->sheet. "\n";
        for ($i = 1; $i <= 20; $i++){
            //  延时模拟长时间任务
            sleep(rand(1, 2));
            //  进度 +1
            echo &#39;任务进度:&#39;. ($this->setPrefix($prefix)->increments($this->sheet)). "\n";
        }
        //  追加结果 任何类型
        $this->setPrefix($prefix)->setTaskContent($this->sheet, [
            &#39;url&#39; => &#39;http://www.baidu.com&#39;
        ]);
    }
}
로그인 후 복사

컨트롤러 부분의 효과

....
    /**
     * 学校pc端后台任务进度列表
     *
     * @return array
     */
    public function duties()
    {
        if( empty($key = request(&#39;key&#39;))){
            $key = md5(\Hash::make(date(&#39;YmdHis&#39;)));
            //  创建任务
            $this->dispatch(new importExcel($key));
            return $key;
        }else{
            //  查询单条任务信息
            //  $this->setPrefix(&#39;export_students&#39;)->taskDetail($key);
            return success([&#39;data&#39; => array_merge([
                //  导出每餐记录列表
                &#39;meal_records&#39; => [],
                //  每日记录列表
                &#39;daily_records&#39; => [],
                //  其他记录列表
                &#39;other_records&#39; => [],
                //  照片库
                &#39;photo_gallery&#39; => [],
                //  采购计划
                &#39;purchasing_plan&#39; => [],
                //  凭证记录
                &#39;voucher_records&#39; => [],
                //  食材库
                &#39;ingredient_records&#39; => [],
                //  导入学生
                &#39;import_students&#39; => [],
                //  导出学生
                &#39;export_students&#39; => []
            ], $this->taskAll())]);
        }
    }
    ....
로그인 후 복사

백그라운드에서 장기 작업을 실행하기 위한 솔루션

달성

_Queue_Driver = redis

개발에 동기화 단계에서는 설치하는 것이 좋습니다. 오류 보고서에 대해 정말 불평할 수 없습니다. 문제 해결이 불편합니다.

대기열 문제 해결 참조:

Laravel 대기열: 대기열 오류 정보를 확인하는 방법은 무엇입니까?

드디어

● 위 코드는 완전히 제가 작성한 프로젝트를 바탕으로 작성한 것이므로 직접 복사하면 호환성 문제가 발생할 수 있습니다.

● 공유는 솔루션 아이디어에 가깝습니다. 앞으로 다른 사람들에게 도움이 되기를 바랍니다.

● 코드에 대한 최적화 아이디어나 제안 사항이 있으면 토론할 수도 있습니다.

더 많은 Laravel 관련 기술 기사를 보려면

Laravel Framework Getting Started Tutorial

칼럼을 방문하여 알아보세요!

위 내용은 백그라운드에서 장기 작업을 실행하기 위한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:learnku.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿