關於Apache的性能優化

關於Apache服務器,我看了一些文檔,有一些提高性能的想法。

1.重新編譯Apache。

Apache的默認配置不是爲了最大化性能而設置的,而是考慮到向後兼容性和平臺兼容性的問題。因此很多2.x的新特性沒有能夠體現出來。在編譯的時候,需要加入一些參數,增加的這些模塊應該會大幅的提高性能。

既然重新編譯,建議使用最新的2.2版,裏面有些部分對性能有不少加強。

2.編譯的時候建議加入下面的參數
./buildconf
./configure /
 --with-mpm=worker /
 --enable-cache --enable-disk-cache --enable-mem-cache --enable-file-cache /
 --enable-nonportable-atomics /
 --enable-mods-shared=most

2.1 Multi-Processing Modules (MPM)

--with-mpm={prefork,worker}

這個是設置Apache的多任務處理的。prefork是指每個連接一個進程,也就是多進程並行處理;而worker是多線程並行處理。支持多線程處理,本來是Apache 2的一大改進,可是爲了和以前的兼容,所以對於Unix默認的都是prefork,這個改進並沒有體現出來。而這個設置只能在編譯的時候進行優化,這也是爲什麼一定要重新編譯一下apache的原因。

apache文檔這麼說:

“·worker MPM 使用多進程,每個進程包含多線程的方式。每個線程一次處理一個連接。worker對於高流量的服務器通常是一個好的選擇,因爲它比prefork MPM佔用更少的內存。
·prefork MPM 使用多進程,每個進程只包含1個線程的方式。每個進程一次處理一個連接。在許多系統上,prefork具有與worker相媲美的速度,但是它會佔用更多的內存。prefork的無線程設計在某些情況下將比worker更有優勢:它可以使用那些沒有處理好線程安全的第三方模塊,並且對於那些線程調試困難的平臺而言,它也更容易調試一些。”

這麼說確實沒有什麼必要用prefork,剛纔看了一下FC5,也是用的prefork模式。所以重新編譯apache是肯定的了。我還不知道哪個Linux發佈版本的apache默認是worker的呢。

爲了設置MPM爲worker需要設置:

--with-mpm=worker

2.2 Caching

mod_cache是從mod_proxy分離出來的。在以前apache 1.3的時候,就已經在mod_proxy中支持緩衝技術了。現在是爲了加強緩衝能力,從mod_proxy中獨立出來,而mod_proxy被完全重寫了,更強調代理的作用了。

從Apache 2.2開始,mod_cache將不再是實驗模塊而作爲穩定模塊發佈了。爲了能夠支持cache,需要在編譯的時候,啓用它,因爲默認caching是禁用的。我估計是因爲以前還是實驗模塊,所以還是爲了向後兼容的問題,暫時是默認禁用的。

mod_cache一共有三種mod_mem_cache,mod_disk_cache和mod_file_cache。具體怎麼用可以看apache的文檔,雖然是英文,不過不是很難懂:

http://httpd.apache.org/docs/2.2/caching.html

網上也有一些關於mod_cache的中文配置文章可以參考。

總值爲了能夠用cache,需要在編譯的時候設置:

--enable-cache --enable-disk-cache --enable-mem-cache --enable-file-cache

2.3 原子操作

有些模塊中,如mod_cache中使用了一些原子操作,多任務中的互斥量操作之類的。爲了可移植性,一般都是用互斥量環繞條件語句來判斷來實現。比如:

acquire_lock(mutex);
if( a == 0 ){
   a = 3;
}
release_lock(mutex);

加鎖的目的是確保if和賦值不會被其他線程中斷。可是有些cpu中提供了一條指令來做判斷賦值,不需要這麼複雜的操作,比如486加入的指令:

cmpxchg [edx], eax

先測試[edx]是否爲0,如果爲0,就讓[edx]=eax。

通過硬件保證了中間不會被中斷。要知道一旦用到了互斥量,那麼線程切換的等待就避免不了,這對於線程太多並且有公用數據的程序來說,影響性能的因素之一。因此一旦得到了硬件的直接支持。在多線程程序的處理上,就少了很多的鎖,也就提高了一定的性能。但是,不是所有的cpu都有這樣的指令,因此默認情況下還是使用鎖的老辦法。除非編譯時明確聲明:

--enable-nonportable-atomics=yes

需要注意的是,這樣編譯後,只能用在486及其以上的計算機中。我估計一般的服務器不是跑在386上吧。呵呵,對了,也儘量不要是64位的系統。

2.4 允許後期動態加載模塊

--enable-mods-shared=most

這將編譯大部分的模塊爲動態模塊,這樣後期可以動態的調入。默認情況竟然是不允許,太令我詫異了。呵呵。我感覺對於典型的多進程應用,模塊就應該是動態加載,這樣比較節省內存空間,反正大家用得都差不多的模塊。

3. 檢查

至於是否還想加其他的模塊你就看着辦吧,一般來說這就夠了。

需要提一下的是,現在apache在2.2種引入了一種新的MPM來提高性能,叫做event。可惜還在實驗狀態,未能穩定。event是worker的變種,和線程類似,也是多線程模型,不同的是,它將做數據處理的線程和等待連接的線程分開,以此試圖解決KeepAlive大了也不是,小了也不是的性能調整問題。

event是使用一個比較小的線程來等待所有的socket,包括等候連接的socket和那些KeepAlive的連接。一旦這些socket有任何發送HTTP請求了,這個等候的線程,就會這個socket交給真正做數據處理的線程進行處理,那個線程處理完成後,會將這個socket交還給這個守候線程。

這樣,即使有大量的KeepAlive連接,也不用擔心性能損耗,因爲只有一個簡單的線程來負責維護這些KeepAlive的連接,而那些真正做任務處理的線程則在一個HTTP響應處理完成後就退回到可用線程池或者被釋放了,因此很省資源。這個思路很好,現在還在實驗,如果試驗成功,估計會成爲2.4或者2.6的穩定MPM。

3.1 httpd -l

通過這條命令可以檢查mpm是prefork還是worker。很不幸默認是prefork,FC5顯示如下:

Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

3.2 apachectl -l

通過這條指令可以檢查cache模塊的加載情況,很不幸,默認是啥都沒有。

4. KeepAlive

我看到KeepAlive默認設置爲On,KeepAliveTimeout默認是5秒。這個設置的含義時說,對於HTTP/1.1的客戶端來說,將會盡量的保持客戶的HTTP連接,通過一個連接傳送多份HTTP請求<->響應。這樣對於客戶端來說,可以提高50%左右的響應時間,而對於服務端來說則降低了更多個連接的開銷。不過這個依賴於客戶端是否想保持連接。我知道IE默認是保持連接的,當你打開100個圖片的網站時,IE好像只開2個連接,通過這兩個連接傳送數據,而不是開100個連接。KeepAliveTimeout時說這次連接結束後開始計時,如果5秒內沒有重新發送HTTP請求,就斷掉連接。這個值可以稍微大一點,但是不可太大,否則會出現同時等候過多的連接,導致過多限制資源,而使服務器性能下降。可以調調看。

備註:

謝謝SeEr的提醒。

-enable-cache --enable-disk-cache --enable-mem-cache --enable-file-cache

這個選項應用在生產環境中還不能保證其穩定性,它剛剛脫離實驗狀態,還需要一個穩定期。因此,使用過程中應慎重考慮該選項。

發佈了42 篇原創文章 · 獲贊 3 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章