# Laravel 集成消息队列完整指南

Laravel 提供了优雅的消息队列系统，支持多种队列驱动，让异步任务处理变得简单。以下是 Laravel 集成消息队列的详细方案。

## 一、队列驱动选择

Laravel 原生支持以下队列驱动：

1. **Database** - 使用数据库作为队列存储
2. **Redis** - 高性能内存队列
3. **Beanstalkd** - 轻量级专用队列服务
4. **Amazon SQS** - AWS 托管队列服务
5. **RabbitMQ** - 通过第三方包支持

## 二、配置消息队列

### 1. 安装配置

```bash
# 安装依赖（以Redis为例）
composer require predis/predis
```

配置 `.env` 文件：
```ini
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
```

### 2. 创建任务

```bash
php artisan make:job ProcessPodcast
```

生成的任务类位于 `app/Jobs/ProcessPodcast.php`：

```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 ProcessPodcast implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $podcast;

    /**
     * 创建新任务实例
     */
    public function __construct($podcast)
    {
        $this->podcast = $podcast;
    }

    /**
     * 执行任务
     */
    public function handle()
    {
        // 处理播客...
        logger()->info('Processing podcast: '.$this->podcast->title);
    }
}
```

## 三、使用队列

### 1. 分发任务

```php
use App\Jobs\ProcessPodcast;
use App\Models\Podcast;

// 基本分发
ProcessPodcast::dispatch($podcast);

// 延迟分发（60秒后执行）
ProcessPodcast::dispatch($podcast)->delay(now()->addSeconds(60));

// 指定队列
ProcessPodcast::dispatch($podcast)->onQueue('processing');
```

### 2. 运行队列 worker

```bash
# 启动基础worker
php artisan queue:work

# 指定队列和连接
php artisan queue:work --queue=high,default --tries=3

# 守护进程模式（生产环境推荐）
php artisan queue:work --daemon
```

## 四、高级功能

### 1. 队列优先级

```php
// 在任务类中设置
public $queue = 'high';
```

或分发时指定：
```php
ProcessPodcast::dispatch($podcast)->onQueue('high');
```

### 2. 失败处理

创建失败任务表：
```bash
php artisan queue:failed-table
php artisan migrate
```

在任务类中定义失败处理：
```php
public function failed(Throwable $exception)
{
    // 发送失败通知...
}
```

查看失败任务：
```bash
php artisan queue:failed
```

重试失败任务：
```bash
php artisan queue:retry all
```

### 3. 队列监控

使用 Horizon（Redis专属）：
```bash
composer require laravel/horizon
php artisan horizon
```

## 五、生产环境部署

### 1. Supervisor 配置

安装 Supervisor：
```bash
sudo apt-get install supervisor
```

创建配置文件 `/etc/supervisor/conf.d/laravel-worker.conf`：
```ini
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/your/project/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/path/to/your/project/storage/logs/worker.log
```

启动 Supervisor：
```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
```

### 2. 性能优化建议

1. 根据服务器核心数设置 `numprocs`（通常为CPU核心数的2-3倍）
2. 对于CPU密集型任务，减少并发进程数
3. 使用 `--memory` 参数限制内存使用
4. 定期重启 worker 防止内存泄漏：
   ```ini
   ; 在Supervisor配置中添加
   stopwaitsecs=3600
   ```

## 六、不同驱动对比

| 驱动       | 优点                      | 缺点                     | 适用场景               |
|-----------|--------------------------|-------------------------|----------------------|
| Database  | 无需额外服务，简单        | 性能最低                | 小流量，开发环境      |
| Redis     | 高性能，Laravel最佳支持   | 需要Redis服务器         | 大多数生产环境        |
| Beanstalk | 轻量级，专用队列服务      | 需要单独安装            | 需要简单队列系统      |
| SQS       | 完全托管，无需运维        | AWS依赖，有额外成本     | AWS环境应用          |
| RabbitMQ  | 功能全面，企业级          | 配置复杂                | 复杂消息路由需求      |

## 七、最佳实践

1. **任务设计原则**：
   - 保持任务小巧专注
   - 避免在任务构造函数中处理业务逻辑
   - 任务应具有幂等性（可重复执行不产生副作用）

2. **错误处理**：
   ```php
   // 在任务类中
   public $tries = 3;
   public $backoff = [60, 120, 300];
   ```

3. **批量处理**：
   ```php
   // 使用批次
   $batch = Bus::batch([
       new ProcessPodcast($podcast1),
       new ProcessPodcast($podcast2),
   ])->then(function (Batch $batch) {
       // 所有任务成功完成...
   })->catch(function (Batch $batch, Throwable $e) {
       // 首个任务失败...
   })->dispatch();
   ```

4. **队列隔离**：
   - 将耗时任务与即时任务分开队列
   - 为失败率高的任务设置专门队列

通过以上配置，您可以在 Laravel 应用中高效地集成消息队列系统，实现异步任务处理，提升应用性能和用户体验。