使用Silber / bouncer-rc5从laravel 5.7更新到laravel 5.8后检查权限时,时间显着增加

时间:2019-04-24 20:25:41

标签: laravel acl laravel-5.7 laravel-5.8

我正在使用bouncer来满足我的ACL需求,自从将项目从laravel 5.7升级到5.8以来,我注意到处理请求的时间大大增加了。

我正在处理两个模型(我们将它们称为ParentChild),以及经过身份验证的用户对其的权限。

// Takes about 110ms. Eager loads various nested relationships and counters with specific constraints
$parents = Parent::myScope(...)->get();

// Bottleneck. Takes 5 minutes (!). Used to take about 40 seconds on laravel 5.7
$parents->each(function ($parent) {
    $parent->permissions = [
        'edit' => auth()->user()->can('edit', $parent),
        'delete' => auth()->user()->can('delete', $parent),
        'restore' => auth()->user()->can('restore', $parent)
    ];
    $parent->children()->each(function ($child) {
        $child->permissions = [
            'edit' => auth()->user()->can('edit', $child),
            'delete' => auth()->user()->can('delete', $child),
            'restore' => auth()->user()->can('restore', $child)
        ];
    }
}

我要附加这样的权限,因为$parents变量将作为json发送到前端。我很确定这个实现是错误的,并且必须有更好的替代方法,但是真正的问题是加载时间莫名其妙地增加了五倍。

使用Debugbar度量获得时间。

monitor中使用redis-cli命令(我正在使用Redis来缓存权限),我注意到GET请求的发送速度比以前慢。实际上,即使我停止了页面的加载( ESC ),对Redis的GET请求也不会立即停止。我不确定这是否是正常行为。

我试图在保镖仓库中检查问题,但没有发现任何东西。

2 个答案:

答案 0 :(得分:1)

您要拨打auth()->user()数百次。您可以尝试只调用一次吗?

$user = auth()->user();

$parents->each(function ($parent) use ($user) {
    $parent->permissions = [
        'edit' => $user->can('edit', $parent),
        'delete' => $user->can('delete', $parent),
        'restore' => $user->can('restore', $parent)
    ];

    $parent->children()->each(function ($child) {
        $child->permissions = [
            'edit' => $user->can('edit', $child),
            'delete' => $user->can('delete', $child),
            'restore' => $user->can('restore', $child)
        ];
    }
}

此外,由于您渴望加载children,因此您不应在每次循环迭代中再次获取它们:

$parent->children()->each(function ($child) {
//               ^^ remove these parentheses
    $child->permissions = [
        'edit' => $user->can('edit', $child),
        'delete' => $user->can('delete', $child),
        'restore' => $user->can('restore', $child)
    ];
}

答案 1 :(得分:0)

经过一些测试,找到了解决方案。事实证明,代码根本没有问题。

服务器出了点问题。我们不知道确切是什么,但是尝试在新安装的计算机上运行项目摆脱了那些糟糕的处理时间。 (现在的时间是在首次请求时15秒)

从laravel 5.7迁移到5.8之后,服务器的问题碰巧变得更糟,这导致了我的追逐。

添加

罪魁祸首是Xdebug。我们用它来进行代码覆盖率分析,但是性能太差了,最终还是切换到了phpdbg。