You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel+Vue SPA中SSE阻塞其他HTTP请求的解决方法

解决Laravel SSE长连接阻塞HTTP请求的问题

问题根源

Laravel默认的会话机制会在请求启动时锁定会话存储(比如文件),直到请求结束才释放锁。SSE是持续保持的长连接,会一直占用这个锁,导致后续所有需要会话的HTTP请求都被阻塞,处于等待锁释放的状态,表现为请求冻结无法完成。

解决方案

1. 手动释放SSE路由的会话锁

在SSE控制器方法的最开始,手动保存并释放会话锁,让后续请求可以正常获取会话资源。这是最直接有效的方案,适用于SSE连接不需要持续持有会话的场景。

示例代码:

use Illuminate\Support\Facades\Session;

public function sse()
{
    // 保存当前会话数据并释放锁
    Session::save();
    // 也可以用辅助函数:session()->save();

    return response()->stream(function () {
        while (true) {
            // 检查新评论逻辑
            $newComments = \App\Models\Comment::where('ticket_id', request()->ticket_id)
                ->where('created_at', '>', now()->subSeconds(3))
                ->get();

            if ($newComments->isNotEmpty()) {
                echo "data: " . json_encode($newComments) . "\n\n";
                ob_flush();
                flush();
            }

            // 休眠降低CPU占用
            sleep(2);

            // 检测客户端断开连接,终止循环
            if (connection_aborted()) {
                break;
            }
        }
    }, 200, [
        'Content-Type' => 'text/event-stream',
        'Cache-Control' => 'no-cache',
        'Connection' => 'keep-alive',
    ]);
}

2. 给SSE路由禁用会话中间件

如果SSE连接完全不需要访问会话数据(比如身份验证已通过令牌等其他方式处理),可以直接移除该路由的会话相关中间件,从根源避免锁占用。

示例路由定义:

// 移除包含会话逻辑的web中间件,以及会话专属中间件
Route::get('/tickets/{ticket}/comments/sse', [CommentController::class, 'sse'])
    ->withoutMiddleware(['web', 'auth.session']);

注意:若需验证用户身份,可保留auth中间件但移除auth.session,或改用API令牌验证替代会话验证。

3. 优化会话驱动(辅助方案)

如果使用默认的file会话驱动,文件锁的阻塞问题会更明显。可以将会话驱动切换为redis或database,这类驱动的锁机制更高效,能减少长连接带来的阻塞影响。修改.env文件:

SESSION_DRIVER=redis

注意事项

  • 若SSE连接过程中需要再次访问会话数据,需重新调用Session::start()获取会话,但尽量避免这种场景,保持SSE连接轻量化。
  • 务必在循环中加入休眠(sleep()),避免服务器CPU占用过高。
  • 检测connection_aborted()确保客户端断开连接时终止循环,及时释放服务器资源。

内容的提问来源于stack exchange,提问作者Church

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:30:19