= 2011-04-13 = == Apache Performance Tuning == * 4/11~4/13 多次重新開機 trac 網站,一直無法找出記憶體需求突然高漲的主因是因為升級到 Squeeze,改用 Apache MPM 版本([http://packages.debian.org/apache2-mpm-prefork apache2-mpm-prefork]),還是其他原因。 * [[Image(jazz/11-04-13:11-04-14_memory-week.png)]] * 花了兩天時間,總算找出造成 trac 網站大量記憶體需求的特徵:刻意發起造成 CLOSE_WAIT 的攻擊行為。 {{{ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15652 www-data 20 0 783m 763m 4624 R 97.0 75.4 17:31.07 apache2 20059 www-data 20 0 52836 31m 4732 S 2.7 3.2 0:06.86 apache2 jazz@trac-pool:~$ sudo netstat -nap | grep 15652 tcp6 1 0 140.110.X.X:80 220.181.93.1:55903 CLOSE_WAIT 15652/apache2 }}} * 手動砍掉 15652 這個 process 之後,同樣這個 IP,後來又產生了一次 CLOSE_WAIT 現象,不禁懷疑這是一種網站攻擊方式。 {{{ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 23708 www-data 20 0 414m 396m 4544 R 99.7 39.2 2:44.46 apache2 23025 www-data 20 0 74940 55m 4752 S 0.0 5.5 0:27.58 apache2 tcp6 0 0 140.110.X.X:80 220.181.93.1:64932 TIME_WAIT - tcp6 0 0 140.110.X.X:80 220.181.93.1:47074 TIME_WAIT - tcp6 0 0 140.110.X.X:80 220.181.93.1:50047 TIME_WAIT - tcp6 0 0 140.110.X.X:80 220.181.93.1:43913 TIME_WAIT - }}} * <解決方法> 降低 net.ipv4.tcp_keepalive_time 的數值,預設是 7200 秒(兩小時),真的太長了!! {{{ echo "decrease TCP socket TIME_WAIT time" sysctl -w net.ipv4.tcp_fin_timeout=10 sysctl -w net.ipv4.tcp_tw_reuse=1 sysctl -w net.ipv4.tcp_tw_recycle=1 echo "decrease TCP socket CLOSE_WAIT time" sysctl -w net.ipv4.tcp_keepalive_time=30 sysctl -w net.ipv4.tcp_keepalive_probes=2 sysctl -w net.ipv4.tcp_keepalive_intvl=2 }}} * <參考> [http://tw.myblog.yahoo.com/yaitoo-richzal/article?mid=212&sc=1 大量 CLOSE_WAIT 的影響] {{{ 大量的 CLOSE_WAIT 連接,直接佔滿 TCP 連線佇列, 導致 Apache 失去回應,且 CPU 使用量與記憶體使用量快速提高!! }}} * <參考> [http://haka.sharera.com/blog/BlogTopic/32309.htm CLOSE_WAIT 生成的原因] * 另外我也做了兩個小調校: * <1> 限制每個 process 的記憶體使用 - 在 /etc/profile 中加入 {{{ ulimit -v 524288 }}} * 其結果是最高可以使用的記憶體是 524288 = 512 * 1024 kbytes = 512 MB。 {{{ virtual memory (kbytes, -v) 524288 }}} * <2> 把 /etc/apache2/apache2.conf 改成只使用 prefork 模組,並且降低 !KeepAliveTimeout 的時間(15秒降低到2秒),還有降低預設開啟的 apache process 數量。 {{{ #!diff --- /etc/apache2/apache2.conf.org 2011-04-12 10:32:53.000000000 +0800 +++ /etc/apache2/apache2.conf 2011-04-14 00:38:39.000000000 +0800 @@ -64,7 +64,7 @@ # # Timeout: The number of seconds before receives and sends time out. # -Timeout 300 +Timeout 30 # # KeepAlive: Whether or not to allow persistent connections (more than @@ -83,7 +83,7 @@ # KeepAliveTimeout: Number of seconds to wait for the next request from the # same client on the same connection. # -KeepAliveTimeout 15 +KeepAliveTimeout 2 ## ## Server-Pool Size Regulation (MPM specific) @@ -96,11 +96,11 @@ # MaxClients: maximum number of server processes allowed to start # MaxRequestsPerChild: maximum number of requests a server process serves - StartServers 5 - MinSpareServers 5 - MaxSpareServers 10 - MaxClients 150 - MaxRequestsPerChild 0 + StartServers 1 + MinSpareServers 1 + MaxSpareServers 1 + MaxClients 5 + MaxRequestsPerChild 100 # worker MPM @@ -113,15 +113,15 @@ # and starting Apache. # ThreadsPerChild: constant number of worker threads in each server process # MaxRequestsPerChild: maximum number of requests a server process serves - - StartServers 2 - MinSpareThreads 25 - MaxSpareThreads 75 - ThreadLimit 64 - ThreadsPerChild 25 - MaxClients 150 - MaxRequestsPerChild 0 - +# +# StartServers 1 +# MinSpareThreads 1 +# MaxSpareThreads 1 +# ThreadLimit 1 +# ThreadsPerChild 1 +# MaxClients 5 +# MaxRequestsPerChild 50 +# # event MPM # StartServers: initial number of server processes to start @@ -130,15 +130,15 @@ # MaxSpareThreads: maximum number of worker threads which are kept spare # ThreadsPerChild: constant number of worker threads in each server process # MaxRequestsPerChild: maximum number of requests a server process serves - - StartServers 2 - MaxClients 150 - MinSpareThreads 25 - MaxSpareThreads 75 - ThreadLimit 64 - ThreadsPerChild 25 - MaxRequestsPerChild 0 - +# +# StartServers 1 +# MinSpareThreads 1 +# MaxSpareThreads 1 +# ThreadLimit 1 +# ThreadsPerChild 1 +# MaxClients 5 +# MaxRequestsPerChild 50 +# # These need to be set in /etc/apache2/envvars User ${APACHE_RUN_USER} }}} * <參考> [http://bobcares.com/blog/?p=71 Configuring Apache for Maximum Performance] * <參考> [http://wiki.vpslink.com/Low_memory_MySQL_/_Apache_configurations Low memory MySQL / Apache configurations] * <參考> [http://www.devside.net/articles/apache-performance-tuning Apache Performance Tuning] {{{ prefork [default MPM for Apache 2.0 and 1.3]: * Apache 1.3-based. * Multiple processes, 1 thread per process, processes handle requests. * Used for security and stability. * Has higher memory consumption and lower performance over the newer Apache 2.0-based threaded MPMs. worker: * Apache 2.0-based. * Multiple processes, many threads per process, threads handle requests. * Used for lower memory consumption and higher performance. * Does not provide the same level of isolation request-to-request, as a process-based MPM does. }}} {{{ MaxClients ≈ (RAM - size_all_other_processes)/(size_apache_process) }}}