性能调优高负载Apache服务器

我期待了解一些服务器性能问题,我看到一个(对我们来说)重负载的Web服务器。 环境如下:

  • Debian Lenny(所有稳定的软件包+修补安全更新)
  • Apache 2.2.9
  • PHP 5.2.6
  • 亚马逊EC2大型实例

我们所看到的行为是,networking通常会感觉到响应,但是稍微延迟一点就可以开始处理请求 – 有时候会有一小部分时间,有时甚至是2-3秒。 服务器上的实际负载被报告为非常高 – 通常为10.xx或20.xx,如上所报告的。 此外,在这些时间(甚至是vi )在服务器上运行其他事情是非常缓慢的,所以负载肯定在那里。 奇怪的是,阿帕奇保持非常敏感,除了最初的延迟。

我们使用prefork来configurationApache如下:

 StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 150 MaxRequestsPerChild 0 

KeepAlive为:

 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5 

查看服务器状态页面,即使在这些负载很重的时候,我们也很less触及客户端上限,通常服务于80-100个请求,其中许多处于保持活动状态。 这告诉我排除最初的请求缓慢“等待处理程序”,但我可能是错的。

Amazon CloudWatch监控告诉我,即使我们的操作系统报告的负载大于15,我们的实例CPU利用率也在75-80%之间。

top示例输出:

 top - 15:47:06 up 31 days, 1:38, 8 users, load average: 11.46, 7.10, 6.56 Tasks: 221 total, 28 running, 193 sleeping, 0 stopped, 0 zombie Cpu(s): 66.9%us, 22.1%sy, 0.0%ni, 2.6%id, 3.1%wa, 0.0%hi, 0.7%si, 4.5%st Mem: 7871900k total, 7850624k used, 21276k free, 68728k buffers Swap: 0k total, 0k used, 0k free, 3750664k cached 

大部分stream程看起来像:

 24720 www-data 15 0 202m 26m 4412 S 9 0.3 0:02.97 apache2 24530 www-data 15 0 212m 35m 4544 S 7 0.5 0:03.05 apache2 24846 www-data 15 0 209m 33m 4420 S 7 0.4 0:01.03 apache2 24083 www-data 15 0 211m 35m 4484 S 7 0.5 0:07.14 apache2 24615 www-data 15 0 212m 35m 4404 S 7 0.5 0:02.89 apache2 

从上面同时输出vmstat例子:

 procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- rb swpd free buff cache si so bi bo in cs us sy id wa 8 0 0 215084 68908 3774864 0 0 154 228 5 7 32 12 42 9 6 21 0 198948 68936 3775740 0 0 676 2363 4022 1047 56 16 9 15 23 0 0 169460 68936 3776356 0 0 432 1372 3762 835 76 21 0 0 23 1 0 140412 68936 3776648 0 0 280 0 3157 827 70 25 0 0 20 1 0 115892 68936 3776792 0 0 188 8 2802 532 68 24 0 0 6 1 0 133368 68936 3777780 0 0 752 71 3501 878 67 29 0 1 0 1 0 146656 68944 3778064 0 0 308 2052 3312 850 38 17 19 24 2 0 0 202104 68952 3778140 0 0 28 90 2617 700 44 13 33 5 9 0 0 188960 68956 3778200 0 0 8 0 2226 475 59 17 6 2 3 0 0 166364 68956 3778252 0 0 0 21 2288 386 65 19 1 0 

最后,从Apache的server-status输出:

 Server uptime: 31 days 2 hours 18 minutes 31 seconds Total accesses: 60102946 - Total Traffic: 974.5 GB CPU Usage: u209.62 s75.19 cu0 cs0 - .0106% CPU load 22.4 requests/sec - 380.3 kB/second - 17.0 kB/request 107 requests currently being processed, 6 idle workers C.KKKW..KWWKKWKW.KKKCKK..KKK.KKKK.KK._WK.KKKKKKK.KRKK..CCK KCK.WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK... KK_KWKKKWKCKCWKK.KKKCK.......................................... ................................................................ 

