今天下午好像有人对服务器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),先按照这个来优化一下,主要分为三个部分。
优化Apache(httpd)
缩短超时时限:
#Timeout 120 Timeout 30
调整prefork参数,我调整的结果是:
#1/1/3 StartServers 1 MinSpareServers 1 MaxSpareServers 3 # 50 ? ServerLimit 20 MaxClients 20 MaxRequestsPerChild 2000
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的压缩输出功能:
# DeflateCompressionLevel 2 AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/x-javascript text/css
简单观察一下,开启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个小时的就是了。
另外,合租的兄弟们,现在新的dv主机默认是PHP 5.2了,咱们啥时候升级呢?