我的服务器发生了什么事? 高负载,大量空闲的CPU时间,低磁盘利用率

我运行一个网站,并发送一个合法的select,每日电子邮件通讯订阅。 虚拟主机和电子邮件发送都由同一台机器完成。

我有大约10万订阅者select了我的每日电子邮件通讯。 我的PHP脚本做了相当不错的工作,直到最近才把邮件发送给他们,但是随着列表的增长,我跟不上。

当我运行顶部时,我的负载非常高 – 通常至less有6或7,有时甚至高达15 – 尽pipe我只有两个CPU。 但是,当我运行sar时,CPU空闲时间平均约为30%。 所以,看来我没有CPU绑定。 当我运行iostat时,好像我没有磁盘绑定,因为我的每个设备的%util很低(不超过5%)。

鉴于我似乎没有CPU绑定或磁盘绑定, 为什么最高报告如此高的负载?

此外,由于我似乎没有CPU绑定或磁盘绑定, 为什么我的电子邮件发送脚本无法跟上?


以下是我在运行top时看到的内容:

top - 11:33:28 up 74 days, 18:49, 2 users, load average: 7.65, 8.79, 8.28 Tasks: 168 total, 5 running, 162 sleeping, 0 stopped, 1 zombie Cpu(s): 38.9%us, 58.6%sy, 0.8%ni, 0.0%id, 0.7%wa, 0.2%hi, 0.8%si, 0.0%st Mem: 3083012k total, 2144436k used, 938576k free, 281136k buffers Swap: 2048248k total, 39164k used, 2009084k free, 1470412k cached 

以下是我在运行iostat -mx时看到的内容:

 avg-cpu: %user %nice %system %iowait %steal %idle 34.80 1.20 55.24 0.37 0.00 8.38 Device: rrqm/s wrqm/sr/sw/s rMB/s wMB/s avgrq-sz avgqu-sz await svctm %util sda 0.19 71.70 1.59 29.45 0.02 0.07 5.90 0.55 17.82 1.16 3.59 sda1 0.00 0.00 0.00 0.00 0.00 0.00 7.10 0.00 13.80 13.72 0.00 sda2 0.05 50.45 1.13 24.57 0.01 0.29 24.25 0.35 13.43 1.15 2.97 sda3 0.05 10.17 0.20 2.33 0.01 0.05 43.75 0.05 20.96 2.45 0.62 sda4 0.00 0.00 0.00 0.00 0.00 0.00 2.00 0.00 70.50 70.50 0.00 sda5 0.07 0.22 0.03 0.07 0.00 0.00 32.84 0.08 856.19 8.03 0.08 sda6 0.02 5.45 0.03 0.72 0.00 0.02 67.55 0.02 26.72 5.26 0.39 sda7 0.00 1.56 0.00 0.42 0.00 0.01 38.04 0.00 8.88 5.84 0.24 sda8 0.01 3.84 0.20 1.35 0.00 0.02 28.55 0.05 31.90 4.08 0.63 

以下是我在运行sar时看到的内容:

 09:40:02 AM CPU %user %nice %system %iowait %steal %idle 09:50:01 AM all 30.59 1.01 49.80 0.23 0.00 18.37 10:00:08 AM all 31.73 0.92 51.66 0.13 0.00 15.55 10:10:06 AM all 30.43 0.99 48.94 0.26 0.00 19.38 10:20:01 AM all 29.58 1.00 47.76 0.25 0.00 21.42 10:30:01 AM all 29.37 1.02 47.30 0.18 0.00 22.13 10:40:06 AM all 32.50 1.01 52.94 0.16 0.00 13.39 10:50:01 AM all 30.49 1.00 49.59 0.15 0.00 18.77 11:00:01 AM all 29.43 0.99 47.71 0.17 0.00 21.71 11:10:07 AM all 30.26 0.93 49.48 0.83 0.00 18.50 11:20:02 AM all 29.83 0.81 48.51 1.32 0.00 19.52 11:30:06 AM all 31.18 0.88 51.33 1.15 0.00 15.47 Average: all 26.21 1.15 42.62 0.48 0.00 29.54 

