優化 Apache 和 PHP

調優 Apache php

Apache 是一種高度可配置的軟件。它具備大量特性,但每一種都代價高昂。從某種程度上來講,調優 Apache 來講就是以恰當的方式分配資源,還涉及到將配置簡化爲僅包含必要內容。html

配置 MPMjquery

Apache 是模塊化的,由於能夠輕鬆添加和移除特性。在 Apache 的核心,多處理模塊(Multi-Processing Module,MPM)提供了這種模塊化功能性 —— 管理網絡鏈接、調度請求。MPM 使您可以使用線程,甚至可以將 Apache 遷移到另一個操做系統。linux

每次只能有一個 MPM 是活動的,必須使用 --with-mpm=(worker|prefork|event) 靜態編譯。數據庫

每一個請求使用一個進程的傳統模型稱爲 prefork。較新的線程化模型稱爲 worker,它使用多個進程,每一個進程又有多個線程,這樣就能以較低的開銷得到更好的性能。最新的 event MPM 是一種實驗性的模型,爲不一樣的任務使用單獨的線程池。要肯定當前使用的是哪一種 MPM,可執行 httpd -l緩存

選擇使用何種 MPM 取決於許多因素。在 event MPM 脫離實驗狀態以前,不該考慮這種模型,而是在使用線程和不使用線程之間做出選擇。表面上看來,若是全部底層模塊(包括 PHP 使用的全部庫)都是線程安全的,線程要優於分叉(forking)。而 Prefork 是較爲安全的選擇;若是選擇了 worker,則應該謹慎測試。性能收益還取決於您的發佈版所附帶的庫及硬件。安全

不管選擇了哪一種 MPM,都必須恰當地配置它。通常而言,配置 MPM 包括告知 Apache 怎樣去控制有多少 worker 正在運行,它們是線程仍是進程。prefork MPM 的重要配置選項如清單 1 所示。服務器


清單 1. prefork MPM 的配置
網絡

                
StartServers       50
MinSpareServers   15
MaxSpareServers   30
MaxClients       225
MaxRequestsPerChild  4000

 

編譯您本身的軟件

最初使用 UNIX® 時,我堅持爲加入系統的一切編譯軟件。最終,維護更新給我帶來了麻煩,因此我學會了如何構建包來簡化這一任務。後來我意識到,大多數時候我都在重複作發佈版作過的事情。如今,在很大程度上來講,我會盡量堅持使用我所選擇的發佈版提供的一切,僅在必要的時候使用本身的包。ide

相似地,您可能會發現,就可維護性而言,使用廠商提供的軟件包要優於使用最新、最棒的代碼。有些時候,性能調優和系統管理的目標會有所衝突。若是使用商業版的 Linux 或依賴於第三方支持,那麼可能不得不考慮廠商的支持。

若是您獨斷獨行,那麼請學會如何構建能與您的發佈版協同工做的包,請學會如何將其集成到補丁系統之中。這將確保軟件,以及您做出的任何更改獲得一致的構建,且能跨多個系統使用。還應訂閱恰當的郵件列表和 RSS 提要來及時得到軟件更新。

prefork 模型會爲每一個請求建立一個新進程。多餘的進程保持空閒,以處理傳入的請求,這縮短了啓動延遲。只要 Web 服務器出現,預先完成的配置就會當即啓動 50 個進程,並盡力保持 10 到 20 個空閒服務器運行。進程數的硬性限制由 MaxClients 指定。儘管一個進程可以處理許多相繼的請求,Apache 仍是會取消鏈接數超過 4,000 之後的進程,這下降了內存泄漏的風險。

配置線程化 MPM 與之相似,不一樣之處只是必須肯定使用多少線程和進程。Apache 文檔解釋了全部必要的參數和計算。

要通過幾回嘗試和出錯以後才能選好要使用的值。最重要的值是 MaxClients。目標在於容許足夠多的 workder 進程或線程運行,同時又不會致使服務器進行過分的交換。若是傳入的請求超出處理能力,那麼至少知足此值的那些請求會獲得服務,其餘請求被阻塞。

