Apache 記憶體吃光調教

日期:2014/03/19  分類:web   標籤:, ,

最近常發現Apache把我的VPS記憶體吃光後,被kernel幹掉在重啟的狀況
以下系統是centos 32bit 512MB

Out of memory: Kill process 9502 (httpd) score 33 or sacrifice child
Killed process 9502 (httpd) total-vm:70580kB, anon-rss:32324kB, file-rss:0kB

仔細觀察幾天,發現我即使設定cron job讓apache每天重新啟動也沒辦法改善這個狀況
因為apache啟動沒多久,記憶體就會吃滿….這到底是WTF

於是只好開始調整apache的config
網路上人家說先從降request著手
於是我就這樣設定

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2

<IfModule prefork.c>
StartServers       1
MinSpareServers    3
MaxSpareServers  5
ServerLimit      15
MaxClients       15
MaxRequestsPerChild  2000
</IfModule>

雖然有點好笑…但目前看來還蠻有用的
至少記憶體沒再飆升

09:10:01 AM    166080    345072     67.51     31844     68500    428328     41.37
09:20:01 AM     10204    500948     98.00     32108     69048    608012     58.72

09:20:01 AM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit
09:30:01 AM      6956    504196     98.64     32336     67780    615180     59.41
09:40:01 AM      6816    504336     98.67     32748     68420    622752     60.14
09:50:01 AM    293176    217976     42.64     33116     69008    237652     22.95
10:00:01 AM    162084    349068     68.29     33364     69028    375572     36.27
10:10:01 AM    157284    353868     69.23     33728     70280    379044     36.61
10:20:01 AM    166308    344844     67.46     33980     70268    352140     34.01
10:30:01 AM    166060    345092     67.51     34240     70268    351668     33.96

9:10我重開,過10分鐘,記憶體又飆到98%
9:40上config,記憶體降到42%,後來升到68%就穩定了
這是我拿digital ocean的VPS測試
這台VPS只有512MB,所以要節省的用
再加上網站本來就沒甚麼人,憑甚麼吃這麼多記憶體= =

來講一下設定檔的詳細功能
KeepAlive 設定apache在處理完client的http request之後是否中斷TCP連線,或是持續一段時間在斷掉
因為我的網站有引用蠻多JavaScript、JQuery、圖片、CSS等等靜態的東西,所以設定打開是比較適合的
如果你的網站都是程式即使生成的動態網頁,比如JAVA等等,那關閉比較好

KeepAliveTimeout 就是設定持續多長的時間關閉連線,為什麼設定2秒呢
假設我設定10秒,每個使用者連到你的網站都會keep 10秒鐘
假設apache每秒處理50個連線,每個連線佔4M,這樣就有10x50x4=2G
這樣就耗掉你的2G記憶體了,而且連線被占住意味著apache會無法接受新連線
所以可以發現打開KeppAlive設定相當耗記憶體
但我只有512MB,不是高富帥server有96G可以用,所以只好調低秒數

MaxKeepAliveRequests 這個是設定最多可以keep幾個連線
這沒有一定的值,不過以我的狀況還是不要設太高
可以依照需求調整,調高一點就是耗記憶體

Apache有兩種MPM功能,一個是prefork,一個是worker
所以你會發現config裡有兩個設定
MPM是甚麼自己GOOGLE吧,不然這篇要寫成一本書了
反正就想像他是多核心的處理器就好了

<IfModule prefork.c>
StartServers       1
MinSpareServers    3
MaxSpareServers   10
ServerLimit      15
MaxClients       15
MaxRequestsPerChild  2000
</IfModule>

<IfModule worker.c>
StartServers         4
MaxClients         300
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

怎麼知道自己的apache是跑在哪個MPM模式呢?

[[email protected] ~]# httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c
[[email protected] ~]#

這樣我就知道我的apache是跑prefork模式
所以我只要設定prefork就好
相反的你設定worker是沒用的

稍微講一下概念
client發出request,request可能有很多connection
apache接到request 就會fork一個child去處理request
當child被request的connection撐爆了,apache就會把它砍掉
然後再生一個新的來處理

MaxClients 是最多可同時連線的connection數,記憶體不多就設少一點吧

ServerLimit 要大於等於MaxClients數量

StartServers 是指apache啟動時最小的process數量,也就是可同時處理的request數
每個process都需要記憶體的,而且apache會自動調整process數量,所以記憶體有剩的話apache會自動增加(fork)process
所以一開始不用設太多,這邊process通常中文叫做子進程,就是apache生的小孩就對了

MaxRequestsPerChild 一個process可以處理的最大request數量,這個千萬不要調低
調低會因為request超過設定數量,造成CPU飆高
當數量達到你設定的值,apache就會把它的小孩殺掉
然後再生一個小孩出來處理,一直重複產生、殺掉,這時CPU還不飆高嗎?網站不變慢?
因為每個小孩都要吃一定量的記憶體,小孩多記憶體吃更多
那不如我們一開始就設定好一個小孩可以吃多一點的request
至少設定1000以上比較安全
但如果記憶體多(比如96GB),可以一開始就在Startserver那邊設定很多小孩
很多小孩來幫忙處理連線,效能當然好XD

Last Modified: 2014/8/21 15:48

2 thoughts on “Apache 記憶體吃光調教

  1. r1235613

    這樣調之後在爆炸之前多活了2天,看來應該是要升級VPS了

    Reply

留言