我在一台拥有 512MB RAM 的专用 VPS 上为客户托管一个网站。在过去的 2 周内,由于可用内存(或可用交换空间)为 0%,该网站已两次瘫痪。该网站的数据库非常密集,因为它运行着包含 60 多个模块的 Drupal。据网站所有者称,该网站平均每月有大约 6,000 名访客(每天约 200 名)。不过,该网站可能会发展得相当快——该网站刚刚推出不到一年。
所以我坐下来终于开始理解 Apache。我以前手动配置过 httpd.conf,但并不完全理解所有的复杂之处。
我了解到我应该通过 MaxClients 计算我的平均 Apache 进程大小(以 Mb 为单位),并且这个数字不应该超过系统可用的内存。根据 Top,每个进程大小略低于 7%(大约是 1.4Mb,对吗?)。512/1.5 = 341... 这对我来说似乎太大了。我是不是误解了什么?起初,我认为我应该按百分比(在本例中为 ~7)计算进程大小。也许我第一次是对的?
这为其他操作系统进程提供了一点空间。
数据库(MySQL)位于同一主机上。
我有两个问题。1) 我正在考虑安装 Varnish 以帮助减少数据库负载(几乎所有访问者都未经身份验证),加快初始响应时间等...对于内存这么小的系统,我疯了吗?如果我这样做,我正在考虑给它 256Mb。想法?显然,东西不会在缓存中停留很长时间。256/7 = ~36 页。然而,我希望“主要”页面会被缓存。主页以及主页后面的一些主要页面将占用大量数据库,我想尽可能减少磁盘 IO 量。
2) 如果我确实安装了 Varnish,我想知道我是否应该将 Apache 设置调整为当前值的一半,因为我已经给了 Varnish 一半的内存。在这个低级配置中,Varnish 和 Apache 之间有什么关系?
答案1
您需要获取更大的 VM。您在帖子开头告诉我们,由于内存耗尽和交换,您的 VM 已经“瘫痪”两次。添加另一个受益于大量内存的应用程序对您的情况有什么帮助?不会。
让我们分解一下您的小型虚拟机及其内存使用情况。
首先,您有 512 MB 的 RAM。取其中的 100 到 125 MB(20-25%)并将其完全从您的计算中移除。内核、支持进程、缓冲区和缓存需要这些 RAM。这样您就剩下 400 MB 的 RAM(平分差额)。
MySQL
假设您要使用 400 MB 中的一半,即 MySQL 为 200MB。我要澄清的是,我并不熟悉 Drupal 的要求,也不清楚它使用的是 MyISAM 还是 InnoDB。如果您要配置 InnoDB,则可以使用变量innodb_buffer_pool_size
并将其设置为 200M。您可以预期 MySQL 使用更多的但是,对于查询缓存(如果使用)、打开表、连接处理、线程跟踪、排序缓冲区、连接缓冲区以及无数其他配置选项,情况就更复杂了。如果您使用的是 MyISAM,情况会更加复杂,因为涉及的变量更多,key_buffer
而且myisam_sort_buffer
这只是其中两个。因此,假设 InnoDB 占用 200M 内存innodb_buffer_pool_size
,并且查询缓存已禁用,那么假设 MySQL 占用 216 MB 内存。
阿帕奇
现在您还有 184 MB 的 RAM 可供 Apache 使用。首先,让我们花点时间澄清一下您问题中一些真正令人困惑的事情。
我了解到我应该通过 MaxClients 计算我的平均 Apache 进程大小(以 Mb 为单位),并且这个数字不应该超过系统可用的内存。
不。 你观察站点使用时的平均 httpd 进程大小。使用每个 httpd 进程的平均大小(假设 prefork MPM 为默认值)计算MaxClients
可以容纳多少内存,以免超出分配给 httpd 或机器的内存,从而导致交换。
根据 Top,每个进程大小略低于 7%(大约是 1.4Mb,对吧?)。512/1.5 = 341... 在我看来这太大了。我是不是误解了什么?
是的。首先,不要再使用百分比来“计算” httpd 进程的大小。
编辑
等等!什么?512 的 7% 是 35.84。我不确定您从哪里得到 1.4 Mb。我的答案仍然有效,我不会调整我的答案来补偿您的 35M httpd 进程。
结束编辑
httpd 进程的大小在列的顶部清晰地列出RES
。例如:
top - 21:48:44 up 168 days, 4:46, 1 user, load average: 0.02, 0.09, 0.08
Tasks: 66 total, 2 running, 64 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2072832k total, 1994784k used, 78048k free, 407976k buffers
Swap: 787176k total, 300k used, 786876k free, 1321988k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8725 mysql 20 0 729m 69m 3396 S 0.0 3.4 53:45.84 mysqld
22217 apache 20 0 161m 17m 7960 S 0.0 0.9 0:08.42 apache2
26193 apache 20 0 161m 16m 6944 S 0.0 0.8 0:00.26 apache2
4470 apache 20 0 161m 16m 6948 S 0.0 0.8 0:01.52 apache2
6193 apache 20 0 161m 15m 6608 S 0.0 0.8 0:01.35 apache2
4014 apache 20 0 161m 15m 6616 S 0.0 0.8 0:01.48 apache2
6939 apache 20 0 161m 15m 6608 S 0.0 0.8 0:01.48 apache2
6685 apache 20 0 161m 15m 6608 S 0.0 0.8 0:01.32 apache2
26146 apache 20 0 161m 15m 6604 S 0.0 0.8 0:00.38 apache2
6443 apache 20 0 161m 14m 5712 S 0.0 0.7 0:01.38 apache2
26450 apache 20 0 161m 14m 5704 S 0.0 0.7 0:00.19 apache2
2524 root 20 0 159m 13m 5524 S 0.0 0.6 0:03.34 apache2
技术上RES
每个进程使用的内存是和的差值SHR
(共享)。这是因为SHR
是其他进程共享的内存。您可以在我向您展示的示例中看到,平均大约为 9 MB,对于我的独特用例。这只是一台运行 Cacti 的机器,几乎没有流量——如果我碰巧看看的话,每天可能只有 5-10 次点击。我怀疑 Drupal 占用的内存如此之少,但你很容易就能看出来。它确实占用的空间远远超过 1.4 MB。
现在,让我们非常不现实假设您的 httpd 进程每次都将使用 10 MB 的 RAM。为 Apache“分配”了 184 MB RAM,因此 MaxClients 为 18(10 MB * 18 = 180 MB)。非常非常多小于341。
漆
首先,让我们评估一下你的服务器的当前状态。假设你正确配置了 MySQL 和 httpd,使其在负载下不交换,那么你正在运行的是一个相当不错的贫血MySQL 配置和 httpd 配置会在您收到超过 18 个并发请求时开始拒绝请求。无论以何种标准衡量,这台机器都无法处理“增长非常快”的流量。
现在您想添加第三个应用程序并为其分配 256MB 的 RAM?!该 RAM 必须来自 MySQL 或 Apache,也许您可以从操作系统本身窃取一些。无论哪种方式,您都会进一步削弱机器上的一项核心服务。
从技术上来说可能的你可以在同一台主机上找到 Varnish、Apache 和 MySQL 的最佳配置设置点,让它们都能以理想的效率运行只是正确数量的 RAM,但我对此表示怀疑。
解决方案
使用我教给您的有关正确配置 MySQL 和 Apache 的知识来做到这一点:正确配置它们。您的设置MaxClients
应该远低于 300,很可能低于 20,甚至可能低于 10。我还没有提到的另一件事是,当 httpd 进程的“峰值”远高于平均值时,它们可能不太愿意放弃 RAM。例如,如果 httpd 工作进程在单个请求中达到 20MB,则该工作进程将继续无限期地使用 20MB(据我所知),直到它被回收为止。您可以通过降低MaxRequestsPerChild
设置来解决这个问题。降低此设置意味着子进程被更频繁地回收。这会降低您在负载下的性能(分叉新进程是相对地更昂贵的是,它将帮助你保持内存使用量可控。
配置正确后,您的服务器就永远不会交换。如果您正确配置了服务器,并且发现诸如负载下拒绝连接之类的问题,那么我建议您扩展您的虚拟机,或者考虑添加 Varnish在单独的专用虚拟机上。
阅读文档并在线寻求帮助是您的一个正确开始。如果您遇到困难或需要深入帮助,请随时在另一个问题中提问,但不要忘记先搜索!您很可能在另一个问题中找到答案。