若是 MaxClients 太高,那麼全部客戶機都將體驗到糟糕的服務,由於 Web 服務器會試圖換出一個進程,以使另外一個進程可以運行。而設得太低意味着可能會沒必要要地拒絕服務。查看高負載下運行的進程數量和全部 Apache 進程所致使的內存佔用狀況對設置這個值頗有幫助。若是 MaxClients 的值超過 256,必須將 ServerLimit 也設爲一樣的數值,請仔細閱讀 MPM 的文檔,瞭解相關信息。

根據服務器的角色調優要啓動和保持空閒的服務器數量。若是服務器僅運行 Apache,那麼可使用適中的值,如 清單 1 所示,由於這樣就能充分利用機器。若是系統中還有其餘數據庫或服務器,那麼就應該限制運行中的空閒服務器的數量。

有效地使用選項和重寫

Apache 處理的每一個請求都要履行一套複雜的規則,這些規則指明瞭 Web 服務器必須遵循的約束或特殊指令。對文件夾的訪問可能按 IP 地址約束爲某個特定文件夾,也可配置用戶名和密碼。這些選項還包含處理特定文件,例如,若是提供了一個目錄列表,該如何處理的文件,或輸出結果是否應壓縮。

這些配置以 httpd.conf 中容器的形式出現,例如 <Directory>,以便指定所用配置引用的是磁盤上的一個位置;再如 <Location>,表示引用是 URL 中的路徑。清單 2 展現了一個實際的 Directory 容器。


清單 2. 爲根目錄應用的一個 Directory 容器

                
<Directory />
    AllowOverride None
    Options FollowSymLinks
</Directory>

 

在清單 2 中,位於一對 Directory/Directory 標記之間的配置應用於給定目錄和該目錄下的一切內容 —— 在本例中,這個給定目錄是根目錄。此處,AllowOverride 標記指出,用戶不容許重寫任何選項(稍後將進一步介紹)。FollowSymLinks 選項被啓用,它容許 Apache 查看以前的符號鏈接來爲請求提供服務,即使文件位於包含 Web 文件的目錄以外。這就意味着,若是 Web 目錄中的一個文件是 /etc/passwd 的符號鏈接,Web 服務器將在請求時順利爲該文件提供服務。若是使用了 -FollowSymLinks,該特性就會被禁用,一樣的請求將導致爲客戶機返回錯誤。

最後這個場景正是致使兩方面關注的緣由所在。第一個方面與性能有關。若是禁用了 FollowSymLinks,Apache 就必須檢查使用該文件名的全部組件(目錄和文件自己),以確保它們不是符號鏈接。這會帶來額外的開銷(磁盤操做)。另一個稱爲 FollowSymLinksIfOwnerMatch 的選項會在文件全部者與鏈接全部者相同時使用符號鏈接。爲得到最佳性能,請使用 清單 2 中的選項。

至此,有安全意識的讀者應該有了警戒的感受。安全性永遠是功能性與風險之間的權衡。在咱們的例子中,功能性是速度,而風險是容許對系統上的文件進行未經受權的訪問。緩解風險的措施之一是 LAMP 應用服務器一般專一於一種具體功能,用戶沒法建立危險的符號鏈接。若是有必要啓用符號鏈接,那麼能夠將其約束在文件系統的特定區域,如清單 3 所示。


清單 3. 將 FollowSymLinks 約束爲一個用戶的目錄

                
<Directory />
   Options FollowSymLinks
</Directory>

