据我所知,我的服务器(Ubuntu Linux 8.04.1)上的平均负载太高,实际上我发现它在高峰时段会变慢或停止服务。
这是一个相当普通的 LAMP,支持单个网站(图片托管),显然会从磁盘提供大量内容(图片),但它们需要通过 PHP 才能提供服务。除了一般建议使用缓存/代理方法外,我不明白为什么它似乎只使用了不到一半的可用资源(4GB RAM,它是 Linode 4096)。
我对 Linux 还不是很了解,所以请提出任何可能有用的东西。这是一部分htop
(MySQL 显示 CPU 使用率为 98.9%,但这只是边缘值,它几乎一直使用 0.*%):
1 [||||||||||||||||||||||||||||||||||| 69.0%] Tasks: 355 total, 6 running
2 [||||||||||||||||||||||| 44.8%] Load average: 18.32 15.02 11.58
3 [|||||||||||||||||||||||||||||||||||| 71.9%] Uptime: 01:10:22
4 [||||||||||||||||||||||||||||| 57.9%]
Mem[||||||||||||||||||||||||||||||||||||||2190/4096MB]
Swp[| 0/127MB]
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
2345 mysql 18 0 177M 72640 5140 S 98.9 1.7 7:47.58 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9350 www-data 16 0 48940 24304 4376 R 13.7 0.6 0:01.05 /usr/sbin/apache2 -k start
9301 mysql 15 0 177M 72640 5140 S 10.0 1.7 0:00.17 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9186 mysql 17 0 177M 72640 5140 S 10.0 1.7 0:00.22 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9150 www-data 15 0 58400 33900 4476 S 8.1 0.8 0:02.03 /usr/sbin/apache2 -k start
9077 mysql 15 0 177M 72640 5140 S 8.1 1.7 0:00.39 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9270 mysql 15 0 177M 72640 5140 S 7.5 1.7 0:00.12 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9037 mysql 16 0 177M 72640 5140 S 7.5 1.7 0:00.45 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
9333 www-data 15 0 35724 11260 4560 S 6.2 0.3 0:03.88 /usr/sbin/apache2 -k start
这是目前的apache2.conf
,虽然我尝试了很多组合,以前在这里问过:
Timeout 90
KeepAlive On
MaxKeepAliveRequests 150
KeepAliveTimeout 3
<IfModule mpm_prefork_module>
StartServers 1
MinSpareServers 1
MaxSpareServers 5
MaxClients 275
ServerLimit 275
MaxRequestsPerChild 1250
</IfModule>
更新:根据要求,这是其中的一部分top
:
top - 15:07:31 up 1:46, 2 users, load average: 12.83, 10.64, 10.14
Tasks: 223 total, 17 running, 206 sleeping, 0 stopped, 0 zombie
Cpu(s): 84.3%us, 8.8%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 1.0%si, 5.9%st
Mem: 4194528k total, 3555696k used, 638832k free, 27748k buffers
Swap: 131064k total, 588k used, 130476k free, 1458672k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2345 mysql 17 0 180m 76m 5140 S 55 1.9 13:09.79 mysqld
12479 www-data 18 0 73224 47m 4552 S 48 1.2 0:03.74 apache2
12294 www-data 17 0 71788 46m 4472 R 39 1.1 0:05.78 apache2
12382 www-data 17 0 73744 48m 4460 R 33 1.2 0:03.19 apache2
更新:根据 Christopher Karel 的建议(感谢),以下是活动进程(输出自ps -efl | cut -c3- | egrep -v "^S"
)。平均显示 1-5 个apache2
进程。apache2.conf
考虑到我的当前和平均负载,这有意义吗?
T root 12519 12508 0 75 0 - 612 finish 15:07 pts/1 00:00:00 top
R www-data 18677 2774 1 76 0 - 17130 - 16:23 ? 00:00:04 /usr/sbin/apache2 -k start
R www-data 18965 2774 2 76 0 - 13397 - 16:26 ? 00:00:04 /usr/sbin/apache2 -k start
R www-data 19047 2774 2 76 0 - 11613 - 16:28 ? 00:00:00 /usr/sbin/apache2 -k start
R www-data 19088 2774 55 76 0 - 10482 - 16:29 ? 00:00:00 /usr/sbin/apache2 -k start
R www-data 19091 2774 0 81 0 - 8579 - 16:29 ? 00:00:00 /usr/sbin/apache2 -k start
R www-data 19092 2774 0 81 0 - 8355 - 16:29 ? 00:00:00 /usr/sbin/apache2 -k start
R www-data 19093 2774 0 82 0 - 8322 - 16:29 ? 00:00:00 /usr/sbin/apache2 -k start
R root 19094 18557 0 77 0 - 593 - 16:29 pts/2 00:00:00 ps -efl
R root 19095 18557 0 78 0 - 729 - 16:29 pts/2 00:00:00 -bash
R root 19096 18557 0 78 0 - 729 - 16:29 pts/2 00:00:00 -bash
答案1
您可能需要启用 Apache 的 mod_status (http://httpd.apache.org/docs/2.0/mod/mod_status.html),这样您就可以准确了解 Web 服务器内部发生的情况。具体来说,您将获得每个请求的 CPU 消耗数字。
从 vmstat/iostat 获取一些快照也不会有什么坏处。
另外,您使用的是 MyISAM 还是 InnoDB 表?当您遇到这些负载峰值时,您从 MySQL 中的“SHOW FULL PROCESSLIST\G”中得到什么?我感觉您在 MySQL 中遇到了锁/查询争用,这会延长内核运行队列的长度。
答案2
任何未处于 S 状态(睡眠)的命令都将被视为活动进程。这包括处于 R 运行状态和 D 阻塞状态的进程。(后者通常发生在等待磁盘或网络设备的 IO 时)您还可能会看到僵尸进程在平均负载下徘徊。
要找到这些内容的具体列表,请尝试以下命令:ps -efl | cut -c3- | egrep -v "^S"
您没有列出很多 iowait 时间,因此它可能是僵尸。
mysqld 的 100% CPU 使用率也可能解释您的间歇性挂断。(也许只是“有时”被固定?)平均负载可能是个转移注意力的花招,或者不是问题的根本原因。
此外,看起来您的机器使用了 4GB RAM 中的 3.5GB。 free -m
可以让您更好地了解正在使用的内容。
答案3
我没有给你完整的解决方案,但我有一些猜测。
- 您的 mysql 服务器似乎只有 128MB 左右的池。如果 LAMP 系统使用一个中等大小的数据库,这似乎偏低。这将产生大量磁盘 I/O。此外,如果 mysql 出现 CPU 峰值,请打开慢查询日志记录一段时间,看看会出现什么。可能需要一个或两个新索引。
- 对于可以读取现代内核中大多数进程计数器的 top 替代品,我推荐 atop。除其他功能外,它还可以显示进程的磁盘访问情况。请注意,atop 在其设置中有一个正在运行的守护进程,因此您可能需要在完成后将其卸载。
- 请谨慎对待您信任的 CPU 使用率数字。它们是使用略有不同的方法生成的。根据我的经验,为了显示总体 CPU 使用率,vmstat 会给出“最佳”(== 最接近感知负载)数字。
- Apache 进程正在认真工作。也许需要对 PHP 代码进行一些优化?
但是,从上面的数据来看,我并不清楚您的设置存在多大问题。虽然您可能可以发挥出更多的性能,但您可能已经接近极限了。
更新:
澄清以下评论。
典型的面向网络的 TCP 服务器由一个守护进程组成,该守护进程具有一个监听套接字和多个与客户端的打开连接。每个套接字都有一个进程在等待它(一个进程可能在多个套接字上等待)。这些进程将处于休眠状态,当某些数据到达时将被操作系统唤醒。如果它是高效的(例如静态 Web 服务器),您可能永远不会看到它在运行,因为它只需要大约 100 微秒就可以唤醒、提供一些数据并返回休眠状态。
更新 2:
现代操作系统将空闲内存分配给新的磁盘缓冲区,直到内存耗尽,然后再重新使用最少使用的缓冲区。因此,内存将始终是满的。此外,两个进程可能会以多种方式将同一页内存报告为其大小的一部分。这样做的结果是:a) 现代操作系统总是内存不足,b) 很难准确判断内存的使用情况。最好的简单指示是争取使缓冲区和缓存数字占物理内存的很大一部分。在此框中,超过 30% 的内存用于缓存磁盘数据。
答案4
如果您主要提供图像(静态文件),那么最好切换到 NGINX;如果您使用 PHP 调整图片大小,那么您可能应该使用 memcached(直接从 NGINX 提供服务,您可以在 NGINX 的配置文件中进行设置)这会产生巨大影响。Apache 不适合提供静态文件(我认为现在它不适合做任何事情)