我在 Debian 上使用 SpamAssassin(默认配置禁用了 Pyzor、AWL 和 Bayes,并启用了 sa-compile),并且每个 spamd 子进程在 32 上消耗大约 100 到 150MB 的内存(大约 50MB 的实际内存)位服务器,在 64 位服务器上大约翻倍(逻辑上足够)。通常有两个子进程,但在繁忙时间可以有五个(最大)运行。
ISTM 认为 200 到 600MB 对于这项任务来说是很多内存。我想继续使用 SA 作为我的过滤结构的一部分,但是证明这么多内存的合理性变得越来越困难。
有什么方法可以减少每个子进程使用的内存量?(或者,使单个子进程如此之快,以至于我可以将最大子进程设置为 2?)。我愿意考虑任何选项,包括会或可能导致准确性降低的选项。
我已经阅读了 SA wiki 上的“内存不足问题”页面;没有任何用处。大于 5 MB 的邮件不会使用 SA 进行扫描。
我认为您误解了 Linux 报告内存使用情况的方式。当一个进程分叉时,它会导致第二个进程与原始进程共享大量资源。其中包括内存。但是,Linux 为此使用了一种称为写时复制 (COW) 的技术。这意味着每个分叉的子进程将在内存中看到与原始进程相同的数据,但只要该数据更改(由子进程或父进程),更改就会被复制,然后才会指向新位置。
在其中一个进程对该数据进行更改之前,它们将共享同一个副本。结果,我可以拥有一个使用 100MB RAM 的进程,并将其分叉 10 次。这些分叉的进程中的每一个都会显示正在使用 100MB 的 RAM,但是如果您查看盒子上的整体内存使用情况,它可能只显示正在使用 130MB 的 RAM(进程之间共享 100MB,加上几 MB 的开销,加上系统其余部分的另外一两个 MB)。
作为最后一个例子,我现在有一个运行着 30 个 apache 进程的盒子。每个进程都显示使用 22MB 的 RAM。但是,当我运行free -m以显示我的整体 RAM 使用情况时,我得到:
如您所见,这个盒子甚至没有足够的 RAM 来运行 30 个进程,每个进程都使用 18MB 的“真实”RAM。除非你真的用完了 RAM 或者你的应用程序正在大量交换,否则我不会担心这些事情。
更新:另外,请查看jldugger在此处回答有关 Linux 内存使用的另一个问题时提到的这个名为smem的工具。
使用sa-compile您可能能够提高许多规则的匹配速度。
这就是我所做的。
我有一个设置,其中很多消息往往会大致同时传递;对于一系列实验,我对复制到临时假脱机的消息运行 SA,然后每五分钟由一个 cron 作业传递。
spamd
会继续打印“也许你应该增加 max-children 参数”,我曾一度将它提高到 40,但我让服务器消耗了所有的交换空间并崩溃了。现在我实现了一个不同的机制,其中交付由 Procmail 锁定文件控制。因为它做起来很简单,所以我只使用进程 ID 的最后一位,并运行 10 个子进程。我完全不确定这是不是最优的,但它已经帮助避免了我不时经历的疯狂的负载峰值。
此外,我开始
spamd
有一些ulimit
限制。这些数字是从http://svn.apache.org/repos/asf/spamassassin/trunk/contrib/run-masses中取出的,除非我取消了ulimit -u
限制。(不知道发生了什么。无论如何,32 太小了。像 500 这样的东西我可以继续spamd
运行一段时间,但最终会达到极限。)我想如果负载在很长一段时间内太高,我会以交付失败告终,但到目前为止,我似乎已经设法将负载降低到可管理的水平;和一堆失败的交付仍然比机器用完交换要好得多。
高负载平均值(有时)是您的机器内存不足(并使用大量 CPU 从虚拟内存来回交换进程)的间接症状,因此您可以尝试将邮件服务器配置为不通过 SpamAssassin 传递邮件,如果平均负载太高。
您没有提及您正在运行哪个 MTA,但如果您从 exim4 中的访问控制列表调用 SA,则此消息底部的建议是有效的。
此外,您可以减轻 SA 上的负载,从而减少其内存使用量,方法是在其前面放置一些其他资源较少的垃圾邮件过滤方法(即,它们可以在垃圾邮件到达 SA 之前处理并拒绝一些垃圾邮件) -例如,灰名单和发件人验证标注使用相对较少的 RAM。
几个月前我们也遇到过类似的情况。SpamAssassin 和 ClamAV 在托管服务器上使用了大量内存。我们可以选择向服务器添加更多内存,但事实证明切换到 Postini 更具成本效益和时间效益。YMMV。