当前位置: 首页 > 后端技术 > PHP

回忆一次Laravel应用性能调优的经历

时间:2023-03-29 21:23:31 PHP

这是事后总结。在经历了多次调优过程中的坑之后,我们最终完善并实施了初步的性能测试方案,并通过真实的测试数据总结了Laravel开发过程中的一些实用技巧。0x00起源于同事最近反映Laravel写的应用程序响应有点慢,20多个并发跑到满CPU...为了解决慢的问题,甚至写了一些接口在节点中。而我的第一反应是一个流行的框架怎么会这么不堪?用法肯定有问题。为了一探究竟,我开启了这段Laravel应用性能调优之旅。0x01调优技巧本次性能测试方案中使用的优化技巧主要是基于Laravel框架本身及其提供的工具。关闭应用debugapp.debug=false缓存配置信息phpartisanconfig:cache缓存路由信息phpartisanrouter:cacheclassmap加载优化phpartisanoptimizeautoload优化composerdumpautoloadonlyloadnecessarymiddlewareasneeded使用just-in-time编译器(JIT),如:HHVM、OPcacheusingPHP7.x除了上述优化技术外,还有许多编码实践可以提高Laravel应用程序的性能,本文不再赘述。(也可以关注我的后续文章)1.关闭应用程序调试打开应用程序根目录下的.env文件,将debug设置为false。APP_DEBUG=false2。缓存配置信息phpartisanconfig:cache运行上述命令将config文件夹下的所有配置信息合并到一个bootstrap/cache/config.php文件中,减少运行时加载的文件数量。phpartisanconfig:clear运行上面的命令清除配置信息的缓存,即删除bootstrap/cache/config.php文件3.缓存路由信息phpartisanroute:cache运行上面的命令生成文件bootstrap/缓存/routes.php。路由缓存可以有效提高路由器的注册效率,在大规模应用中效果更加明显。phpartisanroute:clear运行上面的命令会清空路由缓存,即删除bootstrap/cache/routes.php文件。4、类映射加载优化phpartisanoptimize--force运行上述命令可以将常用加载的类合并到一个文件中,通过减少文件加载来提高运行效率。该命令会生成bootstrap/cache/compiled.php和bootstrap/cache/services.json两个文件。需要合并的类可以通过修改config/compile.php文件来添加。在生产环境中,不需要指定--force参数文件,可以自动生成。phpartisanclear-compiled运行上面的命令会清除classmap加载优化,即删除bootstrap/cache/compiled.php和bootstrap/cache/services.json文件。5.自动加载优化composerdumpautoload-oLaravel应用程序是使用composer构建的。此命令会将PSR-0和PSR-4转换为类映射以提高类加载速度。注意:此操作已在phpartisanoptimize--force命令中完成。6.只加载需要的中间件。Laravel应用程序内置并启用了许多中间件。每个Laravel请求都会加载相关的中间件并生成各种数据。将app/Http/Kernel.php中不需要的中间件(比如session支持)注释掉,可以大大提高性能。7.使用即时编译器HHVM和OPcache无需任何修改即可轻松将您的应用程序性能提高50%或更多。8.使用PHP7.x只能说PHP7.x相比之前的版本在性能上有了很大的提升。好吧,限于你真实的商业环境,这个可能很长一段时间都不会改变,所以我也没说什么。0x02测试计划我们使用简单的Apacheab命令只测试应用程序入口文件,并记录和分析数据。只测试应用的入口文件index.php,访问“/”或“/index.php”返回框架欢迎页面。更全面的性能测试需要测试应用程序的更多接口。使用Apacheab命令。ab-t10-c10{网址}。这条命令的意思是同时发起10个url请求,持续10秒。命令中的具体参数设置需要根据待测服务器的性能进行选择。为避免机器波动造成数据错误,每个测试条件都会多次执行ab命令,并记录命令执行结果,重点关注每秒处理的请求数和请求响应时间,分析剔除异常值。每次测试条件调整时,都需要在浏览器上访问欢迎页面,确保不会因为测试条件的修改而导致访问错误。如果页面访问出错,测试结果就会出错。服务器环境显示,所有脱离特定环境的测试数据都没有意义,只能在类似条件下进行比较。本环境运行在8G内存、2.8GHz处理器、SSD硬盘的Mac上。测试服务器是使用Homestead设置的。虚拟机配置单核CPU,2G内存。服务器的PHP版本为7.1,如无特殊说明,表示开启了OPcache。测试的Laravel应用程序是用5.2版本编写的。app\Http\routes.php中定义了85条路由。测试时,除了虚拟机、终端和固定的浏览器窗口外,没有任何程序会影响本机。以上数据可作为您自己进行测试时的参考。0x03测试流程及数据1.不作任何优化1.1操作根据以下检查项进行相应操作。运行ab-t10-c10http://myurl.com/index.php基本检查item.env文件APP_DEBUG=true不存在bootstrap/cache/config.php不存在bootstrap/cache/routes.php不存在存在bootstrap/cache/compiled.php和bootstrap/cache/services.jsonapp/Http/Kernel.php已打开大部分中间件浏览器访问Laravel应用欢迎页面,保证正常访问1.2数据记录2.关闭应用debug2。1操作在步骤1的基础上,修改.env文件中的APP_DEBUG=false。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。2.2数据记录2.3结果与步骤1的结果对比,发现关闭applicationdebug后,每秒处理请求数从26-34增加到33-35,请求响应时间从300多ms到290ms左右,效果不明显,但确实有一定的提升。注意:这部分与应用中的日志等使用情况有比较大的关系。3、打开缓存配置信息3.1操作在步骤2的基础上,运行phpartisanconfig:cache确认生成了bootstrap/cache/config.php。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。3.2数据记录3.3结果与步骤2的结果对比,发现开启配置信息缓存后,每秒处理请求数从33-35增加到36-38,请求响应时间从大约290毫秒到大约260毫秒。效果不明显。但它确实有一些改进。4、启用缓存路由信息4.1操作在步骤3的基础上,运行phpartisanroute:cache确认生成bootstrap/cache/routes.php。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。4.2数据记录4.3结果与步骤3的结果对比,发现开启路由信息缓存后,每秒处理请求数从36-38个增加到60个左右,请求响应时间从260ms下降到大约160毫秒。效果显着。从TPS来看,提升了70%。5、删除不需要的中间件5.1操作在步骤4的基础上,注释掉不需要的中间件代码。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。注意:我在这个测试中把所有的中间件都注释掉了。在实践中,尽可能只留下必要的中间件。5.2数据记录5.3将结果与步骤4的结果进行对比,发现删除不需要的中间件后,每秒处理请求数从60左右增加到90左右,请求响应时间从160ms下降到110ms左右。效果非常明显,从TPS上来说,提升了50%。6.启用类映射加载优化6.1操作在步骤5的基础上,运行phpartisanoptimize--force确认生成了bootstrap/cache/compiled.php和bootstrap/cache/services.json。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。6.2数据记录6.3与步骤5的结果对比,发现classmap加载优化后,每秒处理请求数从90个增加到110个,请求响应时间从110ms下降到100ms以下,并且效果很明显。7、关闭OPcache7.1在第6步的基础上,关闭PHP的OPcache并重启服务器。使用phpinfo()通过ZendOPcache确认OPcache已关闭。浏览器访问Laravel应用欢迎页面,保证正常访问。运行ab-t10-c10http://myurl.com/index.php。7.2数据记录7.3结果与步骤6的结果对比,发现关闭OPcache后,每秒处理请求数从110个下降到15个,请求响应时间从不到100ms上升到650ms以上。开启和关闭OPcache,数据有数倍的差异。之后重新打开PHP的OPcache,数据又恢复到步骤6的水平。0x04坑踩到1.[LogicException]Unabletoprepareroute[/]forserialization.使用闭包。运行phpartisanroute:cache命令时会报这个错误。原因:在处理路由文件中的“/”时使用了闭包。要运行该命令,路由的具体实现不能使用闭包方式。修改方案:将路由的具体实现放在controller中实现。2.[例外]'Closure'的序列化是不允许的。运行phpartisanroute:cache命令时会报这个错误。原因:路由文件中定义了重复的路由。修改方案:检查路由文件中是否存在重复路由,并进行修改。特别要注意,资源方法很可能会重复它们的方法。3.[RuntimeException]提供的文件名无效。运行phpartisanoptimize--forcenaming会报这个错。原因:加载需要编译的类时没有找到对应的文件。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.FileViewFinder.php第137行中的InvalidArgumentException:未找到视图[welcome]。运行phpartisanconfig:cache后,浏览器访问Laravel应用欢迎页面报这个错误。原因:Laravel应用服务器通过Homestead托管在虚拟机上。而我在虚拟机外运行这个命令,导致生成的config.php中的路径是本地路径,而不是虚拟机上的路径。所以找不到视图文件。修改方案:ssh在虚拟机内部运行命令。0x05实用技能坑也踩过,测试过。下面简单总结一下本次体验的实用技巧。1.有效的Laravel应用优化技巧关闭应用调试app.debug=false缓存配置信息phpartisanconfig:cache缓存路由信息phpartisanrouter:缓存类映射加载优化phpartisan优化(包括autoload优化composerdumpautoload)根据需要只加载必要的中间件并使用即时编译器(JIT),例如:HHVM、OPcache2。写代码时的注意事项路由的具体实现放在controller中。不要定义重复的路由,尤其要注意资源方法。明确各个中间件的作用,删除不必要的中间件引用。0x06下一步的调优技巧和编码注意事项,主要针对框架本身。实际业务逻辑编码中有很多具体的优化技巧,这里不做赘述。后续优化会关注具体的编码实践:使用Memcached存储sessionconfig/session.php使用专业的缓存驱动数据库请求优化为数据集写缓存逻辑合并前端资源Elixir0x07写在最后看网上很多框架性能对比文章和辩论,我也看到了很多简单贴出的数据。这些还不足以窥探真实情况,所以这次我们进行了实践,并在过程中做了详细的记录。为读者在实践过程中提供参考、比较和反思。对本实践有疑问的读者也欢迎提问和评论。话不多说,想了解更多技术干货,请关注微信公众号:up2048。-EOF-推荐阅读LaravelHTTP请求、响应、Laravel思维导图的表单验证LaravelHTTP路由、中间件、Laravel思维导图的控制器Laravel核心概念Laravel思维导图Laravel入门指南Laravel思维导图