上线清单 —— 20 个 Laravel 应用性能优化项

file

让我们开始吧!假若你的 laravel 应用已经投入生产环境中。

从第一个用户,到第十,第一百,直到成千上万的用户!慢慢地,随着用户越多,你的网站会越来越慢

那我们应该如何做?细节决定成败

经过一番搜索,我决定写下这20个使你网站提升速度的小提示

我将从基础开始,大部分都是可以瞬间完成的操作。然后,我将逐步提高难度。最后,就是更高级的内容了。如果你跟着我的步骤一步一步来,我相信你的网站会得到质的提升。

享受你的学习之旅!如果你有什么建议,可以在下方留言!我很高兴跟大家共同探讨。

基础的优化项

让我们看看我们能够在短短几秒钟内做些什么。

1. 路由缓存

每次服务器执行请求时,都会注册所有的路由,这会花费一些时间。但是,你可以选择缓存路由列表来跳过这个步骤。

缓存路由列表是非常简单的。你需要做的是在部署应用程序后,执行下面的这个命令:

php artisan route:cache

但是,如果你添加或修改了任意一个路由信息,请不要忘记清除之前的缓存以及重新执行缓存命令。

php artisan route:clear

# 然后,再次执行
php artisan route:cache

注意,这只对控制器类路由有效。

2. 缓存配置

就如路由一样,你同样可以在应用中缓存配置文件。

设想一下这种场景:每次你发送一个请求到 App 中,Laravel 都需要去加载不同的配置文件,并且要去打开.env 文件读取其中的内容。这种方式性能低下,是不?

不过不用担心,这里有个 Artisan 命令专治这个。

php artisan config:cache

你在部署之后可以使用它。和路由差不多,别忘了编辑东西的时候清理一下缓存。

php artisan config:clear

# 然后,再来一次...
php artisan config:cache

3. 优化 Composer 自动加载

通常,Composer 生成自动加载文件非常快。但是,在生产环境中,如果设置了PSR-4 和 PSR-0 自动加载规则,这可能会变慢。

您可以通过将下面命令添加到部署脚本来优化自动加载器文件创建过程。

$  composer dump-autoload  -o

不要忘记它。

4. 谣言:「不要大量使用 Blade 视图」

这个谣言我都听到头大了。

"千万不要大量使用 Blade 视图,因为它会使得应用性能降低!"

彻头彻尾的大谎言!认真脸!

铭记这个:Laravel 编译 Blade 视图。编译就是说,在流程结束时,你将拥有一个已编译的完整文件,而非使用多个文件。

所以,丝毫不需要担心。


中级干货

5. 换个其他/更好的 Cache/Session 驱动

默认的,当你新建一个 Laravel 项目的时候Cache 和 Sessions 的驱动默认为 「文件」。在本地开发环境和小项目中它没啥问题,但是项目增长时事情就大条了。

所以,考虑下换个更好的驱动例如 Redis。 Laravel 有内置支持它的方式,而你要做的就是 安装 Predis

更多细节在 这里和 此处

6. 尽快升级 Laravel 版本

当新版本发布时,请记得尽快升级 Laravel。这不仅关乎新功能:在可能的情况下,所有贡献者都花时间修复代码库周边的性能问题。

所以,要持续关注并保持代码更新。

7. 删除未使用的服务

这是很多人经常忘记的小技巧,要向自己提问:

"我需要它吗?*

我们知道 Laravel 自带了很多服务,毕竟,这是一个全栈框架,每一个服务都有其用武之地。

所以,请花一些时间检查 config/app.php  文件,看看你是否能找到一个你不需要的服务。如果一切正常,请尝试将其删除并测试您的应用程序。

它应该有所帮助(一点点)!

8. 使用预加载进行查询

如果你知道 Laravel 是什么,你可能也知道预加载是什么。 如果您信息不够及时,预加载是一种通过使用特定语法来减少发送到数据库的查询数量来提高 Eloquent 性能的方法。

此问题称为N + 1查询问题。 让我们举个例子。 你有两个模型:Book 和 Author。 每本 book 都有它的 author。

$books  =  App\Book::all();

foreach  ($books  as  $book)  {
    echo  $book->author->name;
}

想象一下,您的数据库中有1000本书。 现在,此代码将执行 1001 次查询以检索这1000本书的作者姓名。

1(查询以获取1000本书的数据)+ 1000(查询以获取每本书的作者数据)= 1001。

但是,如果你编写这样的代码

$books  =  App\Book::with('author')->get();

