zoukankan      html  css  js  c++  java
  • Laravel --Jobs (同步异步)消息队列 Queue --晋升篇

    Laravel --Jobs (同步异步)消息队列 Queue --晋升篇

    在很多项目业务复杂到一定程度、项目大到一定程度,就都是一些重构、优化、升级等手段,让项目更稳健;能抵挡更强的“风暴”。而 异步服务器 则也是减轻服务器压力,提高项目性能的一个常见手段之一,把一些实时性不强,而且量还比较大的业务可以异步来解决。临近年底了,丢丢哥最近工作比较忙,博客更新少了点。见谅

    本篇博客主要介绍 异步消息队列 简要的介绍下同步消息队列

    本篇博客为了更明确异步消息队列同步消息队列的实现原理 以MySQL消息队列为示例,但是在真正的项目中(如果没有单独的异步服务器,则建议使用Redis消息队列)

    一、简介

    Laravel 的队列服务为不同的队列后端系统提供了一套统一的 API 。队列允许你将一个耗时的任务进行延迟处理,例如像 e-mail 发送。这能让应用程序对页面的请求有更快的响应。

    二、配置

    队列的配置文件被保存在 config/queue.php 中。但是Laravel中优先选用.env的配置在这个文件内你可以找到包含在 Laravel 中的每一种队列驱动连接设置。它们包含了数据库、Beanstalkd、IronMQ、Amazon SQS、Redis 以及提供本机使用的 synchronous 驱动。

    .env配置同步:

    env

    .env配置异步:

    env

    另外框架也提供了 null 这个队列驱动用来丢弃队列任务。

    1.生成队列数据库表与失败队列数据库表

    本实例中是用群发email的实例,如果模仿,请配置自己的邮件服务

    php artisan queue:table
    
    php artisan queue:failed-table
    
    php artisan migrate  
    
    2.创建Mysql数据(需要发邮件)

    数据库

    3.生成队列任务
    php artisan make:job SendUserEmail --queued  
    

    然后在项目的AppJobs里面会生成一个SendUserEmail.php文件

    接下来 我们再生成一个控制器UserController

    php artisan make:controller UserController --resource  
    
    • 定义路由routes.php
    Route::resource('/user','UserController');  
    
    • 编写控制器UserController
    <?php
    
    namespace AppHttpControllers;
    
    use IlluminateHttpRequest;
    
    use AppHttpRequests;  
    use AppJobsCreateMessage;  
    use AppJobsSendUserEmail;
    
    class UserController extends Controller  
    {
       ...
       ...
       /**
         * 这个方法我们用来模拟发送消息队列.
         *
         * @param  int  $id
         * @return IlluminateHttpResponse
         */
        public function show($id)
        {
            //
            $datas = DB::table('user')->where('status',1)->get();
            foreach($datas as $data){
                $job = (new SendUserEmail($data->name,$data->email));
                $this->dispatch($job);
            }
            return redirect('/user');
        }
    
    • 编辑队列文件SendUserEmail.php
    <?php
    
    namespace AppJobs;
    
    use AppJobsJob;  
    use IlluminateQueueSerializesModels;  
    use IlluminateQueueInteractsWithQueue;  
    use IlluminateContractsBusSelfHandling;  
    use IlluminateContractsQueueShouldQueue;  
    use IlluminateSupportFacadesMail;
    
    class SendUserEmail extends Job implements SelfHandling, ShouldQueue  
    {
        use InteractsWithQueue, SerializesModels;
    
        protected $name;
        protected $email;
        /**
         * Create a new job instance.
         *
         * @return void
         */
        public function __construct($name, $email)
        {
            //
            $this->name = $name;
            $this->email = $email;
        }
    
        /**
         * Execute the job.
         *
         * @return void
         */
        public function handle()
        {
            // 如果参试大于三次
            if ($this->attempts() > 3) {
                Log::info($this->name.'邮件参试失败过多');
            }else{
                // 每次进来休息3秒钟
                sleep(3);
                // 休息10秒钟
                //$this->release(10);
                $url = 'http://www.ydma.cn';
                $title = '测试邮件';
                $to = $this->email;
                // 邮件发送
                $flag = Mail::send('email.test', ['name' => $this->name, 'url' => $url], function ($message) use ($to, $title) {
                    // 发送
                    $message->to($to)->subject('【亲爱的程序猿】' . $title);
                });
                echo date('Y-m-d H:i:s')."
    ".$to.'的邮件已发送...';
    
                if($flag){
                    Log::info($this->name.'邮件发送成功');
                }else{
                    Log::info($this->name.'邮件发送失败');
                }
            }
    
    
    
        }
    
    
        /**
         * 处理一个失败的任务
         *
         * @return void
         */
        public function failed()
        {
            Log::error($this->name.'队列任务执行失败'."
    ".date('Y-m-d H:i:s'));
        }
    }
    

    三、执行程序

    1.我们env是设置的database (异步消息队列)

    2.开启队列监听

    php artisan queue:listen  
    

    3.或者 开启后台监听(不影响自己输入其他命令)

    php artisan queue:listen &  
    

    4.也能用work 后面参数是休息时间和尝试次数

    php artisan queue:work connection --daemon --sleep=3 --tries=3  
    

    5.访问网址(这个网址是我自己本地的)

    路由

    6.然后看我的Mysql的变化jobs表本来有8条队列数据需要处理 
    Jobs

    7.然后看终端监听的变化

    消息队列监听

    8.消息队列被一条条的推送..反观数据库jobs的变化,发现被清空了,说明队列执行完了 
    jobs变化

    而且页面并不是等待邮件发完才跳转,而是发送这个队列命令后直接重定向到了user列表页面(跳转很快),这就是异步队列的整个工作流程

    当然如果你看了我之前的一片文章也可以做做全局SQL监听,你就会在日志中发现,每执行一个队列 job表里面就要执行4次命令增、删、改、查,如果是10000条数据的队列就是40000次的表操作,所以说database的消息队列用也得当心,虽然是异步的,考虑的因素还是比较多的。

    全局SQL监听-5.1

    同步消息队列

    这个消息队列,说实话丢丢哥我也是用得少,为什么呢?暂时并没有发现它的应用场景的优势。

    与异步不同的是设置同步消息队列 将.envconfig/queue.php 里面的配置改成是 sync

    然后执行页面的时候发现页面等待跳转的时间很长,得所有的邮件发送完成后才会跳转页面(如果队列中有任务执行失败反复的参试 那这页面应该肯定timeout了)

    扩展思路

    1.队列有可能失败,失败的队列会写入到mysqlfailed_jobs表里面:

    失败队列表

    2.那么如何让这些失败的队列让电脑后面自动去执行消息推送呢?也就是执行这些命令,怎么让程序自动完成

    命令

    3.如果是在一个服务器中用消息队列,是不是一直要开常驻进程??那是不是有消耗?当异步到达一个程度的时候,是不是可以开服务器集群里面的异步服务器专门来做这个事??

    进程

    希望我的博客对你们有所帮助,你的认可就是我最大的动力。。

      https://www.blog8090.com/

    本文为作者原创,允许转载,转载后请以链接形式说明文章出处. 如转载但不标明来源,后果自负。

  • 相关阅读:
    自动批改android模拟器的imei的小程序 和 下载各个版本SDK Tools及ADT
    Bulestacks模拟器Bulestacks.prop文件里中英文对照表
    HTTP Analyzer——WEB调试代理
    XCODE 添加不同IOS版本的模拟器
    在PC上运行安卓(Android)应用程序的几个方法
    二叉查找树的类模板实现
    以给定值为基分割链表
    简单二叉排序树的实现
    vector和list删除元素
    二叉树的基本操作
  • 原文地址:https://www.cnblogs.com/jhcyzxx/p/10480056.html
Copyright © 2011-2022 走看看