apache的keepalive調式說明

在 Apache 服務器中,KeepAlive 是一個布爾值,On 代表打開,Off 代表關閉,這個指令在其他衆多的 HTTPD 服務器中都是存在的。
   KeepAlive 配置指令決定當處理完用戶發起的 HTTP 請求後是否立即關閉 TCP 連接,如果 KeepAlive 設置爲 On,那麼用戶完成一次訪問後,不會立即斷開連接,如果還有請求,那麼會繼續在這一次 TCP 連接中完成,而不用重複建立新的 TCP 連接和關閉 TCP 連接,可以提高用戶訪問速度。
   那麼我們考慮3種情況:
   1。用戶瀏覽一個網頁時,除了網頁本身外,還引用了多個 javascript 文件,多個 css 文件,多個圖片文件,並且這些文件都在同一個 HTTP 服務器上。
   2。用戶瀏覽一個網頁時,除了網頁本身外,還引用一個 javascript 文件,一個圖片文件。
   3。用戶瀏覽的是一個動態網頁,由程序即時生成內容,並且不引用其他內容。

   對於上面3中情況,我認爲:1 最適合打開 KeepAlive ,2 隨意,3 最適合關閉 KeepAlive

   下面我來分析一下原因。

   在 Apache 中,打開和關閉 KeepAlive 功能,服務器端會有什麼異同呢?

   先看看理論分析。

   打 開 KeepAlive 後,意味着每次用戶完成全部訪問後,都要保持一定時間後才關閉會關閉 TCP 連接,那麼在關閉連接之前,必然會有一個 Apache 進程對應於該用戶而不能處理其他用戶 , 假設 KeepAlive 的超時時間爲 10 秒種,服務器每秒處理 50 個獨立用戶訪問,那麼系統中 Apache 的總進程數就是 10 * 50 = 500 個,如果一個進程佔用 4M 內存,那麼總共會消耗 2G 內存,所以可以看出,在這種配置中,相當消耗內存,但好處是系統只處理了 50次 TCP 的握手和關閉操作。
   如 果關閉 KeepAlive,如果還是每秒50個用戶訪問,如果用戶每次連續的請求數爲3個,那麼 Apache 的總進程數就是 50 * 3 = 150 個,如果還是每個進程佔用 4M 內存,那麼總的內存消耗爲 600M,這種配置能節省大量內存,但是,系統處理了 150 次 TCP 的握手和關閉的操作,因此又會多消耗一些 CPU 資源。

   在看看實踐的觀察。

   我 在一組大量處理動態網頁內容的服務器中,起初打開 KeepAlive 功能,經常觀察到用戶訪問量大時Apache進程數也非常多,系統頻繁使用交換內存,系統不穩定,有時負載會出現較大波動。關閉了 KeepAlive 功能後,看到明顯的變化是: Apache 的進程數減少了,空閒內存增加了,用於文件系統Cache的內存也增加了,CPU 的開銷增加了 ,但是服務更穩定了,系統負載也比較穩定,很少有負載大範圍波動的情況,負載有一定程度的降低;變化不明顯的是:訪問量較少的時候,系統平均 負載沒有明顯變化。

   總結一下:
   在內存非常充足的服務器上,不管是否關閉 KeepAlive 功能,服務器性能不會有明顯變化;
   如果服務器內存較少,或者服務器有非常大量的文件系統訪問時,或者主要處理動態網頁服務,關閉 KeepAlive 後可以節省很多內存,而節省出來的內存用於文件系統Cache,可以提高文件系統訪問的性能,並且系統會更加穩定。

   補充:
   關於是否應該關閉 KeepAlive 選項 ,我覺得可以基於下面的一個公式來判斷。

   在理想的網絡連接狀況下,系統的 Apache 進程數和內存使用可以用如下公式表達:
HttpdProcessNumber = KeepAliveTimeout * TotalRequestPerSecond / Average(KeepAliveRequests)
HttpdUsedMemory = HttpdProcessNumber * MemoryPerHttpdProcess
   換成中文:
