httpd進程超多不必定是apache自己的事

本篇文章是爲使用Apache+MySQL,併爲Apache耗盡內存而困擾的系統管理員而寫。若是您沒有耐心讀完本文,請參考如下步驟:mysql

1. 修改/etc/my.cnf,加上這樣一行:
log-slow-queries=queries-slow.log
2. 重啓MySQL
3. 酌情過上一段時間,執行mysqldumpslow命令,或直接查看datadir/queries-slow.log,從中找出執行超時的SQL語句。其中datadir是MySQL全部數據庫的存放路徑。
4. 根據上一步找出的SQL語句的內容,找到相應的數據表和腳本文件,查看超時緣由所在。可能的緣由有:數據量確實太大,未使用索引加快查詢速度,等等。但程序沒寫好確定是緣由之一。
5. 根據查出的緣由酌情解決。程序員

可能有不少系統管理員都爲這樣的情形而困擾過:Apache進程動輒佔用內存幾百兆,並且劇烈浮動,變化無常,有時甚至耗掉上G內存。在訪問者那裏 的表現就是網站速度極不穩定,間歇性抽風,有時甚至會有5-30分鐘沒法打開網頁。(ps:可經過此命令查看平均每一個httpd進程佔用實際物理內存的大小 ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}'  單位:KB)這時候,你的上司或同事可能會急切地打來電話問:咱們的網站怎麼上不去 了?咱們今天還要xxxx呢!但這時你的SSH也沒法像往常同樣忠實地給你一個「login:」,由於它也連不上服務器了。這個時候你的服務器在作什麼 呢?你找出各類理由向他們解釋以後,過上一段時間,網站可以正常訪問了,你也終於SSH上了服務器(聽起來系統管理員真沒用),而後你會用dmesg或者 在 /var/log/messages裏面發現一堆有關內存的信息,什麼DMA了,HighMem了,其中會包含相似這樣一行:
Out of Memory: Killed process 6760 (httpd).
它告訴你的信息是,你的服務器物理內存耗盡,也沒什麼好向交換區淘汰的了,只好殺掉了你的Apache的一個進程。之因此選擇這個進程,基本上就是由於它佔用的物理內存最多。sql

很沒面子的說,我被這樣的問題困擾了大半年。我曾在網上瘋狂地搜索解決的辦法,那些文章通常都會告訴你修改httpd.conf,把 MinSpareThreads或是MaxSpareThreads或是MaxRequestsPerChild設小一點,我嘗試過各類設定,都沒有明顯 的效果。我甚至曾極端地經把MaxRequestsPerChild設爲1,可是Apache的進程仍是會淤積,超過ServerLimit設定值,直到 耗盡內存。數據庫

我曾經懷疑過是PHP內存泄漏,由於PHP官方不保證PHP的各類擴展是線程安全的,推薦使用prefork MPM而不是worker MPM.因而我也曾經把ThreadsPerChild設爲1,由於這樣每一個進程也就只有一個線程,在必定意義上至關於prefork MPM,可是這種作法仍是沒有效果,問題依舊。安全

大約一週之前,我在檢查MySQL的運行狀態的時候,發現有一項Slow_queries數值很高,我敏感地認識到多是某個程序的SQL語句沒有 寫好,並且極可能就是這樣的程序致使Apache進程淤積。而後我翻閱了MySQL手冊中有關Slow query log的部分,按照那裏的指示,修改/etc/my.cnf,在mysqld那一段加上以下一行:服務器

log-slow-queries=queries-slow.logide

重啓MySQL。過上一段時間之後,用mysqldumpslow命令找出了執行超時的那條語句,根據那條查詢的內容,我找出相應的腳本。那是一個 留言本頁面,程序確實沒有寫好,成了垃圾廣告的樂園。有人經過這個頁面向數據庫裏面寫入了超過10萬條的流言,而正常的留言還不到300條。並且這個程序 裏面分頁的作法,竟然是查詢數據表裏面全部10萬條數據並排序,而用到的只有區區10條。居然不使用LIMIT語句,我~@#$%^&*!後來證 實這個留言本已是廢棄的了(我想也不多是正在使用的,由於每次都執行超時,已經沒法使用了),就刪掉了。以後,就再也沒有出現過進程淤積、內存耗盡的 問題。在ThreadsPerChild=64的狀況下,每一個 Apache進程的內存通常就幾十兆,最多的時候也就只有200M,進程數量也不多超過六七個。網站

歷經千辛萬苦,終於搞定了這個問題。在此加以總結,但願本文可以給跟我同樣被程序員害慘的系統管理員們一點點幫助。spa

原題:再也不爲Apache進程淤積、耗盡內存而困擾
出處:互聯網線程

相關文章
相關標籤/搜索