概述
Laravel 框架内置了强大的队列系统,用于处理异步任务、提高系统性能等。队列可以让任务异步执行,而不会阻塞当前进程,可以提高系统的处理能力。
Laravel 的队列系统支持多种驱动,如 Redis、Beanstalkd、SQS 等,可以根据自己的需求选择合适的驱动。
安装
Laravel 框架已经内置了队列组件,所以不需要单独安装。
配置队列
在 Laravel 中,队列的配置可以通过 config/queue.php 文件进行设置,也可以在代码中进行指定。此外,还可以通过 .env 文件中的配置来设置默认的队列驱动程序和其他选项。
默认情况下,Laravel 配置文件中的队列驱动为 sync,即同步模式,任务会立即执行,不会进入队列。如果需要使用队列,可以将驱动设置为支持队列的驱动,如 database、 redis、beanstalkd 等。
通过在 .env 文件中设置队列配置选项,可以方便地在不同的环境中进行队列配置。例如,可以在本地环境中使用 sync 驱动程序,在生产环境中使用 database 驱动程序。
例如:
QUEUE_CONNECTION=database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database
DB_USERNAME=username
DB_PASSWORD=password
注意,这里我们使用了 database 队列驱动,并且连接的是 MySQL 数据库。在实际开发中,根据自己的需要选择适合的驱动和数据库连接
通过修改 config/queue.php 文件,可以方便地在不同的环境中进行队列配置,例如在本地开发环境和生产环境中使用不同的队列驱动程序。此外,您还可以添加新的队列连接选项,以便在代码中指定不同的队列连接。
例如:
'connections' => [
// ...
'database' => [
'driver' => 'database',
'table' => 'gkb_sis_jobs',
'queue' => 'default',
'retry_after' => 90,
'after_commit' => false,
'connection' => 'business',
],
],
示例参数说明:
1.driver: 指定队列驱动程序为 database。
2.table: 指定存储队列任务的表名。
3.queue: 指定要处理的队列名称。如果未指定,则默认为 default 队列。
4.retry_after: 指定队列任务在失败后的重试时间(秒数)。
5.after_commit: 指定在事务提交后才将任务推送到队列。如果将此选项设置为 true,则需要在启用队列时使用事务。
6.connection: 指定使用的数据库连接。如果未指定,则使用默认数据库连接。
需要注意的是,通过 config/queue.php 文件中的设置,您可以为不同的队列连接指定不同的队列驱动程序、队列名称、最大尝试次数等选项。如果您的应用程序需要使用多个队列连接,那么可以在该文件中为每个连接指定不同的配置选项。然后在代码中,可以使用 onConnection 方法来指定要使用的队列连接,还使用 onQueue 方法来指定要使用的队列名称。
例如:
Emails::dispatch($EmailData)->onConnection('database')->onQueue('Emails');
在这个示例中,我们将任务分发到 database 队列连接的 Emails 队列中。
定义任务
定义任务是使用队列的关键。在 Laravel 中,任务通常是一个可序列化的 PHP 对象,该对象包含需要执行的任务的代码和数据。
可以使用 Artisan 命令来生成任务类:
php artisan make:job Emails
生成的任务类位于 app/Jobs 目录中,可以根据需要修改其中的 handle 方法来定义任务执行的逻辑。例如:
<?php
namespace App\Jobs;
use App\Common\Email;
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\Log;
class Emails implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $EmailData;
/**
* 创建一个新的任务实例
* @param array $EmailData 发送邮件数据
* @return void
*/
public function __construct($EmailData)
{
$this->EmailData = $EmailData;
}
/**
* 运行任务
*
* @return void
*/
public function handle(){
$mailer = Email::sendMailer($this->EmailData);
if($mailer['error']){
Log::channel('EmailData')->info($mailer['error']);
}else{
Log::channel('EmailData')->info('邮件发送成功----'.json_encode($this->EmailData));
}
}
/**
* 任务未能处理
*/
public function failed(\Exception $exception){
Log::channel('EmailData')->info('邮件发送失败----'.json_decode($this->EmailData));
}
}
在这个例子中,我们定义了一个 Emails 任务,该任务需要发送邮件给指定的邮箱地址。任务类实现了 ShouldQueue 接口,表明该任务需要通过队列执行。
handle 方法是任务的主要逻辑,这里我们调用了 Email 类中 sendMailer 方法来处理发送邮件的逻辑
分发任务
当定义好任务之后,需要将任务分发到队列中。Laravel 提供了多种方式来分发任务,下面介绍其中两种常见的方式:
同步任务
在开发环境中,我们可能需要同步执行任务,以便进行调试和测试。可以使用 dispatch 方法来同步执行任务。
例如:
Emails::dispatch($EmailData);
这里我们将 Emails 任务分发到队列中,该任务将同步执行。可以通过访问页面或查看日志来查看任务执行结果。
异步任务
在生产环境中,我们通常需要将任务分发到队列中异步处理。可以使用 dispatch 方法来异步执行任务。
例如:
Emails::dispatch($EmailData)->onConnection('database')->onQueue('Emails');
这里我们将 Emails 任务分发到 emails 队列中,并指定了 database 队列连接和 Emails 队列名称。
启动 Queue Worker 进程
定义好任务处理器并分发任务之后,我们需要启动 Queue Worker 进程来监听队列中的任务。在终端中使用如下命令启动 Queue Worker 进程:
php artisan queue:work database --queue=Emails
如果您要在后台运行队列进程,可以使用 nohup 命令,例如:
nohup php artisan queue:work database --queue=Emails &
使用 php artisan queue:work 命令,那么队列代码库中有任何更改都要重启队列,重启命令:
先查看队列进程:ps -ef|grep queue
杀死进程:kill PID
在后台启动: nohup php artisan queue:work database --queue=Emails &
以上命令将启动一个 Queue Worker 进程,并开始监听队列中的任务。如果队列中有任务,Queue Worker 进程会自动获取任务并调用相应的处理器进行处理。
其他命令
除了启动 Queue Worker 进程,Laravel 还提供了多种其他命令来管理队列。
例如:
php artisan queue:listen:启动一个监听器,监听队列中的任务,并在任务可用时处理任务。
php artisan queue:retry [id]:重新处理一个失败的任务。
php artisan queue:failed:列出所有失败的任务。
php artisan queue:flush:清空队列中的所有任务。
需要注意的是,队列处理器是长生命周期的进程,并将启动的应用程序状态存储在内存中。因此,在启动它们之后,代码库中的更改对其不起作用。因此,在部署过程中,一定要重新启动你的队列处理器。此外,请记住,应用程序创建或修改的任何静态状态不会在任务之间自动重置。或者,你可以运行 queue:listen 命令。在使用 queue:listen 命令时,当你想要重新加载更新的代码或重置应用程序状态时,你不必手动重新启动 worker;但是,这个命令的效率不如 queue:work。
注意
laravel 执行 php artisan 命令,之后导致 artisan 生成的日志文件,用户组是 root,导致 web 方式(用户属主:www)执行的代码无法去写入相应的日志文件
在 Laravel 中,你可以使用 config/logging.php 文件来配置日志文件路径和文件名,以及其他相关的日志选项。你可以在该文件中设置 permission 选项来指定日志文件的权限,例如
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single','error'],
'ignore_exceptions' => false,
'permission' => 0777,
],
]
这样,在 Laravel 中生成的日志文件权限就会自动设置为 0777,从而解决该问题。