深入浅出Symfony2 - 如何提高网站响应速度
简介
Symfony2是一个基于PHP语言的Web开发框架,有着开发速度快、性能高等特点。但Symfony2的学习曲线也比较陡峭,没有经验的初学者往往需要一些练习才能掌握其特性。相对其他框架,Symfony2比较吸引人的特点有:
1 支持DI(Dependency Injection,依赖注入)和IoC(Inversion of control)。
2 高性能。
3 扩展性强。
4 文档成熟、拥有成熟的社区支持。
本文通过对一个基于Symfony2框架所开发的网站页面进行逐步优化,最终实现页面加载速度的提高的例子,向读者介绍Symfony2框架的一些核心功能和特点。通过阅读本文,你可以通过一些具体的例子了解Symfony2框架的优秀特性和技术特点,从而体会到使用Symfony2框架可以为网站开发带来的各种优势。
适合人群
l 本文适用于希望提高PHP语言的开发技术,或者对Symfony2框架有兴趣的读者。
l 本文也适用于系统架构师和各类技术决策者。
1.Symfony2的运行环境的设置
在我所演示的项目中,已经包含了一个页面,通过输入这个地址来打开它:dev.php/testpage_1。出现的页面如下图所示:
我们打开浏览器自带的调试功能,然后刷新页面:
可以看到,该页面充斥着大量的js/css/图片文件,而整个页面的加载速度竟然达到了9.6秒。
而如果打开这个页面:page1,出现的页面如下图所示:
我们发现页面的加载速度变成了4秒,同时众多js和css文件被各自合并成为了两个单独的文件(图中红框的部分)。
造成上面两个页面打开速度截然不同的原因在于:如果通过不同的入口文件(app.php和appdev.php)进入页面,Symfony2会根据入口文件的不同,切换到不同的运行环境。比如在默认配置中:通过app.php访问的页面,就是生产环境,而通过appdev.php访问的页面,则是开发环境。Symfony2根据运行环境的不同,运行程序时的配置也会不同。比如细心的读者可能会发现,开发环境中页面的下方多了一条像是工具栏一样的东西(这是Symfony2特有的开发调试栏)。环境的不同会影响Symfony2程序运行的各个环节,以下列举了一些比较重要的不同配置下的差异处:
功能
开发环境
生产环境
-----
-----
-----
开发调试栏
会出现
不会出现
日志
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
记录详细的程序执行信息
只在程序出现错误的时候记录
css/js合并
不会
会
所以可以看出,css/js文件合并其实是Symfony2自动根据环境不同所开启或关闭的一个自带功能罢了,这个功能在Symfony2中叫做Assets管理,当然我们也可以通过控制入口文件来实现开启或者关闭其他更多的功能。
通过Symfony2的环境配置功能开启或关闭各种自带功能就像在文本里改一个参数那么简单,而每个不同的环境又有一套独立的环境配置。Symfony2提供了大量的参数供用户方便的配置各种功能,通过对不同环境下的各个功能进行配置,可以很方便的设置出一套适合你自己的工作/生产环境。
接下来让我们看看Assets管理模块还能为我们做什么。
2.深入Assets管理
通过对上述页面的分析,我们发现虽然js和css文件合并了,但各自的文件内容却没有经过压缩,两个文件的大小分别是437k和310k,这显然是一个不太合理的数字。但我们可以通过简单的配置,让Assets管理模块帮我们在合并文件的同时对内容也进行压缩。
例如我们选择使用uglifyjs2对js进行压缩,用yuicompressor对css进行压缩。在这些软件已经安装完毕的情况下,只需要修改app/config.yml的以下几行:
assetic:
debug: "%kernel.debug%"
use_controller: false
bundles: ['ScourgenHFS2Demo1Bundle']
java: /usr/bin/java
filters:
cssrewrite: ~
uglifyjs2:
compress: true
mangle: true
bin: /opt/local/bin/uglifyjs
yui_css:
jar: /usr/share/yuicompressor-2.4.7.jar
然后在layout模板中引入js/css的地方分别增加一个过滤器
'@ScourgenHFS2Demo1Bundle/Resources/public/css/public_home.css'
'@ScourgenHFS2Demo1Bundle/Resources/public/css/inner_city_line.css'
filter='?yui_css'
%}
...
'@ScourgenHFS2Demo1Bundle/Resources/public/js/common/title.js'
filter='?uglifyjs2'
%}
我们再执行一下生成Assets的命令:
% php app/console assetic:dump --env=prod
Dumping all prod assets.
Debug mode is off.
03:14:06 [file+] /Users/scourgen/Desktop/InfoQ/
optimize_performance_of_pages_with_symfony2/HeadFirstSymfony2-Demo1/app/../web/css/2ff013f.css
03:14:14 [file+] /Users/scourgen/Desktop/InfoQ/
然后再打开刚才生产环境下的页面,这时会发现刚才的两个css和js文件的大小已经变成了271k和232k,文件内容也已经都变成了经过uglifyjs2和yuicompressor压缩之后的内容。虽然两个文件大小依然很大,但如果考虑到它们在经过gzip压缩后的文件大小只有86k和39k,也应该算是在合理范围之内了。
当然在实际开发中,我们经常会碰到虽然服务端的js/css文件内容修改了,但客户端却保留着旧版本的缓存,导致页面样式和js功能出现问
题
快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题
的情况,而为了解决这个问题,同样可以通过修改配置实现:
#app/config.yml
#将framework的templating改成如下的样子:
…
templating:
assets_version: 1
assets_version_format: %%s?%%s
engines:
- twig
assets_base_urls:
http:
-
-
...
然后为css合并文件指定一个文件名:
'@ScourgenHFS2Demo1Bundle/Resources/public/css/public_home.css'
'@ScourgenHFS2Demo1Bundle/Resources/public/css/inner_city_line.css'
filter='?yui_css'
output='css/a.css'
%}
我们再刷新一下页面,看看发生了什么。
这时刚才两个js和css的URL分别变成了:
l
l
虽然js和css文件的url后面都带上了一个变量(也就是上面所定义的assets_version),而由于URL的不同,客户端将会重新下载这两个文件以避免从缓存中读取旧的版本。但为什么这两个文件的地址会变成serverx.dev呢?
其实这是Assets管理模块的另外一个功能:将它所管理的文件路径变成绝对地址(也就是增加了上面配置文件中的和两个域名)。而且在配置了多个域名的情况下,哪个文件名匹配哪个域名是固定的,不会随机显示造成带宽浪费,而这其实是由它的一套算法实现的。
通过这样的修改,我们也得到了两个益处:
5 当页面的js/css/图片文件很多时,由于这些URL的域名都不一样,可以让浏览器在同一时间并发下载更多的文件,从而加快页面打开的时间(参考:浏览器并发连接数)。
6 由于这些URL的域名和网页所在的域名不一样,所以HTTP头里不会携带cookie信息,能够减少网络带宽,从而实现cookie-free domain。
类似的情况也有很多,在开发中为了实现最佳实践我们往往需要绞尽脑汁,但如果使用Symfony2作为开发框架则会使问题变得非常简单,甚至简单到根本不用写代码,只需要更改几行配置就能实现。
话说回来,在经过这些调整之后,前端的载入速度看起来已经不错了。那么Symfony2是否也可以很方便的调试和优化后端代码?答案是肯定的。接下来我们看一下如何使用Symfony2调试和优化程序的性能。
3.调试和开发工具介绍
调试和优化程序的最基本前提就是:你得知道你的程序在干什么。这句话虽然说得轻巧,但在许多框架面前却很难做到。这些框架在各种高新技术的封装下,代码和程序逻辑也变得十分复杂和臃肿,想要得知你所使用的框架背后到底做了哪些具体的事情、或者想获取程序运行的堆栈和调用信息、以及MySQL/NoSQL/MessageQueue……这些服务的调用和执行情况等等,都是不太容易的。而在没有这些信息支持的情况下,想去对后端程序做调试和优化几乎是不可能的。