美文网首页Laravel
112-Laravel 异步队列

112-Laravel 异步队列

作者: 霄峰 | 来源:发表于2017-01-05 23:00 被阅读246次

    这里以发邮件为例,使用Redis做为队列驱动。
    要先安装predis组件:
    composer require predis/predis
    注意:要把php自带的redis插件删除掉!


    1. 配置发送邮箱

    1.1 在项目的.env文件中配置

    DB_HOST= #数据库主机地址
    DB_DATABASE= #数据库名
    DB_USERNAME= #数据库帐号
    DB_PASSWORD= #数据库密码
    
    QUEUE_DRIVER=redis #选用redis做队列驱动
    
    MAIL_DRIVER=smtp
    MAIL_HOST=邮箱服务器地址,如:smtp.126.com
    MAIL_PORT=邮箱服务器端口,如:25
    MAIL_USERNAME=你的邮箱帐号
    MAIL_PASSWORD=你的邮箱密码或授权码
    MAIL_ENCRYPTION=null
    

    1.2 修改config/mail.php

    'from' => ['address' => '你的邮箱帐号', 'name' => '项目名称'],
    

    2. 生成任务类

    php artisan make:job SendMailJob --queued
    

    队列的任务类都默认放在app/Jobs目录下,任务类会包含一个让队列用来调用此任务的handle方法,我们就在这个方法内写要队列执行的动作:

    <?php
    
    namespace App\Jobs;
    
    use Log;
    use Mail;
    use App\Jobs\Job;
    use Swift_RfcComplianceException;
    use Exception;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Bus\SelfHandling;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class SendMailJob extends Job implements SelfHandling, ShouldQueue
    {
        use InteractsWithQueue, SerializesModels;
    
        private $to;
        /**
         * Create a new job instance.
         *
         * @return void
         */
        public function __construct($to = '')
        {
            $this->to = $to;
        }
    
        /**
         * 运行任务。
         *
         * @return void
         */
        public function handle()
        {
            if ($this->attempts() > 3) {
                // 失败了
                echo '失败了';
                return false;
            }
    
            $to = $this->to;
            try {
                // 发邮件
                Mail::send('mails.active', ['content' => 'this is a test Email ! by SCORT !!!'], function ($m) use($to) {
                    $m->from('你的邮箱帐号', '项目名称')
                      ->to($to)
                      ->subject('邮件主题');
                });
    
                echo '成功:' . date('Ymd') . "\n";
            } catch (Swift_RfcComplianceException $e) {
                echo $e->getMessage();
                // 当任务失败时会被调用...
                Log::info($e->getMessage(), ['path' => __METHOD__, 'line' => __LINE__]);
            } catch (Exception $e) {
                echo 'ERROR';
                // 当任务失败时会被调用...
                Log::info($e->getMessage(), ['path' => __METHOD__, 'line' => __LINE__]);
            }
    
        }
    
        /**
         * 处理一个失败的任务
         *
         * @return void
         */
        public function failed()
        {
            // 当任务失败时会被调用...
            Log::info('当任务失败时会被调用', ['path' => __METHOD__, 'line' => __LINE__]);
        }
    }
    
    

    3. 创建邮箱模板

    视图目录resources/views/下创建mails目录,并在这个目录里面创建邮件邮件模板active.blade.php

    <html>
    <head>
        <title>邮件模板</title>
    </head>
    <body>
            <div class="quote">{{ $content or '---' }}</div>
    </div>
    </body>
    </html>
    

    4. 回调处理

    我们可以在 Laravel 内置的app/Providers/AppServiceProvider.php中附加任务事件回调函数:

    <?php
    
    namespace App\Providers;
    
    use Log;
    use Queue;
    use Illuminate\Support\ServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            // 队列失败
            Queue::failing(function ($connection, $job, $data) {
                // 通知团队失败的任务...
                Log::error($connection);
                Log::error('队列执行失败!', $data);
            });
    
            // 队列完成
            Queue::after(function ($connection, $job, $data) {
                Log::info('队列执行完成!', $data);
            });
        }
    
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }
    

    5. 把任务推送到队列上

    可以在app/Http/Controllers/TestController.php控制器(如果没有自行创建)上使用dispatch方法推送

    <?php
    
    namespace App\Http\Controllers;
    
    use App\Jobs\SendMailJob;
    use App\Http\Controllers\Controller;
    
    class TestController extends Controller
    {
        /**
         * 邮件测试
         */
        public function mail()
        {
            $toArr = [
                '469306621@qq.com',
                'feng7396553@163.com',
                'xfeng7396553',
            ];
    
            foreach ($toArr as $to) {
                $job = (new SendMailJob($to));
                $this->dispatch($job);
            }
    
            echo 'success';
    
        }
    }
    

    6. 失败处理

    当任务运行超过该重试次数时,它就会被写入至failed_jobs这个数据表中,运行迁移:

    php artisan queue:failed-table
    php artisan migrate
    

    可以用queue:failed这个 Artisan 命令查看失败任务:

    php artisan queue:failed
    

    要重试所有失败的任务,可以使用queue:retry

    php artisan queue:retry all
    

    删除所有失败的任务:

    php artisan queue:flush
    

    7. 队列监听

    php artisan queue:work --daemon --tries=3 #tries 重试次数
    

    8. 添加路由

    在路由文件app/Http/routes.php中添加如下一条路由:

    Route::get('mail', 'TestController@mail');
    

    9. 开始发邮件

    浏览器中访问:

    http://你的IP/mail
    

    相关文章

      网友评论

        本文标题:112-Laravel 异步队列

        本文链接:https://www.haomeiwen.com/subject/uuftbttx.html