總Apache進程數 = KeepAliveTimeout * 每秒種HTTP請求數 / 平均KeepAlive請求
Apache佔用內存 = 總Apache進程數 * 平均每進程佔用內存數

   需要特別說明的是:
   [平 均KeepAlive請求] 數,是指每個用戶連接上服務器後,持續發出的 HTTP 請求數。當 KeepAliveTimeout 等 0 或者 KeepAlive 關閉時,KeepAliveTimeout 不參與乘的運算從上面的公式看,如果 [每秒用戶請求] 多,[KeepAliveTimeout] 的值大,[平均KeepAlive請求] 的值小,都會造成 [Apache進程數] 多和 [內存] 多,但是當 [平均KeepAlive請求] 的值越大時,[Apache進程數] 和 [內存] 都是趨向於減少的。
   基於上面的公式,我們就可以推算出當 平均KeepAlive請求 <= KeepAliveTimeout 時,關閉 KeepAlive 選項是划算的,否則就可以考慮打開。



================================


今天檢查了一下基本一臺服務器,發現TIME_WAIT高到3k 多.TIME_WAIT本身並不會佔用很大資源的,除非受到攻擊.但太多服務器還是有可能掛掉. TIME_WAIT 3699 CLOSE_WAIT 52 FIN_WAIT1 32 SYN_SENT 1 FIN_WAIT2 2 ESTABLISHED 17 SYN_RECV 45 CLOSING 6  
  根據《TCP/IP詳解》中的TCP的建立和終止中有關"TCP的終止"的講解 TCP的終止通過雙方的四次握手實現。發起終止的一方執行主動關閉,響應的另一方執行被動關閉。  
  1. 發起方更改狀態爲FIN_WAIT_1,關閉應用程序進程,發出一個TCP的FIN段;  
  2. 接收方收到FIN段,返回一個帶確認序號的ACK,同時向自己對應的進程發送一個文件結束符EOF,同時更改狀態爲CLOSE_WAIT,發起方接到ACK後狀態更改爲FIN_WAIT_2;  
  3. 接收方關閉應用程序進程,更改狀態爲LAST_ACK,並向對方發出一個TCP的FIN段;  
  4. 發起方接到FIN後狀態更改爲TIME_WAIT,併發出這個FIN的ACK確認。ACK發送成功後(2MSL內)雙方TCP狀態變爲CLOSED。 我們不難看出上面的顯示的結果的意思。根據TCP協議,主動發起關閉的一方,會進入TIME_WAIT狀態(TCP實現必須可靠地終止連接的兩個方向(全 雙工關閉)),持續2*MSL(Max Segment Lifetime),缺省爲240秒. 爲什麼 TIME_WAIT 狀態需要保持 2MSL 這麼長的時間?  
  
  TIME_WAIT的等待時間爲2MSL,即最大段生存時間.如果 TIME_WAIT 狀態保持時間不足夠長(比如小於2MSL),第一個連接就正常終止了。第二個擁有相同相關五元組的連接出現(因爲連接終止前發起的一方可能需要重發 ACK,所以停留在該狀態的時間必須爲MSL的2倍。),而第一個連接的重複報文到達,干擾了第二個連接。 
  TCP實現必須防止某個連接的重複報文在連接終 止後出現,所以讓TIME_WAIT態保持時間足夠長(2MSL),連接相應方向上的TCP報文要麼完全響應完畢,要麼被丟棄。建立第二個連接的時候,不會混淆。   
  注:MSL(最大分段生存期)指明TCP報文在Internet 上最長生存時間,每個具體的TCP實現都必須選擇一個確定的MSL值。RFC 1122建議是2分鐘,但BSD傳統實現採用了30秒。TIME_WAIT 狀態最大保持時間是2 * MSL,也就是1-4分鐘。 對apache 的操作 HTTP協議1.1版規定default行爲是Keep-Alive,也就是會重用TCP連接傳輸多個request/response.所以我打開 http中的keepalive On,發現TIME_WAIT就立刻少了下來.只有300的樣子.



==============================================


