這篇文章主要介紹Laravel如何讓程序在后臺(tái)執(zhí)行超長(zhǎng)時(shí)間,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司提供網(wǎng)站設(shè)計(jì)和自適應(yīng)建站服務(wù)。團(tuán)隊(duì)由有經(jīng)驗(yàn)的網(wǎng)頁(yè)設(shè)計(jì)師、程序員和市場(chǎng)專家組成,能夠提供從H5網(wǎng)站設(shè)計(jì),網(wǎng)站制作,廣告投放,模板建站到小程序設(shè)計(jì)等全方位服務(wù)。 以客戶為中心,致力于為客戶提供創(chuàng)新、高效的解決方案,幫助您打造成功的企業(yè)網(wǎng)站。
解決的問題:
● 耗時(shí)較長(zhǎng)
● 各端無(wú)法調(diào)取相關(guān)任務(wù)進(jìn)度進(jìn)行反饋
● 自定義任務(wù)過(guò)后反饋結(jié)果
● 請(qǐng)教下,Laravel 如何讓程序在后臺(tái)執(zhí)行超長(zhǎng)時(shí)間的代碼?
流程簡(jiǎn)述
● 使用異步隊(duì)列執(zhí)行相關(guān)任務(wù)
● 使用助手方法進(jìn)行任務(wù) / 進(jìn)度創(chuàng)建
● 通過(guò)暴露接口反饋相關(guān)進(jìn)度
助手類源碼如下
:) // +---------------------------------------------------------------------- namespace App\Lib\Support; trait MissionFrom { /** * 標(biāo)記前綴 模塊名稱#業(yè)務(wù)模塊#板塊標(biāo)記 * * @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 總長(zhǎng)度 * @return string */ public function createTask($sheet = '', $len = 100) { $sheet = $sheet ?: $this->sheet(); $detail = [ // 開始時(shí)間 'begin' => time(), // 標(biāo)記號(hào) 'sheet' => $sheet, // 總長(zhǎng)度 'total_len' => $len, // 當(dāng)前長(zhǎng)度 'schedule' => 0 ]; // 主體信息 $this->connect()->setex($this->prefix. ':'. $sheet, $this->seconds, serialize($detail)); // 初始化任務(wù)進(jìn)度 $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; } /** * 進(jìn)度遞增 * * @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ù)進(jìn)度 * * @param string $sheet * @return string */ public function getSchedule($sheet = '') { return $this->connect()->exists($key = ($this->prefix. ':schedule:'. $sheet)) ? $this->connect()->get($key) : 0; } /** * 生成任務(wù)單號(hào) */ private static function sheet() { return md5(\Hash::make(date('YmdHis'))); } /** * 所有任務(wù)進(jìn)度 * * @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)用過(guò)程如下
sheet = $sheet; } /** * Execute the job. * * @return void */ public function handle() { // 自定義業(yè)務(wù)前綴 $prefix = 'export_students'; // 創(chuàng)建任務(wù)進(jìn)度 $this->sheet = $this->setPrefix($prefix)->createTask($this->sheet, 20); // 開始執(zhí)行任務(wù) echo '任務(wù)開始:'. $this->sheet. "\n"; for ($i = 1; $i <= 20; $i++){ // 延時(shí)模擬長(zhǎng)時(shí)間任務(wù) sleep(rand(1, 2)); // 進(jìn)度 +1 echo '任務(wù)進(jìn)度:'. ($this->setPrefix($prefix)->increments($this->sheet)). "\n"; } // 追加結(jié)果 任何類型 $this->setPrefix($prefix)->setTaskContent($this->sheet, [ 'url' => 'http://www.baidu.com' ]); } }
控制器部分
.... /** * 學(xué)校pc端后臺(tái)任務(wù)進(jìn)度列表 * * @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' => [], // 照片庫(kù) 'photo_gallery' => [], // 采購(gòu)計(jì)劃 'purchasing_plan' => [], // 憑證記錄 'voucher_records' => [], // 食材庫(kù) 'ingredient_records' => [], // 導(dǎo)入學(xué)生 'import_students' => [], // 導(dǎo)出學(xué)生 'export_students' => [] ], $this->taskAll())]); } } ....
達(dá)到的效果
注意事項(xiàng)
QUEUE_DRIVER=sync 變更為 redis
開發(fā)階段強(qiáng)烈建議把 horizon 這玩意兒裝上,Laravel 自帶的報(bào)錯(cuò)異常我實(shí)在無(wú)力吐槽,不方便排錯(cuò).
以上是“Laravel如何讓程序在后臺(tái)執(zhí)行超長(zhǎng)時(shí)間”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!