<Directory /home/*/public_html>
   Options -FollowSymLinks
</Directory>

 

在清單 3 中,一個用戶的主目錄中的任何 public_html 目錄及其全部子目錄都移除了 FollowSymLinks 選項。

如您所見,經過主服務器配置,可爲每一個目錄單獨配置選項。用戶能夠自行重寫這種服務器配置(若是管理員經過 AllowOverrides 語句容許了這種操做),只需將一個 .htaccess 文件放入目錄便可。該文件包含額外的服務器指令,每次請求包含 .htaccess 文件的目錄時將加載並應用這些指令。儘管以前探討過系統沒有用戶的問題,但許多 LAMP 應用程序都利用這種功能性來控制訪問、實現 URL 重寫,所以有必要理解其工做原理。

即使 AllowOverrides 語句能阻止用戶去作您不但願他們作的事,Apache 也必須檢查 .htaccess 文件,看看是否有要完成的工做。父目錄能夠指定由來自子目錄的請求處理的指令,這也就表示,Apache 必須搜索所請求文件的目錄樹的全部組件。可想而知,這會使每次請求都致使大量磁盤操做。

最簡單的解決方案是不容許重寫,這能消除 Apache 檢查 .htaccess 的需求。以後的任何特殊配置都將直接放在 httpd.conf 中。清單 4 顯示爲對一個用戶的項目目錄進行密碼檢查向 httpd.conf 增長的代碼,而不是將其放入一個 .htaccess 文件並依賴於 AllowOverrides


清單 4. 將 .htaccess 配置移入 httpd.conf

                
<Directory /home/user/public_html/project/>
  AuthUserFile /home/user/.htpasswd
  AuthName "uber secret project"
  AuthType basic
  Require valid-user
</Directory>

 

若是配置轉移到 httpd.conf 中,且 AllowOverrides 被禁用,磁盤的使用就能減小。一個用戶的項目可能不會吸引許多人來點擊,但設想一下,將這項技術應用於一個忙碌的站點時會有多麼強大。

有時不可能完全消除 .htaccess 文件的使用。例如,在清單 5 中,一個選項被約束到文件系統的特定部分,重寫也能夠是有做用域的。


清單 5. 限定 .htaccess 檢查的做用域

                
<Directory />
  AllowOverrides None
</Directory>

<Directory /home/*/public_html>
  AllowOverrides AuthConfig
</Directory>

 

實現清單 5 以後,Apache 會在父目錄中查找 .htaccess 文件,但會在 public_html 目錄處中止,由於文件系統的其他部分禁用了此功能。例如,若是請求的是一個映射到 /home/user/public_html/project/notes.html 的文件,那麼僅有 public_html 和 project 目錄被搜索。

關於每目錄單獨配置的最後一個提示就是:要按順序依次進行。任何介紹 Apache 調優的的文章都會告訴您,應經過 HostnameLookups off 指令禁用 DNS 查找,由於試圖反向解析鏈接到您的服務器的全部 IP 地址無疑是浪費資源。然而,基於主機名的任何約束都會迫使 Web 服務器對客戶機的 IP 地址執行反向查找,對其結果進行正向查找,以驗證該名稱的真實性。所以,避免使用基於客戶主機名的訪問控制,在必須使用時限定其做用域,這些都是明智的作法。

持久鏈接

一個客戶機鏈接到 Web 服務器時,容許客戶機經過同一個 TCP 鏈接發出多個請求,這減小了與多個鏈接相關的延遲。在一個 Web 頁面引用了多幅圖片時,這就頗有用:客戶機能夠經過一個鏈接先請求頁面,再請求全部圖片。其缺點在於服務器上的 worker 進程必須等待客戶機要關閉的會話,以後才能轉到下一個請求。

Apache 使您可以配置如何處理持久鏈接(稱爲 keepalives)。httpd.conf 全局級的 KeepAlive 5 容許服務器在鏈接強制關閉以前處理一個鏈接上的 5 個請求。將此值設置爲 0 將禁用持久鏈接。一樣位於全局級上的 KeepAliveTimeout 肯定在會話關閉以前,Apache 將等待另一個鏈接多久。

持久鏈接的處理並不是 「一刀切」 式的配置。對於某些 Web 站點,禁用 keepalives 更合適(KeepAlive 0);而對於其餘一些站點,啓用它會帶來巨大的收益。唯一的解決之道就是嘗試使用這兩種配置,本身觀察哪一種更合適。但若啓用了 keepalives,使用較小的超時時間較爲明智,例如 2,即 KeepAliveTimeout 2。這能確保但願發出另一個請求的客戶機有充足的時間,還能確保 worker 進程不會一直空閒,等待可能永遠不會出現的下一個請求。

壓縮

Web 服務器可以在將輸出發回給客戶機以前壓縮它。這將使經過 Internet 發送的頁面更小,代價是 Web 服務器上的 CPU 週期。對於那些負擔得起 CPU 開銷的服務器來講,這是提升頁面下載速度的好辦法 —— 頁面壓縮後大小變爲原來的三分之一這種事情並不罕見。