这里是我碰巧运行top -c时在特定时间列出的几个进程:

  PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8180 mysql 16 0 57448 19m 2948 S 26.6 0.7 4702:26 /usr/sbin/mysqld --basedir=/ --datadir=/var/lib/mysql --user=mysql --pid-file=/var/lib/mysql/bristno.pid --skip-external-locking 26956 brristno 17 0 0 0 0 Z 8.0 0.0 0:00.24 [php] <defunct> 26958 brristno 17 0 94408 43m 37m R 5.0 1.4 0:00.15 /usr/bin/php /home/brristno/public_html/dbv.php 22852 nobody 16 0 9628 2900 1524 S 0.7 0.1 0:00.17 /usr/local/apache/bin/httpd -k start -DSSL 8591 brristno 34 19 96896 13m 6652 S 0.3 0.4 0:29.82 /usr/local/bin/php /home/brristno/bin/mailer.php 1qwqyb6 i0gbor 24469 nobody 16 0 9628 2880 1508 S 0.3 0.1 0:00.08 /usr/local/apache/bin/httpd -k start -DSSL 25495 nobody 15 0 9628 2876 1500 S 0.3 0.1 0:00.06 /usr/local/apache/bin/httpd -k start -DSSL 26149 nobody 15 0 9628 2864 1504 S 0.3 0.1 0:00.04 /usr/local/apache/bin/httpd -k start -DSSL 

谢谢,德米特里!

1)我已经有了一个脚本,可以取消订阅在过去一个月内至lesspopup过五次的邮件地址,所以希望这可以让我的列表相对局限于活动的电子邮件地址。

2)我正在使用exim 4.69。 我的configuration文件在

/etc/exim.conf

和我的日志文件在:

在/ var /日志/ exim_mainlog
在/ var /日志/ exim_paniclog
在/ var /日志/ exim_rejectlog

另外,当我查看/etc/syslog.conf时,我看到以下内容:

 # Log all the mail messages in one place. mail.* -/var/log/maillog 

我不知道“/”在-/var/log/maillog的开头是什么意思,但是当我查看那个文件时,很明显,那里logging了很多。

另外,这个文件中logging了很多:

在/ var /日志/ exim_mainlog

我自从添加到/etc/exim.conf这一行:

 no_message_logs 

我认为这将禁用邮件日志logging(我重新启动exim),但是当我看着/ var / log / maillog和/ var / log / exim_mainlog这两个文件仍然收到新的日志条目。

问题: 如何禁用大多数/全部的日志logging?

3)当我查看/ var / log / exim_paniclog时,我看到了很多这样的条目:

 2010-12-19 04:03:32 1PUFB1-0006xZ-GF User 0 set for local_delivery transport is on the never_users list 

环顾四周后,似乎意味着exim正试图传递给根邮件地址。 在使用尽可能less的CPU资源时,处理这些邮件传递到根的最佳方式是什么?

如上所述,负载平均值与运行队列中等待进程的数量有关。 如果这些进程中的每一个都没有什么工作要做,并且可以快速释放处理器,那么您可以处理比通常的每CPU经验1大得多的负载平均值。

邮件就是这样一个完美的例子,每个进程都需要CPU发送消息,但是非常非常less。 我已经看到运行sendmail的邮件系统的平均负载在25到35的范围内,并且系统仍然是交互式的并且工作正常。

标记

系统指标(负载,CPU,I / O)往往是大多数人对系统性能的唯一指标 – 但是实际的交易性能却是完全不同的。 这些度量标准可以为性能如何受到限制提供指导,但是看看事务处理实际执行的时间真的更有用。

为什么我的电子邮件发送脚本不能跟上?

这是否意味着您看到邮件队列没有清理的问题? 或者是脚本执行的时间长度? 或者你推断Tere是基于高负荷的问题?

正如mfarver所说,电子邮件系统中的高负载并不less见,特别是随着邮件服务器为避免垃圾邮件而进行的同步检查的数量不断增加。

就个人而言,我不是一个狂热的粉丝 – 我已经有了更好的sendmail和postfix的经验,虽然我承认自从我对MTA进行了严格的testing以来已经有好几年了。 当然,你正在进入的地方,你需要更复杂的电子邮件处理。

而不是closures日志logging,临时添加转发为root帐户可能是一个好主意,以确切地看到所有那些没有得到交付的电子邮件。

