从编译安装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@RHEL-6 ~]# lsof | grep nginx nginx 21075 root rtd DIR 252,3 4096 2 / nginx 21075 root txt REG 252,3 4703968 1581815 /usr/local/nginx/sbin/nginx nginx 21075 root mem REG 252,3 156872 524692 /lib64/ld-2.12.so nginx 21075 root mem REG 252,3 22536 524700 /lib64/libdl-2.12.so nginx 21075 root mem REG 252,3 1918016 524693 /lib64/libc-2.12.so nginx 21075 root mem REG 252,3 145720 524698 /lib64/libpthread-2.12.so nginx 21075 root mem REG 252,3 90952 524695 /lib64/libz.so.1.2.3 nginx 21075 root mem REG 252,3 124624 524710 /lib64/libselinux.so.1 nginx 21075 root mem REG 252,3 113952 524722 /lib64/libresolv-2.12.so nginx 21075 root mem REG 252,3 17256 524725 /lib64/libcom_err.so.2.1 nginx 21075 root mem REG 252,3 386040 524701 /lib64/libfreebl3.so nginx 21075 root mem REG 252,3 43392 524702 /lib64/libcrypt-2.12.so nginx 21075 root mem REG 252,3 46336 524723 /lib64/libkrb5support.so.0.1 nginx 21075 root mem REG 252,3 12592 524657 /lib64/libkeyutils.so.1.3 nginx 21075 root mem REG 252,3 915736 524726 /lib64/libkrb5.so.3.3 nginx 21075 root mem REG 252,3 181632 524724 /lib64/libk5crypto.so.3.1 nginx 21075 root mem REG 252,3 1665328 1338710 /usr/lib64/libcrypto.so.1.0.0 nginx 21075 root mem REG 252,3 272360 524731 /lib64/libgssapi_krb5.so.2.2 nginx 21075 root mem REG 252,3 375352 1338711 /usr/lib64/libssl.so.1.0.0 nginx 21075 root DEL REG 0,4 350933 /dev/zero nginx 21075 root mem REG 252,3 65928 524318 /lib64/libnss_files-2.12.so nginx 21075 root mem REG 252,3 118382 1341679 /usr/local/lib/libpcre.so.0.0.1 nginx 21075 root 0u CHR 1,3 0t0 3661 /dev/null nginx 21075 root 1u CHR 1,3 0t0 3661 /dev/null nginx 21075 root 2w REG 252,3 0 816455 /home/wwwlogs/nginx_error.log nginx 21075 root 3u unix 0xffff88003750d680 0t0 350935 socket nginx 21075 root 4w REG 252,3 0 816455 /home/wwwlogs/nginx_error.log nginx 21075 root 5w REG 252,3 191144 816456 /home/wwwlogs/access.log nginx 21075 root 8w REG 252,3 213550 1581857 /usr/local/nginx/logs/access.log nginx 21075 root 9u IPv4 350932 0t0 TCP *:http (LISTEN) nginx 21075 root 10u unix 0xffff8800376b6980 0t0 350936 socket nginx 21076 www rtd DIR 252,3 4096 2 / nginx 21076 www txt REG 252,3 4703968 1581815 /usr/local/nginx/sbin/nginx nginx 21076 www mem REG 252,3 156872 524692 /lib64/ld-2.12.so nginx 21076 www mem REG 252,3 22536 524700 /lib64/libdl-2.12.so nginx 21076 www mem REG 252,3 1918016 524693 /lib64/libc-2.12.so nginx 21076 www mem REG 252,3 145720 524698 /lib64/libpthread-2.12.so nginx 21076 www mem REG 252,3 90952 524695 /lib64/libz.so.1.2.3 nginx 21076 www mem REG 252,3 124624 524710 /lib64/libselinux.so.1 nginx 21076 www mem REG 252,3 113952 524722 /lib64/libresolv-2.12.so nginx 21076 www mem REG 252,3 17256 524725 /lib64/libcom_err.so.2.1 nginx 21076 www mem REG 252,3 386040 524701 /lib64/libfreebl3.so nginx 21076 www mem REG 252,3 43392 524702 /lib64/libcrypt-2.12.so nginx 21076 www mem REG 252,3 46336 524723 /lib64/libkrb5support.so.0.1 nginx 21076 www mem REG 252,3 12592 524657 /lib64/libkeyutils.so.1.3 nginx 21076 www mem REG 252,3 915736 524726 /lib64/libkrb5.so.3.3 nginx 21076 www mem REG 252,3 181632 524724 /lib64/libk5crypto.so.3.1 nginx 21076 www mem REG 252,3 1665328 1338710 /usr/lib64/libcrypto.so.1.0.0 nginx 21076 www mem REG 252,3 272360 524731 /lib64/libgssapi_krb5.so.2.2 nginx 21076 www mem REG 252,3 375352 1338711 /usr/lib64/libssl.so.1.0.0 nginx 21076 www DEL REG 0,4 350933 /dev/zero nginx 21076 www mem REG 252,3 65928 524318 /lib64/libnss_files-2.12.so nginx 21076 www mem REG 252,3 118382 1341679 /usr/local/lib/libpcre.so.0.0.1 nginx 21076 www 0u CHR 1,3 0t0 3661 /dev/null nginx 21076 www 1u CHR 1,3 0t0 3661 /dev/null nginx 21076 www 2w REG 252,3 0 816455 /home/wwwlogs/nginx_error.log nginx 21076 www 4w REG 252,3 0 816455 /home/wwwlogs/nginx_error.log nginx 21076 www 5w REG 252,3 191144 816456 /home/wwwlogs/access.log nginx 21076 www 8w REG 252,3 213550 1581857 /usr/local/nginx/logs/access.log nginx 21076 www 9u IPv4 350932 0t0 TCP *:http (LISTEN) nginx 21076 www 10u unix 0xffff8800376b6980 0t0 350936 socket nginx 21076 www 11u REG 0,9 0 3659 anon_inode
第二列是进程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,可以监控到客户端的实际加载时间等等。不过这些就需要自己写代码实现了。
转载请注明:爱开源 » nginx和php性能优化相关