zoukankan      html  css  js  c++  java
  • 记一次Laravel Job 异步队列 调用Artisan::call构造函数赋值导致的问题

    先说下bug背景,以下是调用链:

    调用链

      php版本7.1

    laraavel版本5.5

     说明下运行流程A:通过调用TestC artisan command或者接口用dispatch方法将TestCJob放入异步队列,TestCJob通过handle方法调用Artisan::call运行TestCItem,最后这个TestCItem在构造方法中初始化一些变量如runtime,在运行时打印runtime

    注意注意注意,这里就出现问题了

    首先重启队列(让Job生效)

    第一种使用场景:运行流程A的时候,TestCItem handel的时候打印的runtime是重启队列的时间,以后的每个Job调用TestCItem的handle都是打印的重启队列的时间

    第二种使用场景:直接通过命令行执行TestCItem时handle,但是这时打印的是执行时间

     以下是运行日志:

     重启Job队列时会打印一次,之后再执行流程A就不会进入构造函数且runtime是构造函数时间

     

    直接运行TestCItem命令行则每次都会进入TestCItem的构造函数

    这就会造成问题在流程A中runtime和一些其他的在构造函数里设置的值每次运行不是最新的,

    回想下Laravel的架构就会发现问题所在:

    这里Artisan::call向laravel的容器中注入了一个Artisan Command,所以触发了构造函数,之后每次运行时就直接使用注入的对象,所以之前初始化的runtime就是对象构造时候的时间

    所以在Laravel中组合使用Job队列和ArtisanCommand时要注意,千万不要使用构造函数赋值(你将得到Job队列重启时的赋值),应该在handle中赋值使用。

     以下是各个类:

    TestC
    <?php
    
    namespace AppConsoleCommands;
    
    use AppJobsTestCJob;
    use IlluminateConsoleCommand;
    
    class TestC extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'testc';
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'testc';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Execute the console command.
         *
         * @return mixed
         */
        public function handle()
        {
            $this->output('---脚本开始---');
            dispatch(new TestCJob('xxxxx'))->onConnection('redis');
            $this->output('---脚本结束---');
        }
    
        /**
         * @param $msg
         * @param bool $showTime
         * @param bool $isCli
         */
        public function output($msg, $showTime = true, $isCli = true)
        {
            echo ($showTime ? date('Y-m-d H:i:s') . ' ' : '') . $msg . ($isCli ? PHP_EOL : '<br/>');
        }
    
    }

    TestCJob

    <?php
    
    namespace AppJobs;
    
    use Exception;
    use IlluminateBusQueueable;
    use IlluminateContractsQueueShouldQueue;
    use IlluminateFoundationBusDispatchable;
    use IlluminateQueueInteractsWithQueue;
    use IlluminateQueueSerializesModels;
    use IlluminateSupportFacadesArtisan;
    
    class TestCJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
        /**
         * 任务可以尝试的最大次数。
         *
         * @var int
         */
        public $tries = 3;
    
        /**
         * 任务可以执行的最大秒数 (超时时间)。
         *
         * @var int
         */
        public $timeout = 120;
        /**
         * Create a new job instance.
         *
         * @return void
         */
        public function __construct()
        {
        }
        /**
         * Execute the job.
         *
         * @return void
         */
        public function handle()
        {
            $re = 1;
            $re = Artisan::call('testcitem');
            file_put_contents('testcitem.log', '$re' . $re . "
    ", 8);
        }
        /**
         * 任务失败的处理过程
         *
         * @param  Exception  $exception
         * @return void
         */
        public function failed(Exception $exception)
        {
            file_put_contents('testcitemfail.log', json_encode($exception->getMessage()) . "
    ", 8);
            // 给用户发送任务失败的通知,等等……
        }
    
    }

    TestCItem

    <?php
    
    namespace AppConsoleCommands;
    
    use IlluminateConsoleCommand;
    
    class TestCItem extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'testcitem';
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'testcitem';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
            $this->runtime = date('Y-m-d H:i:s');
            $this->output('---TestCItem---__construct');
        }
    
        private $runtime = 0;
        /**
         * Execute the console command.
         *
         * @return mixed
         */
        public function handle()
        {
            $this->output('---handle---' . $this->runtime);
            return 0;
        }
    
        /**
         * @param $msg
         * @param bool $showTime
         * @param bool $isCli
         */
        public function output($msg, $showTime = true, $isCli = true)
        {
            echo ($showTime ? date('Y-m-d H:i:s') . ' ' : '') . $msg . ($isCli ? PHP_EOL : '<br/>');
        }
    
    }
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/timseng/p/13019289.html
Copyright © 2011-2022 走看看