很多任务,我们可以将它抽离出来,放到任务队列去执行。类似用户注册成功后的邮件发送。因为假设有多个人同时注册,但邮件是不能同时发送的。而且注册成功后立马发送邮件,等待api的响应时间也很长。从而影响了用户体验性,所以对于这种不是太重要的功能。可以放到队列里。让它在后台依次执行。Laravel内置的队列有以下几种:

Laravel-队列 - 图1
一般使用最多的还是用 redis 来进行队列
队列类似于生产者和消费者,可以将队列事件触发称为生产者,而消费者则是将队列中的任务完成。

下面来说说在 Laravel 中实现队列功能:

  • 如果使用 Database 驱动程序来使用队列,那么需要一张数据表来存放队列作业: ```shell php artisan queue:table

php artisan migrate

  1. 一般情况,我们很少使用 database 来存放队列,因为这会对数据库的压力很大。
  2. - 建议你使用 `redis` 来存放队列,因为它的读取速度快,这是我个人 `config/queue.php` 内的配置:
  3. ```php
  4. 'redis' => [
  5. 'driver' => 'redis',
  6. 'connection' => 'default',
  7. 'queue' => env('REDIS_QUEUE', 'default'),
  8. 'retry_after' => 90,
  9. 'block_for' => null,
  10. ],

block_for 选项为队列在执行时的阻塞时间,单位为秒。这里只对 redisdatabase 驱动作简要说明。

实践

假设为我们要在用户注册成功后。将发送邮件的功能放到队列里。让它依次被消费完成。首先创建一个任务类:

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

这里需要注意对应自己的项目目录 ,驱动是指定的redis
numprocs 是指的用几个进程来处理任务。

完成以上你需要安装 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