Web 服务器上的内存泄漏

Web 服务器上的内存泄漏

所以我最近遇到了一些服务器性能问题。目前我们正在运行具有 4GB 和 160GB 磁盘空间的 Fedora 服务器。我们几乎已经用完磁盘上的所有文件了。我们正在运行多个网站,每个网站都有多个备份。但实际上只有一个网站获得了流量。这是一个拥有大量访问者的电子商务网站。

最近加载时间很慢,我注意到我们的可用内存变得非常低(低于 1 GB)。我将重新启动服务器(现在我每天必须重新启动 3 次),一切都会好起来的。我们一开始释放了 2.2GB 内存,但 3 或 4 小时后,您会发现内存被耗尽,加载时间也在缓慢增长。我不知道这是从哪里来的,或者我们是否应该升级到更好的服务器。我只是不想升级然后意识到我在 MySQL 请求的某个地方遇到了瓶颈。

任何想法或建议将不胜感激。

编辑-

还有 3 个虚拟主机,我有超过 60,000 个文件。

             total       used       free     shared    buffers     cached
Mem:          4003       3372        630          0        398       1717
-/+ buffers/cache:       1256       2746
Swap:         8189          0       8189

21:21:49 up 46 min,  1 user,  load average: 3.75, 4.20, 4.03

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  2      0 592728 409640 1838360    0    0   165   411  953  473  9  8 47 36  0

这是顶部快照。

 1356 mysql     20   0 1374m 219m 5320 S  5.6  5.5  14:06.21 mysqld
15796 root      20   0  103m  20m  440 D  1.0  0.5   0:04.42 sendmail
 1081 root      20   0  103m  20m  440 D  0.7  0.5   0:21.73 sendmail
24013 root      20   0 97416  22m 2648 D  0.7  0.6   0:15.15 mailq
 1525 root      20   0  247m 7980 3472 S  0.3  0.2   0:06.88 vlogger (access
 1530 apache    20   0  539m  13m 3008 S  0.3  0.3   0:03.56 httpd
 2399 apache    20   0  539m  12m 2748 S  0.3  0.3   0:00.85 httpd
 5763 root      20   0  121m 4932 3868 S  0.3  0.1   0:00.07 sshd
12326 apache    20   0  539m  12m 2992 S  0.3  0.3   0:00.38 httpd
12421 apache    20   0  539m  12m 2988 S  0.3  0.3   0:00.45 httpd
16396 apache    20   0  538m  12m 2284 S  0.3  0.3   0:00.09 httpd
17050 root      20   0 15368 1256  868 R  0.3  0.0   0:00.09 top
    1 root      20   0 37336 4104 1908 S  0.0  0.1   0:02.82 systemd
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0     0    0    0 S  0.0  0.0   0:00.03 ksoftirqd/0
    5 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/0:0H
    6 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kworker/u:0
    7 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/u:0H
    8 root      RT   0     0    0    0 S  0.0  0.0   0:00.11 migration/0
    9 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/0
   10 root      RT   0     0    0    0 S  0.0  0.0   0:00.14 migration/1
   12 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/1:0H
   13 root      20   0     0    0    0 S  0.0  0.0   0:00.02 ksoftirqd/1
   14 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/1
   15 root      RT   0     0    0    0 S  0.0  0.0   0:00.15 migration/2
   17 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/2:0H
   18 root      20   0     0    0    0 S  0.0  0.0   0:00.03 ksoftirqd/2
   19 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/2
   20 root      RT   0     0    0    0 S  0.0  0.0   0:00.11 migration/3
   22 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 kworker/3:0H
   23 root      20   0     0    0    0 S  0.0  0.0   0:00.02 ksoftirqd/3
   24 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/3
   25 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 cpuset
   26 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 khelper
   27 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kdevtmpfs
   28 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 netns
   29 root      20   0     0    0    0 S  0.0  0.0   0:00.00 xenwatch

答案1

每分钟启动 sar 并输出 ps 表。看我的详细回答这里

下次服务器崩溃时,用来sar -r帮助追踪什么时候它发生了。现在使用 ps-cronjob 或我的输出github 上 ps 的 Perl 包装器,找出哪个进程可能是罪魁祸首。

假设服务器在 12:00:00 到 13:00:00 之间发生了爆炸。使用sar -r -s 12:00:00 -e 13:00:00。由此您应该看到数据出现峰值。 (如果更容易的话,有一个基于 Java 的实用程序可以进行绘图,但通常不值得这么麻烦。) 假设您在 12:15 看到一个峰值(或一个波谷)。现在扫描 ps 列输出的时间范围(例如 12:00 到 12:15),按 pid 排序,然后按时间排序,然后查看内存列:

awk '/^=== .* 12:00:/,/^=== .* 12:16:/' /var/log/sa/ps/today |
 sort -k 1n -k 16 

(排序选项假定时间位于第 16 列,但情况可能是也可能不是)。现在您可以再次通过 awk 过滤该输出以查找输出行之间的差异:

... | awk 'lastpid && lastpid==$1 && last != $0 { print} /^[0-9]/ { lastpid=$1;last=$0; }'

这是一个相当粗糙的过滤器。对于某些进程(其命令行一直在变化,例如 mysql、postgresql 和 snmpd),这不会很有帮助,但希望您可以调整 awk 以帮助您找到罪魁祸首。

相关内容