Laravel 12 使用 RabbitMQ 作为消息队列驱动

Laravel 12 使用 RabbitMQ 作为消息队列驱动

在 Laravel 12 中使用 RabbitMQ 作为消息队列驱动需要安装额外的包,因为 Laravel 默认不包含 RabbitMQ 驱动。以下是完整的配置和使用指南:

安装依赖包

安装 RabbitMQ PHP 客户端和 Laravel 队列适配器:

composer require php-amqplib/php-amqplib
composer require vladimir-yuldashev/laravel-queue-rabbitmq

配置环境变量

.env 文件中添加 RabbitMQ 连接信息:

QUEUE_CONNECTION=rabbitmq

RABBITMQ_HOST=127.0.0.1
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest
RABBITMQ_VHOST=/

配置队列连接

config/queue.php 中添加 RabbitMQ 连接配置:

'connections' => [
    // ... 其他连接配置
    
    'rabbitmq' => [
        'driver' => 'rabbitmq',
        'queue' => env('RABBITMQ_QUEUE', 'default'),
        'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,
        
        'hosts' => [
            [
                'host' => env('RABBITMQ_HOST', '127.0.0.1'),
                'port' => env('RABBITMQ_PORT', 5672),
                'user' => env('RABBITMQ_USER', 'guest'),
                'password' => env('RABBITMQ_PASSWORD', 'guest'),
                'vhost' => env('RABBITMQ_VHOST', '/'),
            ],
        ],
        
        'options' => [
            'ssl_options' => [
                'cafile' => env('RABBITMQ_SSL_CAFILE', null),
                'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
                'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
                'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
                'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
            ],
            'queue' => [
                'job' => VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
            ],
        ],
        
        /*
         * 设置工作队列参数
         */
        'worker' => env('RABBITMQ_WORKER', 'default'),
        
        // 高级交换机配置
        'exchange' => [
            'name' => env('RABBITMQ_EXCHANGE_NAME', 'laravel_exchange'),
            'type' => env('RABBITMQ_EXCHANGE_TYPE', 'direct'), // direct, topic, fanout, headers
            'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
            'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
            'auto_delete' => env('RABBITMQ_EXCHANGE_AUTO_DELETE', false),
        ],
        
        // 高级队列配置
        'queue_params' => [
            'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
            'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
            'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
            'auto_delete' => env('RABBITMQ_QUEUE_AUTO_DELETE', false),
            'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS', '[]'),
        ],
        
        // 绑定配置
        'bindings' => [
            [
                'queue' => env('RABBITMQ_QUEUE', 'default'),
                'routing_key' => env('RABBITMQ_ROUTING_KEY', 'default.key'),
            ],
        ],
    ],
],

创建队列任务

php artisan make:job ProcessOrder

编辑 app/Jobs/ProcessOrder.php

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessOrder implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $orderData;

    public function __construct(array $orderData)
    {
        $this->orderData = $orderData;
    }

    public function handle()
    {
        // 处理订单逻辑
        \Log::info('Processing order: ' . json_encode($this->orderData));
        
        // 模拟任务处理
        sleep(2);
        
        \Log::info('Order processed successfully');
    }

    // 任务失败处理
    public function failed(\Throwable $exception)
    {
        \Log::error('Order processing failed: ' . $exception->getMessage());
    }
}

分发任务到 RabbitMQ

在控制器中分发任务:

use App\Jobs\ProcessOrder;

// 分发到默认队列
ProcessOrder::dispatch([
    'order_id' => 12345,
    'customer' => 'John Doe',
    'amount' => 99.99
]);

// 分发到指定队列
ProcessOrder::dispatch([
    'order_id' => 67890,
    'customer' => 'Jane Smith',
    'amount' => 149.99
])->onQueue('priority_orders');

// 延迟分发任务(10分钟后执行)
ProcessOrder::dispatch([
    'order_id' => 54321,
    'customer' => 'Bob Johnson',
    'amount' => 49.99
])->delay(now()->addMinutes(10));

启动队列 Worker

# 监听默认队列
php artisan queue:work rabbitmq

# 监听指定队列
php artisan queue:work rabbitmq --queue=priority_orders,default

# 带有重试机制的 Worker
php artisan queue:work rabbitmq --tries=3 --timeout=30

# 使用多个 Worker 进程
php artisan queue:work rabbitmq --queue=priority_orders --tries=3 --timeout=30 &
php artisan queue:work rabbitmq --queue=default --tries=3 --timeout=30 &

生产环境使用 Supervisor

创建 /etc/supervisor/conf.d/laravel-rabbitmq.conf

