这是一份事后的总结。在经历了调优过程踩的很多坑之后,我们最终完善并实施了初步的性能测试方案,通过真实的测试数据归纳出了 Laravel 开发过程中的一些实践技巧。
0x00 源起
最近有同事反馈 Laravel 写的应用程序响应有点慢、20几个并发把 CPU 跑满... 为了解决慢的问题,甚至一部分接口用 nodejs 来写。
而我的第一反应是一个流行的框架怎么可能会有这么不堪?一定是使用上哪里出现了问题。为了一探究竟,于是开启了这次 Laravel 应用性能调优之旅。
0x01 调优技巧
这次性能测试方案中用到的优化技巧主要基于 Laravel 框架本身及其提供的工具。
关闭应用debug
app.debug=false
缓存配置信息
php artisan config:cache
缓存路由信息
php artisan router:cache
类映射加载优化
php artisan optimize
自动加载优化
composer dumpautoload
根据需要只加载必要的中间件
使用即时编译器(JIT),如:HHVM、OPcache
使用 PHP 7.x
除了以上优化技巧之外,还有很多编码上的实践可以提升 Laravel 应用性能,在本文中暂时不会做说明。(也可以关注我的后续文章)
1. 关闭应用 debug
打开应用根目录下的 .env 文件,把 debug 设置为 false。
APP_DEBUG=false
2. 缓存配置信息
php artisan config:cache
运行以上命令可以把 config 文件夹里所有配置信息合并到一个 bootstrap/cache/config.php
文件中,减少运行时载入文件的数量。
php artisan config:clear
运行以上命令可以清除配置信息的缓存,也就是删除 bootstrap/cache/config.php
文件
3. 缓存路由信息
php artisan route:cache
运行以上命令会生成文件 bootstrap/cache/routes.php
。路由缓存可以有效的提高路由器的注册效率,在大型应用程序中效果越加明显。
php artisan route:clear
运行以上命令会清除路由缓存,也就是删除 bootstrap/cache/routes.php
文件。
4. 类映射加载优化
php artisan optimize --force
运行以上命令能够把常用加载的类合并到一个文件中,通过减少文件的加载来提高运行效率。这个命令会生成 bootstrap/cache/compiled.php
和 bootstrap/cache/services.json
两个文件。
通过修改 config/compile.php
文件可以添加要合并的类。
在生产环境中不需要指定 --force
参数文件也可以自动生成。
php artisan clear-compiled
运行以上命令会清除类映射加载优化,也就是删除 bootstrap/cache/compiled.php
和 bootstrap/cache/services.json
两个文件。
5. 自动加载优化
composer dumpautoload -o
Laravel 应用程序是使用 composer 来构建的。这个命令会把 PSR-0 和 PSR-4 转换为一个类映射表来提高类的加载速度。
注意:
php artisan optimize --force
命令里已经做了这个操作。
6. 根据需要只加载必要的中间件
Laravel 应用程序内置了并开启了很多的中间件。每一个 Laravel 的请求都会加载相关的中间件、产生各种数据。在 app/Http/Kernel.php
中注释掉不需要的中间件(如 session 支持)可以极大的提升性能。
7. 使用即时编译器
HHVM 和 OPcache 都能轻轻松松的让你的应用程序在不用做任何修改的情况下,直接提高 50% 或者更高的性能。
8. 使用 PHP 7.x
只能说 PHP 7.x 比起之前的版本在性能上有了极大的提升。
嗯,限于你的真实企业环境,这个也许很长时间内改变不了,算我没说。
0x02 测试方案
我们使用简单的 Apache ab 命令仅对应用入口文件进行测试,并记录和分析数据。
仅对应用的入口文件 index.php 进行测试,访问 “/” 或者 “/index.php” 返回框架的欢迎页面。更全面的性能测试需要针对应用的更多接口进行测试。
使用 Apache ab 命令。
ab -t 10 -c 10 {url}
。该命令表示对 url 同时发起 10 个请求,并持续 10 秒钟。命令中具体的参数设置需要根据要测试的服务器性能进行选择。为了避免机器波动导致的数据错误,每种测试条件会执行多次 ab 命令,并记录命令执行结果,重点关注每秒处理的请求数及请求响应时间,分析并剔除异常值。
每次对测试条件进行了调整,需要在浏览器上对欢迎页进行访问,确保没有因为测试条件修改而访问出错。如果页面访问出错会导致测试结果错误。
服务器环境说明
所有脱离具体环境的测试数据都没有意义,并且只有在相近的条件下才可以进行比较。
这套环境运行在 Mac 上,内存 8G,处理器 2.8GHz,SSD 硬盘。
测试服务器是使用 Homestead 搭建的。虚拟机配置为单核 CPU、2G 内存。
服务器 PHP 版本为 7.1,未特殊说明,则标识开启了 OPcache。
测试的 Laravel 应用程序采用 5.2 版本编写。
app\Http\routes.php
中定义了 85 个路由。测试过程中除了虚拟机、终端及固定的浏览器窗口外,没有会影响机器的程序运行。
以上的数据,大家在自己进行测试时可以参考。
0x03 测试过程及数据
1. 未做任何优化
1.1 操作
按照以下检查项执行相应的操作。
运行
ab -t 10 -c 10 http://myurl.com/index.php
基础检查项
.env 文件中
APP_DEBUG=true
不存在
bootstrap/cache/config.php
不存在
bootstrap/cache/routes.php
不存在
bootstrap/cache/compiled.php
和bootstrap/cache/services.json
app/Http/Kernel.php
中开启了大部分的中间件浏览器访问 Laravel 应用程序欢迎页确保正常访问
1.2 数据记录
2. 关闭应用debug
2.1 操作
在步骤 1 基础上修改 .env 文件中
APP_DEBUG=false
。浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
2.2 数据记录
2.3 对比结果
与步骤 1 结果比较发现:关闭应用 debug 之后,每秒处理请求数从 26-34 上升到 33-35,请求响应时间从 大部分 300ms 以上下降到 290ms 左右,效果不太明显,但确实有一定的提升。
注意:这部分与应用中的日志等使用情况有比较大的关联。
3. 开启缓存配置信息
3.1 操作
在步骤 2 基础上,运行
php artisan config:cache
,确认生成bootstrap/cache/config.php
。浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
3.2 数据记录
3.3 对比结果
与步骤 2 结果比较发现:开启配置信息缓存之后,每秒处理请求数从 33-35 上升到 36-38,请求响应时间从 290ms 左右下降到 260ms 左右,效果不太明显,但确实有一定的提升。
4. 开启缓存路由信息
4.1 操作
在步骤 3 基础上,运行
php artisan route:cache
,确认生成bootstrap/cache/routes.php
。浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
4.2 数据记录
4.3 对比结果
与步骤 3 结果比较发现:开启路由信息缓存之后,每秒处理请求数从 36-38 上升到 60 左右,请求响应时间从 260ms 下降到 160ms 左右,效果显著,从 TPS 看,提升了 70%。
5. 删除不必要的中间件
5.1 操作
在步骤 4 基础上,注释掉不必要的中间件代码。
浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
注意:这次测试中我注释掉了所有的中间件。实际情况中应该尽量只留下必要的中间件。
5.2 数据记录
5.3 对比结果
与步骤 4 结果比较发现:删除了不必要的中间件之后,每秒处理请求数从 60 左右上升到 90 左右,请求响应时间从 160ms 下降到 110ms 左右,效果非常明显,从 TPS 看,提升了 50%。
6. 开启类映射加载优化
6.1 操作
在步骤 5 基础上,运行
php artisan optimize --force
,确认生成bootstrap/cache/compiled.php
和bootstrap/cache/services.json
。浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
6.2 数据记录
6.3 对比结果
与步骤 5 结果比较发现:做了类映射加载优化之后,每秒处理请求数从 90 上升到 110,请求响应时间从 110ms 下降到 100ms 以下,效果还是比较明显的。
7. 关闭 OPcache
7.1 操作
在步骤 6 基础上,关闭 PHP 的 OPcache,并重启服务器。通过 phpinfo() 的 Zend OPcache 确认 OPcache 已经关闭。
浏览器访问 Laravel 应用程序欢迎页确保正常访问。
运行
ab -t 10 -c 10 http://myurl.com/index.php
。
7.2 数据记录
7.3 对比结果
与步骤 6 结果比较发现:关闭 OPcache 之后,每秒处理请求数从 110 下降到 15,请求响应时间从 100ms 以下上升到 650ms 以上。开启与关闭 OPcache,数据上竟有几倍的差别。
此后,我重新开启了 PHP 的 OPcache,数据恢复到步骤 6 水平。
0x04 踩过的坑
1. [LogicException] Unable to prepare route [/] for serialization. Uses Closure.
在运行 php artisan route:cache
命令时报这个错误。
原因:路由文件中处理“/”时使用了闭包的方式。要运行该命令,路由的具体实现不能使用闭包方式。
修改方案:将路由的具体实现放到控制器中来实现。
2. [Exception] Serialization of 'Closure' is not allowed.
在运行 php artisan route:cache
命令时报这个错误。
原因:路由文件中定义了重复的路由。
修改方案:排查路由文件中的重复路由并修改。尤其要注意 resource
方法很可能导致与其方法重复。
3. [RuntimeException] Invalid filename provided.
在运行 php artisan optimize --force
命名时报这个错误。
原因:在加载需要编译的类时没有找到相应的文件。5.2 版本的 vendor/laravel/framework/src/Illuminate/Foundation/Console/Optimize/config.php
中定义了要编译的文件路径,但不知道为什么 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/ActiveRecords.php
没有找到,所以报了这个错误。
修改方案:暂时注释掉了以上 config.php 中的 ../ActiveRecords.php
一行。
4. InvalidArgumentException in FileViewFinder.php line 137: View [welcome] not found.
在运行 php artisan config:cache
之后,浏览器上访问 Laravel 应用程序欢迎页报这个错误。
原因:Laravel 应用程序服务器是通过 Homestead 在虚拟机上搭建的。而这个命令我是在虚拟机之外运行的,导致生成的 config.php 中的路径是本机路径,而不是虚拟机上的路径。所以无法找到视图文件。
修改方案:ssh 到虚拟机内部运行该命令。
0x05 实践技巧
坑也踩了,测试也做过了。这里针对这次经历做个实践技巧的简单总结。
1. 有效的 Laravel 应用程序优化技巧
关闭应用debug
app.debug=false
缓存配置信息
php artisan config:cache
缓存路由信息
php artisan router:cache
类映射加载优化
php artisan optimize
(包含自动加载优化composer dumpautoload
)根据需要只加载必要的中间件
使用即时编译器(JIT),如:HHVM、OPcache
2. 编写代码时注意事项
路由的具体实现放到控制器中。
不定义重复的路由,尤其注意
resouce
方法。弄清各中间件的作用,删除不必要的中间件引用。
0x06 下一步
以上的调优技巧及编码注意事项主要针对框架本身,在真正的业务逻辑编码中有很多具体的优化技巧,在此没有讨论。
后续的优化重点将会放在具体编码实践上:
使用 Memcached 来存储会话 config/session.php
使用专业的缓存驱动器
数据库请求优化
为数据集书写缓存逻辑
前端资源合并 Elixir
0x07 写在最后
网上看到很多框架性能对比的文章与争论,也看到很多简单贴出了数据。这些都不足以窥探真实的情况,所以有了我们这次的实践,并在过程中做了详实的记录。在各位读者实践过程中提供参考、比较、反思之用。对于这次实践有疑问的读者,也欢迎提出问题和意见。
以上是Laravel框架性能调优方法 的详细内容。更多信息请关注PHP中文网其他相关文章!

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

SublimeText3汉化版
中文版,非常好用

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),