我猜测MTAconfiguration为直接发送邮件给他们的收件人。 如果确实有性能问题,那么可以考虑使用智能中继来更快地卸载服务器上的消息。 但是请尝试将Exim切换到队列中,以查看是否首先解决负载(更重要的是任何性能)问题。 另外,看看你的DNScaching,看看是否可以改善。

如果你已经使用智能中继,那么请检查它的configuration是否正确–IME,使用基于sendmail的设置,php mail()调用阻塞很长一段时间(但不知怎的,消息仍然被传递?),如果MTA不能连接到智能主机。

现在很多电子邮件服务提供商都将垃圾邮件作为阻止垃圾邮件的一种方法来实施,而按域sorting邮件列表有助于减lessDNS查询,最终可能会导致远程系统限制或阻止邮件。 确保你做的一切都是实用的,以避免看起来像一个垃圾邮件制造者(如SPF,DKIM) – IIRC Exim不直接支持米尔特人 – 有很多有用的米尔​​特人 – 特别是milter限制。

high loadrun queue的平均大小 – 例如想要在CPU上run queue进程。 看起来你的脚本做了很多CPU的工作。 所以,你必须把它分类并在这里张贴它的来源。 你怎么发信?

首先,你的负荷不是那么高。 2个CPU上的8个负载意味着每个CPU负载4个。 另外现代的CPU是平常的双核心,所以它就像2个CPU在一个,所以负载实际上更像是每个CPU 2个。

就处理电子邮件而言,有两件事可以减轻负担:1)确保你有一个处理退回电子邮件的脚本,以便你可以标记一个电子邮件地址为“反弹”,而不是发送到地址了。 一个大邮件列表的通常跳出率,即使是一个select在一个是大约20%。 反弹确实会影响服务器,因为不仅服务器必须发送人们看不到的电子邮件,还必须接收并处理退回的电子邮件。

2)禁用日志logging到maillog。 在大量的邮件列表中,条目将被添加到每个发送的电子邮件中的maillog以及收到的每个退回电子邮件中。 写入maillog是非常耗费资源的,因为它涉及磁盘写入。 通过简单地禁用maillog,你可以减less你的系统负载“有很多”,有时多达50%,我不知道你使用的是什么邮件服务器,但是在Linux上你通常会在/etc/syslog.conf

只需注释掉邮件条目,然后重新启动系统日志服务。

还有一件事:反弹的电子邮件通常会回到根帐户。 系统通常达到root帐户的邮箱限制,通常是100MB。 一旦达到限制,你就开始另一个问题,你甚至不能接受反弹的电子邮件,所以你的系统可能会发送自己的反弹消息增加更多的负载。

结论:监视你的反弹,并保持清单 – 标记帐户,不发送邮件给他们了。

您的maillog条目标记为不在每个条目上冲洗。 这应该有助于减less写入此日志的CPU开销。 但是,由于您使用的是Exim,因此默认情况下不使用此日志。 检查你的configuration,确保你没有启用syslog。

要减less正在logging的内容,请将log_selector规范添加到您的configuration中。 可能的值详见Exim Specification(可能是第49章)。 虽然,这可能不是你的问题。

尝试运行exiwhat看什么交付正在尝试。 mailq不应该有很多消息等待交付和已经排队了一个小时或更多。 已经在队列中一段时间​​的消息的长长的列表表明你正在尝试可能反弹的交付。

Exim不能处理很多同时运行的交付stream程。 你应该看看configuration的变化,这可能有帮助。

  • 尝试增加两次重试之间的时间,并缩短将邮件反弹为未传递之前的时间。 这将减less反弹无法传递的消息所需的尝试次数。
  • 禁用即时交付尝试,以便从队列运行交付。 您可能希望使用queue_only_loadqueue_only_load地执行此操作。
  • 设置queue_run_max来限制队列运行器进程的数量。

要解决尝试交付的路线,您可以使用运输或别名。 我给我的电子邮件地址别名。 Ubuntu使用这个路由器来防止以root用户身份运行。

 mail4root:
   debug_print =“R:mail4root for $ local_part @ $ domain”
  驱动程序=redirect
   domains = + local_domains
   data = / var / mail / mail
   file_transport =地址文件
   local_parts = root
  用户=邮件
   group = mail