[program:laravel-rabbitmq-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/your-project/artisan queue:work rabbitmq --sleep=3 --tries=3 --max-jobs=1000
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/your-project/storage/logs/worker.log
stopwaitsecs=60

管理 Supervisor:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-rabbitmq-worker:*

高级配置选项

交换机类型

.env 中配置不同的交换机类型:

# 直连交换机(默认)
RABBITMQ_EXCHANGE_TYPE=direct

# 主题交换机(支持通配符匹配)
RABBITMQ_EXCHANGE_TYPE=topic

# 扇出交换机(广播到所有队列)
RABBITMQ_EXCHANGE_TYPE=fanout

# 头交换机(基于消息头路由)
RABBITMQ_EXCHANGE_TYPE=headers

死信队列配置

添加死信队列支持:

'queue_params' => [
    'arguments' => [
        'x-dead-letter-exchange' => 'dead_letters',
        'x-dead-letter-routing-key' => 'dead_letter_key',
    ],
],

// 单独配置死信队列
'dead_letter_queue' => [
    'name' => 'dead_letters',
    'exchange' => 'dead_letters',
    'routing_key' => 'dead_letter_key',
],

优先级队列

配置优先级队列:

'queue_params' => [
    'arguments' => [
        'x-max-priority' => 10, // 设置优先级范围 (1-255)
    ],
],

分发优先级任务:

ProcessOrder::dispatch($data)->onQueue('high_priority')->rabbitmqPriority(10);

监控 RabbitMQ

使用 RabbitMQ 管理插件(默认端口 15672):

# 启用管理插件
RABBITMQ_MANAGEMENT=1

# 自定义管理端口
RABBITMQ_MANAGEMENT_PORT=15672

在浏览器中访问:http://your-server:15672

常见问题解决

连接问题

  1. 无法连接 RabbitMQ

    • 检查防火墙设置:sudo ufw allow 5672/tcp
    • 验证 RabbitMQ 服务状态:sudo systemctl status rabbitmq-server
    • 检查用户权限:sudo rabbitmqctl list_users
  2. SSL 连接问题

    RABBITMQ_SSL_VERIFY_PEER=false
    

性能优化

  1. 预取计数

    php artisan queue:work rabbitmq --prefetch=10
    
  2. 禁用序列化模型

    // 在任务类中
    public $preserveModel = false;
    
  3. 批量处理消息

    php artisan queue:work rabbitmq --batch=100
    

高级使用场景

延迟消息队列

配置延迟队列插件:

# 启用 RabbitMQ 延迟消息插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

.env 中配置:

RABBITMQ_EXCHANGE_TYPE=x-delayed-message
RABBITMQ_EXCHANGE_ARGUMENTS={"x-delayed-type":"direct"}

分发延迟消息:

ProcessOrder::dispatch($data)
    ->delay(now()->addMinutes(30))
    ->onQueue('delayed_queue');
RPC 模式(请求-响应)

创建 RPC 任务:

class RpcProcessOrder implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $correlationId;

    public function __construct(public array $orderData)
    {
        $this->correlationId = Str::uuid()->toString();
    }

    public function handle()
    {
        // 处理逻辑...
        return ['status' => 'success'];
    }
}

发起 RPC 请求并等待响应:

use VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue;

$response = app(RabbitMQQueue::class)->rpc(
    new RpcProcessOrder($data),
    'rpc_queue',
    30 // 超时时间(秒)
);

完整控制器示例

namespace App\Http\Controllers;

use App\Jobs\ProcessOrder;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function createOrder(Request $request)
    {
        $data = $request->validate([
            'customer' => 'required|string',
            'items' => 'required|array',
            'total' => 'required|numeric'
        ]);
        
        $orderId = uniqid('ORD_');
        
        // 分发订单处理任务
        ProcessOrder::dispatch([
            'order_id' => $orderId,
            'customer' => $data['customer'],
            'items' => $data['items'],
            'total' => $data['total'],
            'timestamp' => now()->toDateTimeString()
        ])->onQueue('order_processing');
        
        // 分发后续通知任务
        ProcessOrder::dispatch([
            'order_id' => $orderId,
            'customer' => $data['customer'],
            'action' => 'send_confirmation'
        ])->delay(now()->addMinutes(5))
        ->onQueue('notifications');
        
        return response()->json([
            'status' => 'pending',
            'message' => 'Order is being processed',
            'order_id' => $orderId
        ]);
    }
}

总结

通过以上配置,您可以在 Laravel 12 中成功使用 RabbitMQ 作为消息队列驱动。RabbitMQ 提供了强大的消息路由、持久化、确认机制和高级消息模式,非常适合需要高可靠性和复杂消息处理场景的应用。

关键优势:

  • 支持多种交换机类型和路由模式
  • 消息持久化和确认机制
  • 优先级队列和延迟消息
  • 死信队列和消息重试
  • 高吞吐量和分布式处理能力

对于生产环境,建议:

  1. 使用 Supervisor 管理 Worker 进程
  2. 配置 RabbitMQ 集群实现高可用
  3. 启用 TLS 加密传输
  4. 实施合理的队列监控和警报
  5. 定期进行队列性能测试和优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值