从我有限的经验中,我得出以下结论/问题:

  • 我们可能会允许太多的KeepAlive请求

  • 我确实看到在vmstat中等待IO的时间虽然不一致,不是很多(我想呢?),所以我不确定这是一个大问题,我对vmstat的经验不足

  • 同样在vmstat中,我在一些迭代中看到了许多等待被服务的进程,这是我的networking服务器上的初始页面加载延迟的原因,可能是错误的

  • 我们提供了静态内容(75%或更高)和脚本内容的混合,脚本内容通常是处理器密集型的,因此在两者之间find适当的平衡是重要的。 从长远来看,我们希望将静态位置移动到其他位置,以优化两台服务器,但是我们的软件目前还没有准备好

如果任何人有任何想法,我很乐意提供更多的信息,另外需要注意的是,这是一个高可用性的生产环境,所以我在调整之后要小心谨慎,这就是为什么我没有玩过KeepAlive价值我自己呢。

我会首先承认我没有太多关于在云中运行的东西 – 但是根据我在其他地方的经验,我会说这个web服务器configuration反映了相当低的stream量。 runqueue如此之大意味着没有足够的CPU来处理它。 runqueue还有什么?

我们可能会允许太多的KeepAlive请求

不,keeplive仍然能够提高性能,现代浏览器在知道何时stream水线以及什么时候并行运行请求方面非常聪明,虽然5秒的超时时间还是相当长,而且还有很多服务器正在等待 -我得到了巨大的延迟问题,我build议把它降低到2-3。 这应该会缩短运行时间。

如果你还没有在networking服务器上安装mod_deflate,那么我build议你这样做,然后把ob_gzhandler()添加到你的PHP脚本中。 你可以做一个自动预备:

 if(!ob_start("ob_gzhandler")) ob_start(); 

(是的,copression使用更多的CPU – 但是您应该通过让服务器跑出运行速度更快/处理更less的TCP数据包来节省CPU总量,而且您的站点也更快)。

我build议在MaxRequestsPerChild上设置一个上限 – 比如说500.如果你有内存泄漏的地方,这只允许一些进程的更新。 你的httpd进程看起来很大 – 确保你已经删除了你不需要的任何apache模块,并确保你提供了良好的caching信息的静态内容。

如果你仍然看到问题,那么问题可能是在PHP代码(如果你切换到使用fastCGI,这应该是显而易见的,没有任何重大的性能损失)。

更新

如果静态内容在不同页面上变化很大,那么也许值得尝试一下:

 if (count($_COOKIE)) { header('Connection: close'); } 

也在PHP脚本上。

你应该考虑安装一个asynchronous的反向代理,因为W状态下的许多进程也是相当高的。 你的Apache进程似乎花费了大量的时间发送内容,以减缓networking被阻塞的客户端。 作为Apache服务器前端的Nginx或Lighttpd可以显着减less许多处于W状态的进程。 是的,你应该限制一些keepalive请求。 可能值得尝试closureskeepalive。

顺便说一句,阿帕奇的进程太高,22 rps,我只能使用5个Apache进程服务100-120 rps。 下一步可能是分析你的应用程序。

你的vmstat中有两行显示你的CPU等待时间相当高,而且在这些行中,你做了相当数量的写操作(io-bo)和上下文切换。 我会看看什么是写块,以及如何消除等待。 我认为可以在改善磁盘IO方面find最大的改进。 检查系统日志 – 将其设置为写入asynchronous。 确保你的控制器的写caching正在工作(检查它 – 你可能有一个坏的电池)。

Keepalive不会导致您的性能问题,如果您没有在前面运行caching,它可以节省连接设置的时间。 你可能会碰撞MaxSpareServers一点点,所以在紧缩时你不会等待所有的叉子。

你应该考虑把keepalive作为第一次尝试…

与107请求处理我会保持MaxSpareServers更高,然后你设置…

恕我直言,在长期的nginx作为静态内容的反向代理应予以考虑

第一个build议:禁用keepalives。 当我能够确定性能提高的特定情况时,我只需要它,但通常请求/秒随Keepalive启用而降低。

第二个build议:设置一个MaxRequestsPerChild。 我在这里回应symcbean,它会帮助在内存泄漏的情况下进行翻转。 500是一个很好的起点。

第三条build议:增加MaxClients。 这是一个球场计算(物理内存 – 非httpd进程使用的内存)/每个httpd进程的大小。 根据httpd的编译方式,这个数字最大值为255,我用公共服务器的250来处理google / yahoo / MS爬行系统。

build议:增加MaxSpareServers:类似于4-5x MinSpareServers。

抨击那些失败的build议,我会考虑使用反向代理或DB的memcache负载平衡。