圖片一般已是壓縮過的,所以壓縮應僅限於文本輸出。Apache 經過 mod_deflate 提供壓縮。儘管 mod_deflate 可輕鬆啓用,但它涉及到太多的複雜性,不少手冊都解釋了這些複雜的內容。本文不會介紹壓縮的配置,但提供了相應文檔的連接(參見 參考資料 部分)。

調優 PHP

PHP 是運行應用程序代碼的引擎。應該僅安裝計劃使用的那些模塊,並配置您的 Web 服務器,使之僅爲腳本文件(一般是以 .php 結尾的那些文件)使用 PHP,而非全部靜態文件。

操做碼緩存

請求一個 PHP 腳本時,PHP 會讀取該腳本,並將其編譯爲 Zend 操做碼,這是要執行的代碼的一種二進制表示形式。隨後,此操做碼由 PHP 執行並丟棄。操做碼緩存將保存這個編譯後的操做碼,並在下一次調用該頁面時重用它。這會節省不少時間。有多種緩存可用,我比較經常使用的是 eAccelerator。

要安裝 eAccelerator,您的計算機上須要有 PHP 開發庫。因爲不一樣的 Linux 發佈版存放文件的位置不一樣,因此最好直接從 eAccelerator 的 Web 站點得到安裝說明(參見 參考資料 部分得到連接)。您的發佈版也有可能已經包含了一個操做碼緩存,只需安裝便可。

不管如何在系統上安裝 eAccelerator,都有一些配置選項須要注意。配置文件一般是 /etc/php.d/eaccelerator.ini。eaccelerator.shm_size 定義共享高速緩存的大小,編譯後的腳本就存儲在這裏。該值的單位是兆字節(MB)。根據您的應用程序肯定恰當的大小。eAccelerator 提供了一個腳原本顯示緩存的狀態,其中包含內存佔用,64MB 是個不錯的選擇(eaccelerator.shm_size="64")。若是您選擇的值未被接受,那麼必須修改內核的最大共享內存的大小。向 /etc/sysctl.conf 添加 kernel.shmmax=67108864,運行 sysctl -p 來使設置生效。kernel.shmmax 值的單位是字節。

若是共享內存的分配超出極限,eAccelerator 必須將舊腳本從內存中清除。默認狀況下,這是被禁用的;eaccelerator.shm_ttl = "60" 指定:當 eAccelerator 用完共享內存時,60 秒內未被訪問的全部腳本都將被清除。

另外一種流行的 eAccelerator 替代工具是 Alternative PHP Cache(APC)。Zend 的廠商也提供了一種商業操做碼緩存,包括一個進一步提升效率的優化器。

php.ini

PHP 的配置是在 php.ini 中完成的。四個重要的設置控制 PHP 可以使用多少系統資源,如表 1 所列。


表 1. php.ini 中與資源相關的設置

設置 描述 建議值
max_execution_time 一個腳本可以使用多少 CPU 秒 30
max_input_time 一個腳本等待輸入數據的時間有多長(秒) 60
memory_limit 在被取消以前,一個腳本可以使用多少內存(字節) 32M
output_buffering 數據發送給客戶機以前,有多少數據(字節)須要緩存 4096

具體數字主要取決於您的應用程序。若是要從用戶處接收大文件,那麼 max_input_time 可能必須增長,能夠在 php.ini 中修改,也能夠經過代碼重寫它。與之相似,CPU 或內存佔用較多的程序也可能須要更大的設置值。目標就是緩解超標程序的影響,所以不建議全局禁用這些設置。關於 max_execution_time,還有一點須要注意:它表示進程的 CPU 時間,而不是絕對時間。所以一個進行大量 I/O 和少許計算的程序的運行時間可能遠遠超過 max_execution_time。這也是 max_input_time 能夠大於 max_execution_time 的緣由所在。

PHP 可執行的日誌記錄數是可配置的。在生產環境中,禁用除最重要的日誌之外的一切日誌記錄可以減小磁盤寫操做。若是須要使用日誌來排除問題,那麼能夠按需啓用日誌記錄。error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR 將啓用足夠的日誌記錄,使您發現問題,同時從腳本中消除大量無用的內容。

相關文章
相關標籤/搜索