使用 silber/bouncer-rc5 从 laravel 5.7 更新到 laravel 5.8 后检查权限时明显增加了时间
Noticeable time increase when checking permissions after updating from laravel 5.7 to laravel 5.8 using silber/bouncer-rc5
我正在使用 bouncer 来满足我的 ACL 需求,自从将我的项目从 laravel 5.7 升级到 5.8 后,我注意到处理请求所需的时间显着增加。
我正在处理两个模型(我们称它们为 Parent
和 Child
),以及经过身份验证的用户对它们的权限。
// 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
措施获得的。
使用 redis-cli
中的 monitor
命令(我使用 Redis
来缓存权限),我注意到 GET 请求比以前更慢。事实上,即使我停止加载页面 (ESC),对 Redis 的 GET 请求也不会立即停止。我不确定这是否是正常行为。
我试图检查 bouncer 回购中的问题,但我没有找到任何东西。
您给 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)
];
}
经过一些测试,找到了解决方案。事实证明,代码完全没有问题。
服务器出了点问题。我们不知道究竟是什么,但试图 运行 新安装的机器上的项目摆脱了那些可怕的处理时间。 (现在第一次请求时间为 15 秒)
从 laravel 5.7 迁移到 5.8 后,服务器的问题巧合地变得更糟,这让我无所事事。
附录
罪魁祸首是 Xdebug。我们用它来进行代码覆盖率分析,但性能太差了,我们最终改用了 phpdbg。
我正在使用 bouncer 来满足我的 ACL 需求,自从将我的项目从 laravel 5.7 升级到 5.8 后,我注意到处理请求所需的时间显着增加。
我正在处理两个模型(我们称它们为 Parent
和 Child
),以及经过身份验证的用户对它们的权限。
// 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
措施获得的。
使用 redis-cli
中的 monitor
命令(我使用 Redis
来缓存权限),我注意到 GET 请求比以前更慢。事实上,即使我停止加载页面 (ESC),对 Redis 的 GET 请求也不会立即停止。我不确定这是否是正常行为。
我试图检查 bouncer 回购中的问题,但我没有找到任何东西。
您给 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)
];
}
经过一些测试,找到了解决方案。事实证明,代码完全没有问题。
服务器出了点问题。我们不知道究竟是什么,但试图 运行 新安装的机器上的项目摆脱了那些可怕的处理时间。 (现在第一次请求时间为 15 秒)
从 laravel 5.7 迁移到 5.8 后,服务器的问题巧合地变得更糟,这让我无所事事。
附录
罪魁祸首是 Xdebug。我们用它来进行代码覆盖率分析,但性能太差了,我们最终改用了 phpdbg。