最近做了一个项目,提交给性能测试结果如下:

List: TPS =3400
Detail: TPS =480

Detail页面 资源消耗大:  CPU idle75%, Load average:10

服务器配置为8g内存,4cpu,linux 2.6的核,lighttpd+php,本机跑了memcached。另有一台同样配置的服务器跑mysql。

由于对方要求load必须降下来,所以开始调优。

首先分析为什么load会大呢?vmstat查看io和阻塞都不大,但是system cs即上下文切换峰值为万数量级。top看了下内存占用率也正常。而load代表的含义是,cpu中正在执行的进程与等待执行进程的数目。它过大的原因,要不就是进程数太多,要不就是某些进程占用时间片太长。

先从代码入手,把detail静态信息做缓存,动态信息ajax异步加载。但其实测试环境下,mysql数据量并不大,这样优化没啥效果。

第二步,想会不会是lighttpd并发数不够,所以增大了PHP_FCGI_CHILDREN,使总共派生的php-cgi数目达到500.还是没进展,而且貌似偶尔还有小下降。这时查看lighttd的errorlog,发现有mysql too many connection的错误。

第三步,调整mysql的配置,将Max_connections配置到500,wait_timeout配置为1000,即增大可用连接,防止长连接。这时看着有所进步。

第四步,既然我的tps已经达到要求,而load过高,那么调整lighttpd的并发并没有好处,所以仍旧修改php-cgi数目为100。

第五步,将memcached迁移到mysql服务器上,因为该服务器cpu、内存使用都比较低。

再次测试,load降到了4以下!bingo!

ps:记录一些命令

查看cpu信息:grep ‘model name’ /proc/cpuinfo

据说load average的值保持在  Load Average < CPU个数 * 核数 *0.7 比较好!

这里有一篇文章,把load average说的很明白:http://www.gracecode.com/archives/2973/

context switch rate(上下文切换)的说明,节取自:http://blog.csdn.net/marising/archive/2010/01/12/5182771.aspx

就是Process(Thread)的切换,如果切换过多,会让CPU忙于切换,也会导致影响吞吐量。《高性能服务器架构 》这篇文章的第2节就是说的是这个问题的。究竟多少算合适?google了一大圈,没有一个确切的解释。Context Switch大体上由两个部分组成:中断和进程(包括线程)切换,一次中断(Interrupt)会引起一次切换,进程(线程)的创建、激活之类的也会引起一次切换。CS的值也和TPS(Transaction Per Second)相关的,假设每次调用会引起N次CS,那么就可以得出

Context Switch Rate = Interrupt Rate + TPS* N

CSR减掉IR,就是进程/线程的切换,假如主进程收到请求交给线程处理,线程处理完毕归还给主进程,这里就是2次切换。也可以用CSR、IR、TPS的值代入公式中,得出每次事物导致的切换数。因此,要降低CSR,就必须在每个TPS引起的切换上下功夫,只有N这个值降下去,CSR就能降低,理想情况下N=0,但是无论如何如果N >= 4,则要好好检查检查。

对于ligttpd来说,一个请求,先发送至lighttpd,然后交给fastcgi模块(这个模块是编译在ligttpd里的,不知道会不会导致cs切换),最后交给php-cgi,应该最终还会把处理结果返回给lighttpd,从而传送给用户。这样算来,一次请求至少导致2次cs切换。

这个文章不错,存之:http://blog.csdn.net/tianlesoftware/archive/2011/02/21/6198780.aspx

Leave a Reply