[MediaTemple]虚拟主机内存优化的一点心得

今天下午好像有人对服务器ddos,或者大量灌spam(我不敢说每个人都安装了anti spam插件,即使安装了,“应对”spammer也要消耗服务器资源),http服务器耗尽服务器资源后挂掉,一会儿被watchdog重启,过不了多一会儿再次挂掉。。。以前也尝试过优化apache,不过今天似乎终于摸到了一点儿窍门。

我们合租的MediaTemple服务器cpu负载不高,内存相对紧张:

top - 23:39:45 up 16 days,  7:24,  2 users,  load average: 0.58, 0.50, 0.47
Tasks:  46 total,   1 running,  45 sleeping,   0 stopped,   0 zombie
Cpu(s):  9.9% us,  2.5% sy,  0.0% ni, 87.6% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:    689496k total,   550892k used,   138604k free,        0k buffers

所以优化主要针对如何节约内存。主机内存实际是256M,可能是多核的缘故,总显示接近700M内存,不过对应的各个进程占用的内存也相应增加了。MediaTemple的KB中有一篇[(dv) HOWTO: Performance tuning (Optimization)](http://kb.mediatemple.net/article.php?id=771),先按照这个来优化一下,主要分为三个部分。

优化Apache(httpd)

缩短超时时限:

#Timeout 120
Timeout 30

调整prefork参数,我调整的结果是:

<IfModule prefork.c>
#1/1/3
StartServers       1
MinSpareServers    1
MaxSpareServers    3
# 50 ?
ServerLimit       20
MaxClients        20
MaxRequestsPerChild  2000
</IfModule>

StartServers是开始的httpd进程数,Min和Max SpareServers是最少和最多空闲进程数,ServerLimit和MaxClients是总进程数限制,这两个参数一般来说是相同的,httpd所消耗的总内存数就和这个相关(实际进程数还会多两个,应该是负责管理子进程的“父进程”),内存不够可以把这两个数值进一步缩小,但这也同时对应着httpd同时处理的并发数。MaxRequestsPerChild是每个进程在处理多少个任务后自杀,根据需要和相关设置还会再启动新的子进程,这种机制有利于释放一些内存碎片。

MaxClients不够会在log产生错误信息,可以用下面的命令查询:

grep -i maxclient /var/log/httpd/error_log

可以根据情况再调整MaxClients的值,但如果内存就是短缺,又能有什么办法呢?

优化Mysql

设置缓存,在my.cnf的[mysqld]段中增加:

# Cache
query-cache-type = 1
query-cache-size = 16M

虽然会多占用一些内存,但能加快处理的速度,尽快把等待队列“消化”掉,还是有利于加速的。在mysql中可以查询cache使用情况:

mysql> show status like 'Qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 12       |
| Qcache_free_memory      | 13028408 |
| Qcache_hits             | 35117    |
| Qcache_inserts          | 751      |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 56       |
| Qcache_queries_in_cache | 377      |
| Qcache_total_blocks     | 872      |
+-------------------------+----------+
8 rows in set (0.00 sec)
...... some times late ......
mysql> show status like 'Qcache%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 88      |
| Qcache_free_memory      | 8837920 |
| Qcache_hits             | 164437  |
| Qcache_inserts          | 3572    |
| Qcache_lowmem_prunes    | 0       |
| Qcache_not_cached       | 432     |
| Qcache_queries_in_cache | 1177    |
| Qcache_total_blocks     | 2579    |
+-------------------------+---------+
8 rows in set (0.00 sec)

调整query-cache-size的值让Qcache_lowmem_prunes保持在0最好,设置太大了也是浪费内存。

关闭不需要的服务

比如named,域名解析使用域名注册商提供的就足够了,关闭spamassassin,邮件服务仅限于对外发送邮件,不接收:

chmod 644 /etc/init.d/psa-spamassassin

watchdog暂时不建议关闭,人不在的时候它会自动重启服务,还是有一点用处的。

其它优化设置

从其它地方还看到可以开启KeepAlive:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

这样每个连接可以发送100次请求,超时时间为15秒。如果KeepAliveTimeout减少一些,MaxKeepAliveRequests还可以设置得更大一点。

还可以启用apache的压缩输出功能:

<ifmodule mod_deflate.c>
#   DeflateCompressionLevel 2
    AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/x-javascript text/css
</ifmodule>

简单观察一下,开启deflate之后,服务器cpu idle值大概会减少15~20%,国外主机数据传输本身就慢,希望这些花销值得。

top - 01:39:03 up 16 days,  9:23,  3 users,  load average: 2.16, 2.09, 1.97
Tasks:  48 total,   1 running,  47 sleeping,   0 stopped,   0 zombie
Cpu(s): 24.1% us,  8.4% sy,  0.0% ni, 67.6% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:    689496k total,   431452k used,   258044k free,        0k buffers
Swap:        0k total,        0k used,        0k free,        0k cached

结果

现在看一下结果,ps -U apache u能看到一共有20个apache进程在运行,占用内存总量为:

root@fwolf:~# ps -U apache u|awk '{S+=$6} END {print S}'
385396

随着服务运行,内存使用量还会增加(所以MaxRequestsPerChild别设太大,定期重启一些进程)。再看看那个疑似对我ddos的家伙:

root@fwolf:~# netstat -nap|grep :80|wc -l
513
root@fwolf:~# netstat -nap|grep TIME_WAIT|wc -l
9
root@fwolf:~# netstat -nap|grep 124.115|wc -l
464
root@fwolf:~# netstat -nap|grep 124.115.0|wc -l
376
root@fwolf:~# netstat -nap|grep 124.115.4|wc -l
93

此时服务器访问稍慢,有时会超时,但起以前动不动内存不足,httpd挂掉要好一些了。查了一下,这个IP地址属于“陕西省西安市 电信”,地址总换,但基本都在上面两个网段之内。

再后来,访问量降下来之后,系统就恢复正常了,优化应该还是对服务器速度有一些作用的。

root@fwolf:~# netstat -nap|grep :80|wc -l; netstat -nap|grep TIME_WAIT|wc -l
69
47

最后贴两张后台流量图表,异常大概开始于18号下午16点,导致18号流量剧增。服务器时间是西8区,所以小时图表中的0点就是16点。按天的那个图表不知为什么出不来,不过注意18号的流量只是前9个小时的就是了。

Free Image Hosting at www.ImageShack.us

Free Image Hosting at www.ImageShack.us

另外,合租的兄弟们,[现在新的dv主机默认是PHP 5.2了](http://www.mediatemple.net/webhosting/dv/details.htm#php5),咱们啥时候升级呢?

参考

  • [再议apache优化](http://jed.dzhope.com/read.php/272.htm)
  • [APACHE优化之apache的内存使用](http://hi.baidu.com/swgweb/blog/item/dba900e94cbe9b3cb90e2d18.html)
  • [谈谈Apache的优化](http://tech.idv2.com/2007/08/09/about-apache-perf-tuning/)

Update @ 2008-01-19

看来我的担心是多余的,mod_deflate启用之后并没有耗费太多系统资源,访问量恢复正常之后,cpu load也恢复了正常:

top - 16:15:45 up 17 days, 0 min,  1 user,  load average: 0.04, 0.05, 0.07
Tasks:  51 total,   1 running,  50 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.8% us,  0.7% sy,  0.0% ni, 95.9% id,  1.7% wa,  0.0% hi,  0.0% si
Mem:    689496k total,   510200k used,   179296k free,        0k buffers
Swap:        0k total,        0k used,        0k free,        0k cached

好像启用了KeepAlive后httpd进程轮换得特别快,不像以前半天不重生一个。现在可以清楚的看到18号全天的流量图标了,再补两张图:

Free Image Hosting at www.ImageShack.us

Free Image Hosting at www.ImageShack.us

按每小时400M流量计算,每秒流量为110K,不知道算是个什么样的水平。

Update @ 2008-01-19

关闭named服务后,jail环境的ssh用户使用wget下载文件会遇到Name or service not known错误,把/etc/resolv.conf也配置到chroot中就可以了。有趣的是,如果named服务启动着就不存在这个问题。

顺便还把denyhosts装上了,daemon模式运行,占内存不多,攻击者还不少呢,值得。参考:[使用DenyHosts阻止SSH暴力破解](http://www.sofee.cn/blog/2006/10/22/51/)

2 thoughts on “[MediaTemple]虚拟主机内存优化的一点心得”

  1. 那两个IP段已经是臭名昭彰,建议直接用iptables封段这两个段。 BTW,用的是什么流量统计工具?

Leave a Reply

Your email address will not be published. Required fields are marked *