nginx和php性能优化相关
2013-04-07 18:14
417 查看
一直以来都是在写hadoop,很少写nginx和php相关的东西了。网上绝大多数文章是优化linux系统参数,优化nginx,php的配置参数等等,尝试写个不同视角的,跟具体技术点关系太大的,主要是思路。
从编译安装nginx和php开始捋一下。
编译nginx和php一个最基本的原则是,尽可能编译更少的附加模块,nginx和php或者更早的apache,为了完成某项特定的功能,会将该功能已动态连接库的形式包含在软件里面,在linux下面是.so后缀的文件。一般来说,用户在configure阶段,可以自己选择--with-xxx或者--without-xxx来决定是否使用它提供的模块。为了方便,我们当然可以这样做,比如我们要在php里面使用curl的函数,就指定--with-curl=/usr/local/curl这种方式去configure。但是,除非这个模块是你必须使用的,否则就不要指定编译它。
原则一:如果不需要这个模块,就不要编译它。
原因是这样,当你启动nginx或者php进程的时候,这些进程都会打开所有你所编译的这些动态连接库,每个动态链接库都会占用linux系统的FD资源,这个用lsof是可以很清楚的看到的。同样,你的log文件也是会占用FD资源。
第二列是进程PID,我这里列了nginx的两个进程,你加载的动态链接库越多,他占用的FD和内存就会越多,而TCP/IP本身每个连接我记得是会占用1.5k左右的内存。所以,尽可能少的加载动态连接库,可以将更多的内存和cpu资源让给tcp/ip连接。
所以,除了必须要用的,尽可能少的指定configure参数是可以提高一些性能的。例如nginx的gzip参数,如果你不是遇到特别大的带宽瓶颈无法逾越,就尽量不要指定使用gzip,他可以减小带宽占用,但同时在高并发情况下会增大CPU的占用,gzip算法挺费CPU时间的。同理,不需要rewrite,就不要加pcre参数,不需要mhash,就不要给php指定mhash参数,以此类推。
原则二:尽可能使用缓存系统
无论是nginx的缓存,还是php的缓存,或者memcached或者redis,除非你遇到客户端刷新问题,否则不要拒绝缓存机制,这在性能优化里是非常有用的,这有点类似于代码重用。代码重用会减少程序员的工作量,而缓存会减少服务器的工作量,关于这方面任何人都没有异议吧。在我的实际工作中,由于不涉及前端工作,所以不怎么去关心memcached和redis。但是我也会尽可能的使用缓存,特别是php的缓存,我主要使用的就是eaccelerator。做一个对比,在不使用eaccelerator的情况下,php开256进程,并发量达到1000多的时候,CPU就已经跑满了,nginx会报出大量的errorlog。而使用了eaccelerator,php并发量达到2000或者更高,cpu也只跑到了一半多一些,nginx还没有报出errorlog。而且有很多优秀的缓存,除了eaccelerator之外,还有xcache等。
原则三:尽可能使用面向过程,而不是面向对象。
其实我这么说可能有点老土了,但是面向过程的确要比面向对象的方式要执行效率高。当然我不否认面向对象在代码重用和构建大型系统上的优势。面向对象的方式要比面向过程在php解释器里面多了好几步流程,而用虚拟机就更慢了。尽管这种区别可能只有几十个cpu微秒时间,但是累计误差是很可怕的一件事。
原则四:好的算法和坏的算法。
对于不是要求特严格的网站来说,其实算法无分好坏,只要能解决问题就行,但是就像原则三里面说到的累积误差。一个不好的算法带来的往往是整体效率的低能。单独跑一个几百几千个数的冒泡和快排的效率差别,可能相差也不过是几个毫秒,十几个毫秒。但是几万个呢,几十万个呢?早期去选择好的算法和书写风格,会让后面的工作轻松很多,代码重构的工作真的又耗精力又耗时间。
原则五:学会用监控。
监控的目的不仅仅是看服务器是不是还活着,这个活着包括服务器活着,也包括上面的服务还活着,这个根本就不是监控的最终目的。服务器和服务是不是还活着,不需要你去监控。群众的眼睛是雪亮的,服务用不了的话,电话早就被打爆了。监控的最终目的是分析出性能的瓶颈所在,然后想办法去调优。无论是图形化的cacti,ganglia,zabbix还是linux下面命令行的iftop,iostat,vmstat,lsof等等,将每台服务器的硬件资源利用率最大化,才是真正的目标所在。咱们毕竟不是国企央企政府机关,可以征收上来的苛捐杂税买一堆oracle,emc在那摆着观赏把玩,剩下的回扣甩给二奶三奶。
当然,这个监控也不仅仅是监控访问量和负载的关系,很多都可以监控,也可以通过前后端的技术来实现,比如在nginx配置里面加上一个参数,可以监控到页面的请求响应时间,或者通过cookie和javascript,可以监控到客户端的实际加载时间等等。不过这些就需要自己写代码实现了。
没事瞎写的,很久不搞web相关的东西了,写起来感觉挺怪的。恩,我开始挂臭袜子了。本文出自 “实践检验真理” 博客,转载请与作者联系!
从编译安装nginx和php开始捋一下。
编译nginx和php一个最基本的原则是,尽可能编译更少的附加模块,nginx和php或者更早的apache,为了完成某项特定的功能,会将该功能已动态连接库的形式包含在软件里面,在linux下面是.so后缀的文件。一般来说,用户在configure阶段,可以自己选择--with-xxx或者--without-xxx来决定是否使用它提供的模块。为了方便,我们当然可以这样做,比如我们要在php里面使用curl的函数,就指定--with-curl=/usr/local/curl这种方式去configure。但是,除非这个模块是你必须使用的,否则就不要指定编译它。
原则一:如果不需要这个模块,就不要编译它。
原因是这样,当你启动nginx或者php进程的时候,这些进程都会打开所有你所编译的这些动态连接库,每个动态链接库都会占用linux系统的FD资源,这个用lsof是可以很清楚的看到的。同样,你的log文件也是会占用FD资源。
[root@collect-crash5-197 Hload]# lsof | grep nginx nginx 14214 nobody cwd DIR 8,9 4096 31623598 /opt/modules/tengine/sbin nginx 14214 nobody rtd DIR 8,2 4096 2 / nginx 14214 nobody txt REG 8,9 3114093 31623599 /opt/modules/tengine/sbin/nginx nginx 14214 nobody mem REG 8,2 143600 65301 /lib64/ld-2.5.so nginx 14214 nobody mem REG 8,2 1722304 65305 /lib64/libc-2.5.so nginx 14214 nobody mem REG 8,2 129984 65356 /lib64/libpcre.so.0.0.1 nginx 14214 nobody mem REG 8,2 145824 65350 /lib64/libpthread-2.5.so nginx 14214 nobody mem REG 8,2 18152 65349 /lib64/libutil-2.5.so nginx 14214 nobody mem REG 8,2 615136 65315 /lib64/libm-2.5.so nginx 14214 nobody mem REG 8,2 85544 65591 /lib64/libz.so.1.2.3 nginx 14214 nobody mem REG 8,2 48600 65346 /lib64/libcrypt-2.5.so nginx 14214 nobody mem REG 8,2 92736 65327 /lib64/libresolv-2.5.so nginx 14214 nobody mem REG 8,3 1262416 4146256 /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so nginx 14214 nobody mem REG 8,2 114352 65623 /lib64/libnsl-2.5.so nginx 14214 nobody mem REG 8,2 23360 65329 /lib64/libdl-2.5.so nginx 14214 nobody mem REG 8,3 120945 4245561 /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/nginx/nginx.so nginx 14214 nobody DEL REG 0,9 1301143625 /dev/zero nginx 14214 nobody mem REG 8,2 53880 65306 /lib64/libnss_files-2.5.so nginx 14214 nobody 0u CHR 1,3 1670 /dev/null nginx 14214 nobody 1u CHR 1,3 1670 /dev/null nginx 14214 nobody 2w REG 8,9 19614456983 31719533 /opt/modules/tengine/logs/error.log nginx 14214 nobody 3w REG 8,17 0 73587637 /data/logs/error5/access.log nginx 14214 nobody 5u unix 0xffff81010f64ec40 1596291379 socket nginx 14214 nobody 7u unix 0xffff810186199480 1596291382 socket nginx 14214 nobody 9u unix 0xffff81010886eec0 1596291384 socket nginx 14214 nobody 10u IPv4 1301143624 TCP *:http (LISTEN) nginx 14214 nobody 11w REG 8,17 0 90475700 /data/logs/errorv/access.log nginx 14214 nobody 12w REG 8,17 0 1507590 /data/logs/errorcode/access.log nginx 14214 nobody 13w REG 8,17 0 73662516 /data/logs/mobile/access.log nginx 14214 nobody 14w REG 8,9 8612894912 31719506 /opt/modules/tengine/logs/access.log nginx 14214 nobody 15w REG 8,9 19614456983 31719533 /opt/modules/tengine/logs/error.log nginx 14214 nobody 16u unix 0xffff81010886fc80 1596291389 socket nginx 14214 nobody 17u unix 0xffff8101185cda00 1596291378 socket nginx 14214 nobody 18r 0000 0,11 0 1596291381 eventpoll nginx 14214 nobody 19u 0000 0,7 0 356 anon_inode nginx 14214 nobody 20u unix 0xffff81010886f440 1596291391 socket nginx 14214 nobody 21u unix 0xffff81011b1d3a00 1596291393 socket nginx 14214 nobody 23u unix 0xffff81013d2c5d00 1596291396 socket nginx 14214 nobody 25u unix 0xffff81013d2c5780 1596291398 socket nginx 14214 nobody 27u unix 0xffff81013d2c5200 1596291402 socket nginx 14214 nobody 29u unix 0xffff81013d2c4c80 1596291404 socket nginx 14214 nobody 31u unix 0xffff81013d2c4700 1596291406 socket nginx 14214 nobody 33u unix 0xffff81013d2c4180 1596291408 socket nginx 14214 nobody 35u unix 0xffff8102020a3940 1596291410 socket nginx 14214 nobody 37u unix 0xffff8102020a33c0 1596291412 socket nginx 14214 nobody 39u unix 0xffff8102020a2e40 1596291415 socket nginx 14215 nobody cwd DIR 8,9 4096 31623598 /opt/modules/tengine/sbin nginx 14215 nobody rtd DIR 8,2 4096 2 / nginx 14215 nobody txt REG 8,9 3114093 31623599 /opt/modules/tengine/sbin/nginx nginx 14215 nobody mem REG 8,2 143600 65301 /lib64/ld-2.5.so nginx 14215 nobody mem REG 8,2 1722304 65305 /lib64/libc-2.5.so nginx 14215 nobody mem REG 8,2 129984 65356 /lib64/libpcre.so.0.0.1 nginx 14215 nobody mem REG 8,2 145824 65350 /lib64/libpthread-2.5.so nginx 14215 nobody mem REG 8,2 18152 65349 /lib64/libutil-2.5.so nginx 14215 nobody mem REG 8,2 615136 65315 /lib64/libm-2.5.so nginx 14215 nobody mem REG 8,2 85544 65591 /lib64/libz.so.1.2.3 nginx 14215 nobody mem REG 8,2 48600 65346 /lib64/libcrypt-2.5.so nginx 14215 nobody mem REG 8,2 92736 65327 /lib64/libresolv-2.5.so nginx 14215 nobody mem REG 8,3 1262416 4146256 /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so nginx 14215 nobody mem REG 8,2 114352 65623 /lib64/libnsl-2.5.so nginx 14215 nobody mem REG 8,2 23360 65329 /lib64/libdl-2.5.so nginx 14215 nobody mem REG 8,3 120945 4245561 /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/auto/nginx/nginx.so nginx 14215 nobody DEL REG 0,9 1301143625 /dev/zero nginx 14215 nobody mem REG 8,2 53880 65306 /lib64/libnss_files-2.5.so nginx 14215 nobody 0u CHR 1,3 1670 /dev/null nginx 14215 nobody 1u CHR 1,3 1670 /dev/null nginx 14215 nobody 2w REG 8,9 19614456983 31719533 /opt/modules/tengine/logs/error.log nginx 14215 nobody 3w REG 8,17 0 73587637 /data/logs/error5/access.log nginx 14215 nobody 5u unix 0xffff810186199480 1596291382 socket nginx 14215 nobody 7u unix 0xffff81010886eec0 1596291384 socket nginx 14215 nobody 9u unix 0xffff81010886fc80 1596291389 socket nginx 14215 nobody 10u IPv4 1301143624 TCP *:http (LISTEN) nginx 14215 nobody 11w REG 8,17 0 90475700 /data/logs/errorv/access.log nginx 14215 nobody 12w REG 8,17 0 1507590 /data/logs/errorcode/access.log nginx 14215 nobody 13w REG 8,17 0 73662516 /data/logs/mobile/access.log nginx 14215 nobody 14w REG 8,9 8612894912 31719506 /opt/modules/tengine/logs/access.log nginx 14215 nobody 15w REG 8,9 19614456983 31719533 /opt/modules/tengine/logs/error.log nginx 14215 nobody 16u unix 0xffff8101185cdcc0 1596291377 socket nginx 14215 nobody 17u unix 0xffff81010886f440 1596291391 socket nginx 14215 nobody 18u unix 0xffff81011b1d3a00 1596291393 socket nginx 14215 nobody 19u unix 0xffff81010886ec00 1596291380 socket nginx 14215 nobody 20r 0000 0,11 0 1596291386 eventpoll nginx 14215 nobody 21u 0000 0,7 0 356 anon_inode nginx 14215 nobody 23u unix 0xffff81013d2c5d00 1596291396 socket nginx 14215 nobody 25u unix 0xffff81013d2c5780 1596291398 socket nginx 14215 nobody 27u unix 0xffff81013d2c5200 1596291402 socket nginx 14215 nobody 29u unix 0xffff81013d2c4c80 1596291404 socket nginx 14215 nobody 31u unix 0xffff81013d2c4700 1596291406 socket nginx 14215 nobody 33u unix 0xffff81013d2c4180 1596291408 socket nginx 14215 nobody 35u unix 0xffff8102020a3940 1596291410 socket nginx 14215 nobody 37u unix 0xffff8102020a33c0 1596291412 socket nginx 14215 nobody 39u unix 0xffff8102020a2e40 1596291415 socket
第二列是进程PID,我这里列了nginx的两个进程,你加载的动态链接库越多,他占用的FD和内存就会越多,而TCP/IP本身每个连接我记得是会占用1.5k左右的内存。所以,尽可能少的加载动态连接库,可以将更多的内存和cpu资源让给tcp/ip连接。
所以,除了必须要用的,尽可能少的指定configure参数是可以提高一些性能的。例如nginx的gzip参数,如果你不是遇到特别大的带宽瓶颈无法逾越,就尽量不要指定使用gzip,他可以减小带宽占用,但同时在高并发情况下会增大CPU的占用,gzip算法挺费CPU时间的。同理,不需要rewrite,就不要加pcre参数,不需要mhash,就不要给php指定mhash参数,以此类推。
原则二:尽可能使用缓存系统
无论是nginx的缓存,还是php的缓存,或者memcached或者redis,除非你遇到客户端刷新问题,否则不要拒绝缓存机制,这在性能优化里是非常有用的,这有点类似于代码重用。代码重用会减少程序员的工作量,而缓存会减少服务器的工作量,关于这方面任何人都没有异议吧。在我的实际工作中,由于不涉及前端工作,所以不怎么去关心memcached和redis。但是我也会尽可能的使用缓存,特别是php的缓存,我主要使用的就是eaccelerator。做一个对比,在不使用eaccelerator的情况下,php开256进程,并发量达到1000多的时候,CPU就已经跑满了,nginx会报出大量的errorlog。而使用了eaccelerator,php并发量达到2000或者更高,cpu也只跑到了一半多一些,nginx还没有报出errorlog。而且有很多优秀的缓存,除了eaccelerator之外,还有xcache等。
原则三:尽可能使用面向过程,而不是面向对象。
其实我这么说可能有点老土了,但是面向过程的确要比面向对象的方式要执行效率高。当然我不否认面向对象在代码重用和构建大型系统上的优势。面向对象的方式要比面向过程在php解释器里面多了好几步流程,而用虚拟机就更慢了。尽管这种区别可能只有几十个cpu微秒时间,但是累计误差是很可怕的一件事。
原则四:好的算法和坏的算法。
对于不是要求特严格的网站来说,其实算法无分好坏,只要能解决问题就行,但是就像原则三里面说到的累积误差。一个不好的算法带来的往往是整体效率的低能。单独跑一个几百几千个数的冒泡和快排的效率差别,可能相差也不过是几个毫秒,十几个毫秒。但是几万个呢,几十万个呢?早期去选择好的算法和书写风格,会让后面的工作轻松很多,代码重构的工作真的又耗精力又耗时间。
原则五:学会用监控。
监控的目的不仅仅是看服务器是不是还活着,这个活着包括服务器活着,也包括上面的服务还活着,这个根本就不是监控的最终目的。服务器和服务是不是还活着,不需要你去监控。群众的眼睛是雪亮的,服务用不了的话,电话早就被打爆了。监控的最终目的是分析出性能的瓶颈所在,然后想办法去调优。无论是图形化的cacti,ganglia,zabbix还是linux下面命令行的iftop,iostat,vmstat,lsof等等,将每台服务器的硬件资源利用率最大化,才是真正的目标所在。咱们毕竟不是国企央企政府机关,可以征收上来的苛捐杂税买一堆oracle,emc在那摆着观赏把玩,剩下的回扣甩给二奶三奶。
当然,这个监控也不仅仅是监控访问量和负载的关系,很多都可以监控,也可以通过前后端的技术来实现,比如在nginx配置里面加上一个参数,可以监控到页面的请求响应时间,或者通过cookie和javascript,可以监控到客户端的实际加载时间等等。不过这些就需要自己写代码实现了。
没事瞎写的,很久不搞web相关的东西了,写起来感觉挺怪的。恩,我开始挂臭袜子了。本文出自 “实践检验真理” 博客,转载请与作者联系!
相关文章推荐
- 使用socket方式连接Nginx优化php-fpm性能
- 使用socket方式连接Nginx优化php-fpm性能
- 使用socket方式连接Nginx优化php-fpm性能
- 使用socket方式连接Nginx优化php-fpm性能
- ubuntu nginx安装及相关linux性能參数优化
- 使用socket方式连接Nginx优化php-fpm性能
- nginx php fastcgi优化相关
- 使用socket方式连接Nginx优化php-fpm性能
- Nginx作为WEB服务相关配置(性能优化,网络连接,访问控制,虚拟主机,https等等)
- nginx,php-fpm性能优化
- php代码优化及php相关问题总结
- Nginx配置性能优化的方法
- Android面试题-与性能优化相关面试题五
- 分享10条PHP性能优化的小技巧,帮助你更好的用PHP开发
- PHP性能优化
- php性能优化:使用 isset()判断字符串长度速度比strlen()更快
- php性能优化
- Nginx高性能web服务器之性能优化(八)
- 高流量站点NGINX与PHP-fpm配置优化