gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 33 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Laravel框架中队列和工作(Queues、Jobs)操作实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

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

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

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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的表:

?
1
2
$ php artisan queue:table    
$ php artisan migrate

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

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

?
1
$ php artisan make :job SendEmail

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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方法来将其添加进队列中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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命令:

?
1
$ php artisan queue:work

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

?
1
$ php artisan queue:work --tries=3

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

?
1
$ php artisan queue:work --timeout=30

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

?
1
$ php artisan queue:work -- sleep =10

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

本文使用Laravel 5.6进行讲解 。

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

原文链接:https://blog.sbot.io/articles/24 。

最后此篇关于Laravel框架中队列和工作(Queues、Jobs)操作实例详解的文章就讲到这里了,如果你想了解更多关于Laravel框架中队列和工作(Queues、Jobs)操作实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com