Laravel进度用WebSocket吗

wen PHP项目 18

本文目录导读:

Laravel进度用WebSocket吗

  1. 为什么推荐WebSocket?
  2. Laravel中的WebSocket方案
  3. 不使用WebSocket的备选方案
  4. 实际应用示例:文件上传进度
  5. 决策建议
  6. 最佳实践

在Laravel中,实现实时进度更新推荐使用WebSocket,但并非必须,以下是详细的方案对比和实现建议:

为什么推荐WebSocket?

实时性要求

  • WebSocket:全双工通信,服务器可主动推送进度数据
  • HTTP轮询:需要客户端反复请求,延迟高且浪费资源

典型场景

  • 文件上传/处理进度
  • 长时间运行的任务(导出、批量操作)
  • 实时数据同步

Laravel中的WebSocket方案

Laravel Reverb(推荐,Laravel 10+)

// 1. 安装
composer require laravel/reverb
// 2. 配置广播
// config/broadcasting.php
'connections' => [
    'reverb' => [
        'driver' => 'reverb',
        'key' => env('REVERB_APP_KEY'),
        'secret' => env('REVERB_APP_SECRET'),
        'app_id' => env('REVERB_APP_ID'),
        'options' => [
            'host' => env('REVERB_HOST'),
            'port' => env('REVERB_PORT'),
        ],
    ],
],
// 3. 创建事件
php artisan make:event TaskProgress
// 4. 事件类
class TaskProgress implements ShouldBroadcast
{
    public $progress;
    public $taskId;
    public function __construct($taskId, $progress)
    {
        $this->taskId = $taskId;
        $this->progress = $progress;
    }
    public function broadcastOn()
    {
        return new Channel('task.'.$this->taskId);
    }
}
// 5. 触发更新
event(new TaskProgress($taskId, 50));

Laravel WebSockets(第三方包)

composer require beyondcode/laravel-websockets

Pusher(第三方服务)

// .env
PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-key
PUSHER_APP_SECRET=your-secret
PUSHER_APP_CLUSTER=mt1
// 使用
event(new TaskProgress($taskId, 75));

不使用WebSocket的备选方案

Server-Sent Events (SSE)

// 路由
Route::get('/progress/{taskId}', function ($taskId) {
    return response()->stream(function () use ($taskId) {
        while (true) {
            $progress = Cache::get("task_$taskId", 0);
            echo "data: $progress\n\n";
            ob_flush();
            flush();
            if ($progress >= 100) break;
            usleep(500000); // 0.5秒
        }
    }, 200, [
        'Content-Type' => 'text/event-stream',
        'Cache-Control' => 'no-cache',
        'Connection' => 'keep-alive',
    ]);
});

HTTP轮询(简单但不推荐)

// 前端每2秒查询一次
setInterval(async () => {
    const response = await fetch(`/api/task/${taskId}/progress`);
    const data = await response.json();
    updateProgress(data.progress);
}, 2000);

实际应用示例:文件上传进度

HTML + JavaScript

<!-- 使用Socket.IO客户端 -->
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:8080');
// 监听进度更新
socket.on('upload.progress', (data) => {
    const progressBar = document.getElementById('progress');
    progressBar.style.width = data.percent + '%';
    progressBar.textContent = data.percent + '%';
});
// 上传文件
async function uploadFile(file) {
    const formData = new FormData();
    formData.append('file', file);
    const response = await fetch('/upload', {
        method: 'POST',
        body: formData
    });
}
</script>

Laravel后端

// 控制器
class UploadController extends Controller
{
    public function upload(Request $request)
    {
        $file = $request->file('file');
        $taskId = uniqid();
        // 模拟长时间处理
        for ($i = 0; $i <= 100; $i += 10) {
            sleep(1); // 模拟处理时间
            // 广播进度
            broadcast(new TaskProgress($taskId, $i));
        }
        return response()->json(['taskId' => $taskId]);
    }
}

决策建议

场景 推荐方案 理由
新项目(Laravel 10+) Reverb 官方支持,性能好,易于集成
已有Pusher账号 Pusher 节省服务器资源,无需维护
简单进度展示 SSE 实现简单,无需额外服务
实时性要求不高 轮询 最简方案,但效率低

最佳实践

  1. 小规模应用:使用Reverb + Laravel Echo
  2. 高并发场景:考虑Redis + WebSocket集群
  3. 移动端优化:WebSocket比轮询省电90%
  4. 安全性:使用Laravel认证中间件保护WebSocket连接

对于实时进度更新,WebSocket是最优选择,Laravel Reverb提供了开箱即用的解决方案,推荐在新项目中使用。

抱歉,评论功能暂时关闭!