溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Laravel如何讓程序在后臺執(zhí)行超長時間

發(fā)布時間:2020-12-31 11:20:39 來源:億速云 閱讀:193 作者:小新 欄目:編程語言

這篇文章主要介紹Laravel如何讓程序在后臺執(zhí)行超長時間,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

解決的問題:

● 耗時較長

● 各端無法調(diào)取相關(guān)任務(wù)進度進行反饋

● 自定義任務(wù)過后反饋結(jié)果

● 請教下,Laravel 如何讓程序在后臺執(zhí)行超長時間的代碼?

流程簡述

● 使用異步隊列執(zhí)行相關(guān)任務(wù)

● 使用助手方法進行任務(wù) / 進度創(chuàng)建

● 通過暴露接口反饋相關(guān)進度

助手類源碼如下

<?php
// +----------------------------------------------------------------------
// | Do what we can do
// +----------------------------------------------------------------------
// | Date  : 2019/9/11 - 9:25 AM
// +----------------------------------------------------------------------
// | Author: seebyyu <seebyyu@gmail.com> :)
// +----------------------------------------------------------------------
namespace App\Lib\Support;
trait MissionFrom
{
    /**
     * 標記前綴 模塊名稱#業(yè)務(wù)模塊#板塊標記
     *
     * @var string
     */
    public $prefix = 'school:task:default';
    /**
     * 任務(wù)詳情
     * @var array
     */
    public $original = [];
    /**
     * Redis 鏈接
     *
     * The Redis factory implementation.
     *
     * @var \Illuminate\Redis\Connections\Connection
     */
    protected $redis;
    /**
     * 任務(wù)存在有效期
     *
     * @var int
     */
    protected $seconds = 600;
    /**
     * 創(chuàng)建任務(wù)
     *
     * @param string $sheet
     * @param int $len 總長度
     * @return string
     */
    public function createTask($sheet = '', $len = 100)
    {
        $sheet = $sheet ?: $this->sheet();
        $detail = [
            //  開始時間
            'begin' => time(),
            //  標記號
            'sheet' => $sheet,
            //  總長度
            'total_len' => $len,
            //  當(dāng)前長度
            'schedule' => 0
        ];
        //  主體信息
        $this->connect()->setex($this->prefix. ':'. $sheet, $this->seconds, serialize($detail));
        //  初始化任務(wù)進度
        $this->connect()->setex($this->prefix. ':schedule:'. $sheet, $this->seconds, 1);
        return $sheet;
    }
    /**
     * 設(shè)置任務(wù)內(nèi)容
     *
     * @param $sheet
     * @param $value
     * @return MissionFrom
     */
    public function setTaskContent($sheet, $value)
    {
        if( $this->connect()->exists($this->prefix. ':'. $sheet)){
            $this->connect()->setex($this->prefix. ':content:'. $sheet, $this->seconds, serialize($value));
        }
        return $this;
    }
    /**
     * 獲取任務(wù)內(nèi)容
     *
     * @param $sheet
     * @return MissionFrom
     */
    public function getTaskContent($sheet)
    {
        return empty($data = $this->connect()->get($this->prefix. ':content:'. $sheet)) ? null : unserialize($data);
    }
    /**
     * 設(shè)置任務(wù)前綴
     *
     * @param string $prefix
     * @return $this
     */
    public function setPrefix($prefix = '')
    {
        $this->prefix = 'school:task:'. ($prefix ?: 'default');
        return $this;
    }
    /**
     * 任務(wù)詳情
     *
     * @param string $sheet
     * @return array
     */
    public function taskDetail($sheet = '')
    {
        $detail = $this->connect()->get($key = ($this->prefix. ':'. $sheet));
        if( !empty($detail)){
            $this->original = array_merge( unserialize($detail), [
                'schedule' => (int)$this->getSchedule($sheet),
                'content' => $this->getTaskContent($sheet)
            ]);
        }
        return (array) $this->original;
    }
    /**
     * 進度遞增
     *
     * @param string $sheet
     * @return int
     */
    public function increments($sheet = '')
    {
        $inc = 0;
        if( !empty($detail = $this->taskDetail($sheet)) &&
            $detail['schedule'] < $detail['total_len']){
            $inc = $this->connect()->incr($this->prefix. ':schedule:'. $sheet);
        }
        return $detail['schedule'] ?? $inc;
    }
    /**
     * 獲取任務(wù)進度
     *
     * @param string $sheet
     * @return string
     */
    public function getSchedule($sheet = '')
    {
        return $this->connect()->exists($key = ($this->prefix. ':schedule:'. $sheet)) ? $this->connect()->get($key) : 0;
    }
    /**
     * 生成任務(wù)單號
     */
    private static function sheet()
    {
        return md5(\Hash::make(date('YmdHis')));
    }
    /**
     * 所有任務(wù)進度
     *
     * @return array
     */
    public function taskAll()
    {
        $task_group_list = [];
        //  分組
        foreach( (array)$this->connect()->keys('school:task:*') as $task) {
            if( count($task_item = explode(':', $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('redis.connection');
    }
}

調(diào)用過程如下

<?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 導(dǎo)入
 *
 * Class importExcel
 * @package App\Jobs
 */
class importExcel implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MissionFrom;
    /**
     * 任務(wù)運行的超時時間。
     *
     * @var int
     */
    public $timeout = 300;
    /**
     * @var string
     */
    public $sheet;
    /**
     * importExcel constructor.
     * @param $sheet
     */
    public function __construct($sheet = '')
    {
        $this->sheet = $sheet;
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //  自定義業(yè)務(wù)前綴
        $prefix = 'export_students';
        //  創(chuàng)建任務(wù)進度
        $this->sheet = $this->setPrefix($prefix)->createTask($this->sheet, 20);
        //  開始執(zhí)行任務(wù)
        echo '任務(wù)開始:'. $this->sheet. "\n";
        for ($i = 1; $i <= 20; $i++){
            //  延時模擬長時間任務(wù)
            sleep(rand(1, 2));
            //  進度 +1
            echo '任務(wù)進度:'. ($this->setPrefix($prefix)->increments($this->sheet)). "\n";
        }
        //  追加結(jié)果 任何類型
        $this->setPrefix($prefix)->setTaskContent($this->sheet, [
            'url' => 'http://www.baidu.com'
        ]);
    }
}

控制器部分

....
    /**
     * 學(xué)校pc端后臺任務(wù)進度列表
     *
     * @return array
     */
    public function duties()
    {
        if( empty($key = request('key'))){
            $key = md5(\Hash::make(date('YmdHis')));
            //  創(chuàng)建任務(wù)
            $this->dispatch(new importExcel($key));
            return $key;
        }else{
            //  查詢單條任務(wù)信息
            //  $this->setPrefix('export_students')->taskDetail($key);
            return success(['data' => array_merge([
                //  導(dǎo)出每餐記錄列表
                'meal_records' => [],
                //  每日記錄列表
                'daily_records' => [],
                //  其他記錄列表
                'other_records' => [],
                //  照片庫
                'photo_gallery' => [],
                //  采購計劃
                'purchasing_plan' => [],
                //  憑證記錄
                'voucher_records' => [],
                //  食材庫
                'ingredient_records' => [],
                //  導(dǎo)入學(xué)生
                'import_students' => [],
                //  導(dǎo)出學(xué)生
                'export_students' => []
            ], $this->taskAll())]);
        }
    }
    ....

達到的效果

Laravel如何讓程序在后臺執(zhí)行超長時間

注意事項

QUEUE_DRIVER=sync 變更為 redis

開發(fā)階段強烈建議把 horizon 這玩意兒裝上,Laravel 自帶的報錯異常我實在無力吐槽,不方便排錯.

以上是“Laravel如何讓程序在后臺執(zhí)行超長時間”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI