很多任务,我们可以将它抽离出来,放到任务队列去执行。类似用户注册成功后的邮件发送。因为假设有多个人同时注册,但邮件是不能同时发送的。而且注册成功后立马发送邮件,等待api的响应时间也很长。从而影响了用户体验性,所以对于这种不是太重要的功能。可以放到队列里。让它在后台依次执行。Laravel内置的队列有以下几种:
一般使用最多的还是用 redis
来进行队列
队列类似于生产者和消费者,可以将队列事件触发称为生产者,而消费者则是将队列中的任务完成。
下面来说说在 Laravel
中实现队列功能:
- 如果使用
Database
驱动程序来使用队列,那么需要一张数据表来存放队列作业: ```shell php artisan queue:table
php artisan migrate
一般情况,我们很少使用 database 来存放队列,因为这会对数据库的压力很大。
- 建议你使用 `redis` 来存放队列,因为它的读取速度快,这是我个人 `config/queue.php` 内的配置:
```php
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
block_for
选项为队列在执行时的阻塞时间,单位为秒。这里只对 redis
和 database
驱动作简要说明。
实践
假设为我们要在用户注册成功后。将发送邮件的功能放到队列里。让它依次被消费完成。首先创建一个任务类:
php artisan make:job SendMail
执行以上命令laravel 会为你在 app/Jobs
目录生成 SendMail
,你可以在 SendMail
类里注入你想要的依赖
<?php
namespace App\Jobs;
use App\Mail\Welcome;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendMail implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public User $user;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(User $user) {
$this->user = $user;
}
/**
* Execute the job.
* 发送邮件
* @return void
*/
public function handle() {
Mail::to($this->user->email)->send(new Welcome($this->user));
}
}
handel
会自动执行,所以你不用担心。我们将它放到 UserObserver
类的created
方法里。等待用户注册成功后分发任务。
<?php
namespace App\Observers;
use App\Jobs\SendMail;
use App\Models\User;
class UserObserver {
/**
* 在事务处理后触发事件
* @var bool
*/
public $afterCommit = true;
/**
* 使用队列分发邮件
*/
public function created(User $user) {
dispatch(new SendMail($user));
}
}
使用全局辅助函数 dispatch
来实列化一个任务。这样就完成了任务的创建。
完成这些是不够的。任务是要一直运行的。但是不能保证命令会中断。所以使用 Linux 的 Supervisor
sudo apt-get install supervisor
安装后在 /etc/supervisor/conf.d
创建你的任务配置文件,这里创建一个 laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/df/code/laravel/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=df
numprocs=8
redirect_stderr=true
stdout_logfile=/home/df/code/laravel/worker.log
stopwaitsecs=3600
这里需要注意对应自己的项目目录 ,驱动是指定的redisnumprocs
是指的用几个进程来处理任务。
完成以上你需要安装 php-redis
sudo apt-get install php-redis
.env
需要配置好redis
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=123456
REDIS_PORT=6379