foreach  ($books  as  $book)  {
    echo  $book->author->name;
}

更改基础查询以避免此性能问题。 您将只执行两个查询而不是1001! 这是巨大的性能提升。

9. 缓存查询结果

有时候, 缓存一个具体的查询结果可能是一个好主意。

想象这样一个场景:你准备在你的应用主页上展示 “十大专辑” 排行榜。 这项工作是通过从数据库中执行查询完成的(查询可能涉及到artists表以及其他的一些表)。 你的主页访问量是 1000 次/小时 。

如果这个排行榜数据的查询次数是 1000次每小时,那么一天下来执行的查询次数就是24000次。
现在,让我们假设这个排行榜是每小时更新一次 。那么,将每次的查询结果缓存一小时如何 ?

$value  =  Cache::remember('top_10_albums',  60,  function  ()  {
    return  Album::with('artist',  'producer')->getTopTen();
});

这个缓存组件的  remember 方法在未找到缓存的情况下将会先从数据库中获取数据,并缓存60分钟。到期后,将会再次从数据库中获取最新的数据,更新缓存。

查询次数 从 24000 到 24 次/天 。

10. 为你的数据表建立索引

记住,必要的时候请为您的数据表建立索引。 这看起来像是个没什么卵用的提示,但实际上这很有必要。 因为我见过非常多的应用,它们的数据表没有索引。

实现起来很简单,您可以创建一个新的数据库迁移并使用里面的方法来添加索引.

Schema::table('my_table_name',  function(Blueprint  $table){
    $table->index('field_to_be_indexed');
});

当然,索引不是您喜欢在哪建就直接创建一个就是了。您必须研究您的业务、代码和查询,去分析哪里才是最需要索引的地方,然后再建立索引。

11. 中间件太多?

Laravel 会对你注册的中间件进行大量的(前/后)调用。所以,请你仔细检查它们,并且去掉那些你不需要的中间件。

通常中间件列表在 Kernel.php 

12. 是时候使用队列了!

有些时候,Laravel 比预期慢,这时你可以考虑异步执行任务。

最常见的情况就是发送一封欢迎邮件,让我们一起看看任务流程。

  1. 用户填写我们的表单;
  2. 将他/她的详细信息写入数据库;
  3. 发送一封写有欢迎语和确认链接的邮件给他/她;
  4. 并展示感谢页面;

很多时候,这些任务完全是在控制器中并且按照顺序执行。

我的建议是学会如何使用事件和队列,可以将发送邮件任务交给专门的流程,以致于改善用户使用体验。


高级干货

13. 使用 Pusher 改进异步队列

上面我写了一些跟队列有关的内容。有时,你也可以使用队列来改善面向用户的任务。

想象一下,你正在创建一个繁重的(在计算方面)进程,并且希望给用户显示这个任务的进度条。你可以轻松地使用队列的异步任务并集成 Pusher 来向前端发送消息以达到目的,即使这个任务没有完成。

另一个经常使用的示例是向用户发送消息不需要刷新页面。

考虑一下吧!

14. 使用 Logs / Debugbars / Laravel Telescope 测量调试工具

在提升自己方面,有一句我自己非常喜欢的引用。是从我的 CEO (感谢 Massimo !)引用 Peter Drucker 的话那听来的。

如果你无法衡量它,你就无法改进它。

这个概念非常适合 Web 应用程序的上下文。要想改善 Web 应用的请求管理时间,需要测量很多东西。幸运地,我们有许多非常优秀的工具来完成这件事。

  • 慢日志: MYSQL , MariaDB 和其他数据库可以启用慢日志来追踪那些语句花了大量的时间。你可以使用这些数据来判定是否必须更改或优化特定的代码(或查询);

  • Debugbar : Laravel Debugbar 是一个很棒的扩展包。在很多应用程序方面,你可以使用它来收集数据。比如查询,视图,时间等等;

  • Laravel Telescope : 另一个非常酷的工具是 Laravel Telescope ,对 Laravel 应用,有“优雅的调试助手”的美称。如果你感兴趣, 我已经在这里写了一篇关于它的文章

15. 更新你的PHP版本

虽然这看起来很简单,但是如果你的项目够大的话,这执行起来会很麻烦,所以我觉得把这条加入高级技巧里面。

如果你的 PHP 版本在7.0以下,更新你的 PHP 和 laravel 版本。

16. 在服务器上使用 Lumen

