• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Laravel框架中队列和工作(Queues、Jobs)操作实例详解

    在我们的web应用中,经常会遇到这样的情况:

    用户在进行了某项操作后,我们需要在后台完成一个耗时且耗费资源的任务,以对应用户的操作。

    通常来说,web应用中的操作都是同步的(synchronous),即用户的操作可以立即得到回馈。

    但是在以上情况下,同步等待操作结果将是灾难性的。比如用户点击了申请密码重置邮件,倘若我们让用户一直停滞在等待页面,直至邮件发送成功,那么用户体验将非常地不好,因为有时候可能需要很长的时间才能将邮件发送完成。

    从另一个角度来说,如果我们服务器处于高负荷的情况,当多个用户同时请求发送邮件等操作时,我们不希望同时地给服务器增加负荷,否则可能会导致服务器崩溃,造成无法预估的情况。

    从以上的讨论可以看出,我们需要一种机制,可以非同步地响应用户操作,并且不会给服务器增加过大的负荷。

    那么这样一种机制就是Queues和Jobs(即队列和工作)。

    如果你系统地学习过计算机科学,那么队列的概念你应该不陌生。假设我们去银行办事,我们拿了一个号,发现前面有8个人在等待,那么我们实际上就处在一个队列之中,队列中靠前的人会先被叫到号码,并且叫号的顺序即拿号的顺序。这样的队列就叫做Queue,采用的是先到先处理的方式,不允许插队的情况存在。而我们要办的事情就叫Job。

    在Laravel中,我们可以很方便地使用Queues及Jobs来达到我们的目的。首先我们需要先来看一下,Laravel中有哪些Queues。

    打开config/queue.php,我们可以看到几种常见的队列设置:

    return [      
      
      /*      
      |--------------------------------------------------------------------------      
      | Default Queue Connection Name      
      |--------------------------------------------------------------------------      
      |      
      | Laravel's queue API supports an assortment of back-ends via a single      
      | API, giving you convenient access to each back-end using the same      
      | syntax for every one. Here you may define a default connection.      
      |      
      */      
      
      'default' => env('QUEUE_DRIVER', 'sync'),      
      
      /*      
      |--------------------------------------------------------------------------      
      | Queue Connections      
      |--------------------------------------------------------------------------      
      |      
      | Here you may configure the connection information for each server that      
      | is used by your application. A default configuration has been added      
      | for each back-end shipped with Laravel. You are free to add more.      
      |      
      | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"      
      |      
      */      
      
      'connections' => [      
      
        'sync' => [      
          'driver' => 'sync',      
        ],      
      
        'database' => [      
          'driver' => 'database',      
          'table' => 'jobs',      
          'queue' => 'default',      
          'retry_after' => 90,      
        ],      
      
        'beanstalkd' => [      
          'driver' => 'beanstalkd',      
          'host' => 'localhost',      
          'queue' => 'default',      
          'retry_after' => 90,      
        ],      
      
        'sqs' => [      
          'driver' => 'sqs',      
          'key' => env('SQS_KEY', 'your-public-key'),      
          'secret' => env('SQS_SECRET', 'your-secret-key'),      
          'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),      
          'queue' => env('SQS_QUEUE', 'your-queue-name'),      
          'region' => env('SQS_REGION', 'us-east-1'),      
        ],      
      
        'redis' => [      
          'driver' => 'redis',      
          'connection' => 'default',      
          'queue' => 'default',      
          'retry_after' => 90,      
          'block_for' => null,      
        ],      
      
      ],      
      
      /*      
      |--------------------------------------------------------------------------      
      | Failed Queue Jobs      
      |--------------------------------------------------------------------------      
      |      
      | These options configure the behavior of failed queue job logging so you      
      | can control which database and table are used to store the jobs that      
      | have failed. You may change them to any database / table you wish.      
      |      
      */      
      
      'failed' => [      
        'database' => env('DB_CONNECTION', 'mysql'),      
        'table' => 'failed_jobs',      
      ],      
      
    ];

    在connections中,我们看到sync这个连接。sync是Laravel默认的队列,代表的就是synchronous,即同步队列。

    今天我们要来看一下,如何使用database,即数据库来实现异步任务处理。

    要使用database来作为队列的内部实现机制,我们需要建立一张用于储存Jobs的表:

    $ php artisan queue:table     
    $ php artisan migrate

    以上命令将会在数据库创建名为jobs的表。

    队列我们有了,那么现在我们来看一下Jobs。Laravel中jobs文件默认位置在app/Jobs文件夹下,我们可以通过make:job这个Artisan命令快速创建我们的job类:

    $ php artisan make:job SendEmail

    生成的job会实现Illuminate\Contracts\Queue\ShouldQueue这个接口,表明生成的job对象将被推到队列中进行异步处理。

    job类其实很简单,里面只有一个名为handle的方法,该方法在job被queue处理的时候自动被调用。

    在上面的命令中,我们创建了一个名为SendEmail的类:

    ?php    
      
    namespace App\Jobs;    
      
    use App\Email;    
    use Illuminate\Bus\Queueable;    
    use Illuminate\Queue\SerializesModels;    
    use Illuminate\Queue\InteractsWithQueue;    
    use Illuminate\Contracts\Queue\ShouldQueue;    
    use Illuminate\Foundation\Bus\Dispatchable;    
      
    class SendEmail implements ShouldQueue    
    {    
      use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;    
      
      protected $email;    
      
      /**    
       * Create a new job instance.    
       *    
       * @param Podcast $podcast    
       * @return void    
       */    
      public function __construct(Email $email)    
      {    
        $this->email = $email;    
      }    
      
      /**    
       * Execute the job.    
       *    
       * @param AudioProcessor $processor    
       * @return void    
       */    
      public function handle()    
      {    
        // Process email and send the email to recipient(s)    
        // 这里我们可以处理我们的邮件并将邮件发送至接收人 
      }    
    }

    可以看到,我们可以将model传递进job的constructor中。Laravel会自动序列化(Serialize)模型的识别信息,在job真正被处理的时候,完整的模型数据才会被从数据库调用出来。另外,在handle方法中,我们也可以注入我们的依赖dependencies。

    好了,现在我们有了job类,可以创建job对象了,那么如何把job添加进队列呢?

    在我们的控制器中,我们可以调用job的dispatch方法来将其添加进队列中:

    ?php  
      
    namespace App\Http\Controllers;  
      
    use App\Jobs\SendEmail;  
    use Illuminate\Http\Request;  
    use App\Http\Controllers\Controller;  
    use App\Email; 
      
    class EmailsController extends Controller  
    {  
      /**  
       * Store a new email.  
       *  
       * @param Request $request  
       * @return Response  
       */  
      public function send(Request $request)  
      {  
        // Create email...  
        // 这里我们提取email信息并创建$email, Email是我们自定义的Model 
        $email = Email::create($request->only('sender', 'to', 'content')); 
      
        SendEmail::dispatch($email);  
      }  
    }

    这样一来,每当我们的控制器调用send方法时,就会创建一个SendEmail的job在数据库中。

    那么怎么样调用Queue Worker来处理我们的jobs呢?

    在.env文件中,我们将QUEUE_DRIVER=sync改为QUEUE_DRIVER=database。

    接下来,我们运行以下Artisan命令:

    $ php artisan queue:work

    队列的worker会一直运行,每当有任务被添加进数据库jobs表中,worker便会自动抓取出任务进行处理。当任务失败时,worker会重复执行任务,直至最大尝试次数(默认为255)。我们可以手动设置最大尝试次数:

    $ php artisan queue:work --tries=3

    当然,我们也可以手动设置任务的超时(默认90s,在config/queue.php中的retry_after设置):

    $ php artisan queue:work --timeout=30

    最后,当没有任务的时候,我们可以设置一个睡眠时间,当worker在睡眠时间时,将不会处理任务:

    $ php artisan queue:work --sleep=10

    上面的命令意思是每当worker处理完所有任务后,会睡眠10s,然后才会再次检查任务队列

    本文使用Laravel 5.6进行讲解

    本文主要讲解了Laravel框架中队列和工作(Queues、Jobs)操作实例详解,更多关于Laravel框架的使用技巧请查看下面的相关链接

    您可能感兴趣的文章:
    • laravel5.6 框架邮件队列database驱动简单demo示例
    • Laravel使用Queue队列的技巧汇总
    • Docker部署Laravel应用实现队列&任务调度
    • Laravel 6 将新增为指定队列任务设置中间件的功能
    • Laravel 队列使用的实现
    • Laravel框架队列原理与用法分析
    • Laravel中为什么不使用blpop取队列详析
    • 关于 Laravel Redis 多个进程同时取队列问题详解
    • 源码分析 Laravel 重复执行同一个队列任务的原因
    • Laravel使用消息队列需要注意的一些问题
    • Laravel中利用队列发送邮件的方法示例
    • 浅谈Laravel队列实现原理解决问题记录
    • 浅析Laravel5中队列的配置及使用
    • PHP的Laravel框架中使用消息队列queue及异步队列的方法
    • Laravel 4.2 中队列服务(queue)使用感受
    上一篇:Laravel实现批量更新多条数据
    下一篇:Laravel框架数据库迁移操作实例详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Laravel框架中队列和工作(Queues、Jobs)操作实例详解 Laravel,框架,中,队列,和,