性能调优高负载 Apache 服务器

fut*_*eal 13 debian performance-tuning vmstat amazon-ec2 apache-2.2

我希望了解我在(对我们而言)负载较重的 Web 服务器上看到的一些服务器性能问题。环境如下:

  • Debian Lenny(所有稳定包 + 修补安全更新)
  • 阿帕奇 2.2.9
  • PHP 5.2.6
  • Amazon EC2 大型实例

我们看到的行为是,网络通常感觉是响应式的,但开始处理请求会有轻微的延迟——有时是几分之一秒,有时是我们高峰使用时间的 2-3 秒。服务器上的实际负载报告为非常高 - 通常为 10.xx 或 20.xx,如top. 此外,在这些时间(甚至vi)在服务器上运行其他东西非常慢,所以负载肯定在那里。奇怪的是 Apache 仍然非常敏感,除了最初的延迟。

我们使用 prefork 将 Apache 配置如下:

StartServers          5
MinSpareServers       5
MaxSpareServers      10
MaxClients          150
MaxRequestsPerChild   0
Run Code Online (Sandbox Code Playgroud)

和 KeepAlive 为:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
Run Code Online (Sandbox Code Playgroud)

查看服务器状态页面,即使在这些负载很重的时候,我们也很少达到客户端上限,通常处理 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
Run Code Online (Sandbox Code Playgroud)

大多数流程如下所示:

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            
Run Code Online (Sandbox Code Playgroud)

vmstat与上述同时输出的示例:

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   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
Run Code Online (Sandbox Code Playgroud)

最后,来自 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.K.K.KKKKK.K.R.KK..C.C.K
K.C.K..WK_K..KKW_CK.WK..W.KKKWKCKCKW.W_KKKKK.KKWKKKW._KKK.CKK...
KK_KWKKKWKCKCWKK.KKKCK..........................................
................................................................
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我确实看到在 vmstat 中等待 IO 花费了一些时间,尽管不是一致而且不是很多(我认为?)所以我不确定这是否是一个大问题,我对 vmstat 的经验较少

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

  • 我们提供静态内容(75% 或更高)和脚本内容的混合服务,脚本内容通常占用大量处理器,因此在两者之间找到适当的平衡很重要;从长远来看,我们希望将静态数据移到其他地方以优化两台服务器,但我们的软件今天还没有为此做好准备

如果有人有任何想法,我很乐意提供更多信息,另一个注意事项是这是一个高可用性的生产安装,所以我很谨慎地进行一次又一次的调整,这就是为什么我自己没有玩过KeepAlive价值之类的东西然而。

sym*_*ean 7

我首先承认我不太喜欢在云中运行东西 - 但根据我在其他地方的经验,我会说这个网络服务器配置反映了相当低的流量。运行队列如此之大表明没有足够的 CPU 来处理它。运行队列中还有什么?

我们可能允许过多的 KeepAlive 请求

不 - keeplive 仍然可以提高性能,现代浏览器非常聪明地知道何时进行管道传输以及何时并行运行请求,尽管 5 秒的超时仍然相当高,并且您有很多服务器在等待 - 除非您有巨大的延迟问题,我建议将其降低到 2-3。这应该稍微缩短运行队列。

如果您尚未在网络服务器上安装 mod_deflate - 那么我建议您这样做 - 并将 ob_gzhandler() 添加到您的 PHP 脚本中。您可以将其作为自动前置:

if(!ob_start("ob_gzhandler")) ob_start();
Run Code Online (Sandbox Code Playgroud)

(是的,压缩使用更多的 CPU - 但你应该通过更快地让服务器退出运行队列/处理更少的 TCP 数据包来节省 CPU 整体 - 作为奖励,你的站点也更快)。

我建议为 MaxRequestsPerChild 设置一个上限 - 比如说 500。这只是允许进程发生一些周转,以防您在某处出现内存泄漏。您的 httpd 进程看起来很大 - 确保您已删除所有不需要的 apache 模块,并确保您提供具有良好缓存信息的静态内容。

如果您仍然看到问题,那么问题可能出在 PHP 代码中(如果您切换到使用 fastCGI,这应该很明显,不会造成任何重大的性能损失)。

更新

如果静态内容跨页面变化不大,那么也可能值得尝试:

if (count($_COOKIE)) {
    header('Connection: close');
}
Run Code Online (Sandbox Code Playgroud)

在 PHP 脚本上也是如此。