如果你的应用程序数据量增长很大,你可以考虑为你的系统做服务拆分了。不过,这并没有一个明确的方法指南来引导你完成它:拆分标准的高与低取决于来自应用程序的领域到拆分所有必需的内容所需的工作中的许多因素。

但是,一旦你拆分成功,你的项目将获得新生。

如果你对这个主题感兴趣的话,可以从  https://medium.com/@munza/large-scale-lara... 开始。

17. 为静态资源提供 CDN 服务

我非常肯定你有很多前端的资源,比如 CSS 文件和 JS 脚本。

你可以通过多种方式来减少发送给用户的数据量:

  • 压缩静态资源;
  • 捆绑静态资源(将多个 CSS 文件或者 JS 脚本合并为一个,以减少请求次数);
  • 开启 gzip 压缩;

然而,如果你遇到大量的流量,则你可以将你的静态资源托管到专用的 CDN 服务器上,比如:

  • Akamai(阿卡迈);
  • Max CDN;
  • Cloudflare;
  • 亚马逊 AWS 服务 (S3 + CloudFront);

译者注:国内可以使用又拍云和七牛云

18. 使用高级测量工具

安装 Laravel Debugbar 或 Telescope 将是一个良好的开端,但对于更重大的项目,这还不够。

你需要选择更高级的工具,如下:

  • New Relic;
  • AppOptics;
  • Datadog;
  • Sentry;

以上列表的应用程序不做同样的事情:他们被设计用于不同目的。花些时间去学习他们以理解他们如何提供帮助。

19. 垂直扩展

你已经对代码的细枝末节都进行了彻底优化,但是你的应用体量在不断增长。迟早你都要进行垂直扩展。

有个简单的说法就是:更多的 RAM,更多的空间,更多的带宽就,以及更多的 CPU

注意这个只是对许多没有足够时间来安排重构/优化的初创公司的通常做法。法子是不错,所以你可以认为这是能让你喘口气的临时解决方案。

20. 水平扩展

水平扩展是另一种扩展的方式,它不同于传统的垂直扩展,主要有两点:

  • 取代在现有配置上增加硬件资源的方式,你可能将会添加更多的功能模块来处理日益增加的流量。 在垂直扩展的环境中,你只需要增加服务器配置就行,但是水平扩展应用就意味着你的应用将会部署运行在不同的机器上,有可能是在一个负载均衡机器或者其他服务之后。这就意味着需要更多的设置和配置;此时事情就没那么简单了;
  • 并非所有的应用都可以在短时间内扩展完毕,有时候你需要重构隔离一些代码;有时候你需要把应用拆分为不同规模的小型服务。

水平扩展会有有很多事情要做,但是一旦你能对应用进行水平扩展时,好处也是超乎想象的。

结论

今天有足够的内容了!我通过合并我的个人经验和以前做过的一些研究创建了在这个列表。

如果你愿意,请尽管提出一些新东西,我很乐意相应更新一下此文章。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:http://francesco.codes/2018/11/18/the-20...

译文地址:https://learnku.com/laravel/t/24559

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 16

mark一波,laravel资深粉丝来了

5年前 评论

大多数优化问题的解决方案:加硬件和带宽,使用CDN优化静态资源,优化表结构和较差的sql查询

5年前 评论

無腦加快取(緩存)其實是相當危險的行為,在啟動任何服務之前應先考量「如果這個服務掛了,對系統本身會不會造成影響」

很多人覺得快取就弄個 Redis 或 Memcached,可以大幅降低資料庫負載。然而當 Redis 或 Memcached 掛點時造成的雪崩常常會讓服務死掉。

5年前 评论
guanhui07

挺赞的

5年前 评论
wenber
  1. 使用 Pusher 改进异步队列
    展示进度条.这个例子好啊.值得尝试下.
5年前 评论

很棒的总结,如果加入swoole加速相关的就好了。

5年前 评论

在服务器上使用 Lumen 也算一项?

5年前 评论

mark 谢谢楼主

5年前 评论
CrazyZard

在Laravel5.8版本的时候 缓存是在到秒的 不再是分了

4年前 评论

@CrazyZard 这个确实方便了不少。

4年前 评论

谢谢分享

4年前 评论

好文章,刚好最近需要。感谢作者,感谢译者~

4年前 评论

学习了 :+1:

2年前 评论

用php artisan optimize替代php artisan route:cache会更好。 但是一旦有更改,就需要重新执行次命令。 无论是代码还是代码对应的项目,只要有缓存,就会存在缓存一致性的问题。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!