KeepAlive在Apache Core中的設置說明:
Keep-Alive擴展自HTTP/1.0和HTTP/1.1的持久鏈接特性。提供了長效的HTTP會話,用以在同一個TCP連接中進行多次請求。在某 些情況下,這樣的方式會對包含大量圖片的HTML文檔造成的延時起到50%的加速作用。在Apache1.2版本以後,您可以設置 KeepAlive On 以啓用持久鏈接。
對於HTTP/1.0的客戶端來說,僅當客戶端指定使用的時候纔會使用持久鏈接連接。此外,僅當能夠預先知道傳輸的內容長度時,纔會與HTTP/1.0的 客戶端建立持久鏈接連接。這意味着那些長度不定的內容,諸如CGI輸出、SSI頁面、以及服務器端生成的目錄列表等內容一般來說將無法使用與 HTTP/1.0客戶端建立的持久鏈接連接。而對於HTTP/1.1的客戶端來說,如果沒有進行特殊指定,持久將是默認的連接方式。如果客戶端進行了請 求,將使用分塊編碼以解決在持久鏈接裏發送未知長度內容的問題。

另一個相關的是KeepAliveTimeout在Apache Core中的設置說明:
Apache在關閉持久連接前等待下一個請求的秒數。一旦收到一個請求,超時值將會被設置爲Timeout指令指定的秒數。
對於高負荷服務器來說,KeepAliveTimeout值較大會導致一些性能方面的問題:超時值越大,與空閒客戶端保持連接的進程就越多。

後最後還有一個相關的是MaxKeepAliveRequests在Core中的說明:
MaxKeepAliveRequests指令限制了當啓用KeepAlive時,每個連接允許的請求數量。如果將此值設爲"0",將不限制請求的數目。我們建議最好將此值設爲一個比較大的值,以確保最優的服務器性能。
通過Apache的設置說明,我們已經能明白KeepAlive的原理。在對於一個包含許多圖片的網頁來說, 客戶端會在瞬間發出多個HTTP請求,此時多次建立TCP連接會大大降低響應速度。 此時通過持續連接,可以允許用戶在一個TCP連接中發出多個HTTP請求, 減少TCP連接建立次數,提高響應速度。我們可以通過access_log統計出連續HTTP請求出現的次數、間隔時間、訪問量, 以確定 MaxKeepAliveRequests 和 KeepAliveTimeout 的值。 KeepAliveTimeout 太小發揮不了持續連接的作用;太大了,持續連接遲遲不斷, 浪費TCP連接數不說,更糟糕的是系統中的 httpd 進程數目會因此不斷增加, 使得系統負載升高,甚至會導致服務器失去響應。

但是當你的服務器只是在處理動態網頁請求時,由於用戶很少會瞬間請求多個動態網頁 (一般都是打開頁面之後閱讀好半天才點下一頁), 此時打開KeepAlive無異於浪費TCP連接數。

哪麼什麼決定着我們是不是要開啓KeepAlive的因素就很簡單的確定出來了,就是說在用戶一個頁面請求中是否會向服務器發出多個HTTP的請求。

對於我的哪個朋友,他們的服務器中有着動態應用,有着所有的圖片,我看了一下,估算他們的首頁中發出的請求類型爲以下幾種:text/html、 text/css、application/octet-stream、text/javascript、image/gif、image/jpeg。一 個首頁發出了181次請求(我看了所有的請求,注意所有的請求都是同一個域名)。這裏可能由應用程序生成的只有text/html和 application/octet-stream,這種請求中text/html只有一次,而application/octet-stream也只有 4次。哪麼關閉KeepAlive對他們有幫助嗎?我的回覆是沒有幫助,而且會讓服務器的服務質量更差!

如果是這樣的情況,怎麼辦呢?我的建議如下:
1.如果我們每一個頁面中只有一個請求是動態生成的,而180個(裏面可能有4個不是,不過不重要了)都是靜態的,哪麼應該將靜態與動態分開到兩個服務器上(一臺機器都可以)。將動態應用的KeepLive關閉,將靜態服務器的KeepLive打開。
2.前端前部署四層交換或七層交換或緩存服務器,這樣會讓系統的擴展做起來,同時也可以讓服務器的KeepLive打開時有更好的效果。
3.應該考慮優化下他們的apache了,聽說一個進程有高達xxM的內存佔用,比較恐怖,在10M以內比較正常的說,不過這是一個option了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章