PHP任务队列:RabbitMQ、Gearman和Redis
在现代PHP Web应用程序中,经常需要在不阻塞用户主线程的情况下执行耗时或资源密集型操作。发送邮件群发、生成报告、处理图片、处理视频——所有这些任务最好异步地在后台执行。为此,存在任务队列(job queues)——这些机制允许您延迟任务执行,并通过工作进程(worker)稍后处理。
在本文中,我们将介绍三种流行的PHP任务队列工具:RabbitMQ、Gearman和Redis。您将了解在何种情况下使用它们,并看到代码示例。
为什么需要任务队列?
使用任务队列的主要优势:
- 异步性——用户无需等待繁重操作完成。
- 可扩展性——您可以启动多个工作进程进行并行处理。
- 容错性——如果工作进程崩溃,任务仍保留在队列中,稍后会被处理。
- 职责分离——任务发送代码与任务处理代码松散耦合。
1. RabbitMQ——强大的消息代理
RabbitMQ是一个完整的消息代理,支持AMQP协议。它提供可靠投递、路由、确认等功能。适用于高负载的复杂系统。
在PHP中使用RabbitMQ需要扩展php-amqplib。
安装
composer require php-amqplib/php-amqplib示例:发送任务
<?phprequire_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\\Connection\\AMQPStreamConnection;use PhpAmqpLib\\Message\\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');$channel = $connection->channel();
$channel->queue_declare('email_queue', false, true, false, false);
$data = json_encode(['email' => 'user@example.com', 'subject' => '你好!']);$msg = new AMQPMessage($data, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
$channel->basic_publish($msg, '', 'email_queue');echo "任务已发送到队列";
$channel->close();$connection->close();示例:工作进程(处理器)
<?phprequire_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\\Connection\\AMQPStreamConnection;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');$channel = $connection->channel();
$channel->queue_declare('email_queue', false, true, false, false);
$callback = function ($msg) { $data = json_decode($msg->body, true); echo "正在向 {$data['email']} 发送主题为 '{$data['subject']}' 的邮件"; // 此处为实际发送邮件 $msg->ack(); // 确认处理};
$channel->basic_qos(null, 1, null);$channel->basic_consume('email_queue', '', false, false, false, false, $callback);
while ($channel->is_consuming()) { $channel->wait();}2. Gearman——分布式任务系统
Gearman专注于分布式任务处理。它允许在远程服务器上或后台调用函数。非常适合微服务架构。
PHP有扩展gearman(PECL)。
安装
sudo apt install gearman-job-serverpecl install gearman示例:客户端(发送任务)
<?php$client = new GearmanClient();$client->addServer('127.0.0.1', 4730);
$result = $client->doBackground('send_email', json_encode([ 'email' => 'user@example.com', 'subject' => '你好!']));
echo "任务已发送