本文發表在《程序員》雜志2008年第11期
PHP沉思錄之六:Drupal的性能問題
左輕侯
Drupal是一個基于PHP的開源CMS系統,也是我認為技術上實現得最好的一個PHP應用。Drupal的架構非常優秀,通過微內核+plugin的方式,實現了極佳的擴展性,從而使Drupal遠遠超出一般的CMS這一范疇。從這個意義上來說,把Drupal稱為Web OS似乎更加合適一些。關于Drupal,有太多的話可以說,也許我會在以后的時間里寫一篇文章對它進行專門的討論。但是在本文中,我想討論的,是Drupal社區中的每一個人都會面對,但不是每一個人都對其有清晰認識的問題,即Drupal的性能問題。
因為客戶需求,我曾經對Drupal做過比較全面的測試。當時的環境是雙服務器(DB server+Web Server),硬件配置都是單CPU+4G。數據庫里面有幾千條Node記錄。用JMeter對各種情況下(開/關各種cache模塊,logged user/anonymous user)不同頁面的讀取和寫入操作都進行過測試。
測試的結果可能和很多人印象中不一樣。兩個主要的結果如下:
1. Logged user和anonymous user的性能差距非常大。同一個頁面,logged user的RPS(Requests per second)一般不超過20,而啟用了cache的anonymous user的RPS在100多,當使用了file-based cache以后,甚至能超過300。
2. 數據庫壓力相對較小。由于Drupal把大量可配置的內容都放在數據庫中,因此往往容易產生這樣一種印象,即Drupal對數據庫要求應該是很高的。但事實上,無論是cache還是非cache模式,DB server的壓力都相當?。–PU在10%以下),而Web Server的CPU在80%以上。跟蹤所有的db query的執行時間后,也證明了這一點(全部db query的執行時間只占頁面生成時間的一小部分)。
經過反復的測試和思考,我得出了一些結論。很明顯,Drupal在大量logged user并發情況下的瓶頸,在于執行Drupal代碼的CPU時間,而不是在于數據庫或者其他地方。之所以出現這樣的情況,和PHP本身的執行機制和Drupal的實現方式有關。Drupal在生成一個非cached的頁面時,不管這個頁面多么簡單,都要執行一個完整的bootstrap過程,即使只啟用了最少的模塊,這個過程也要調用幾十個PHP文件,執行成千上萬行PHP代碼。而PHP的機制又決定了沒有任何PHP代碼或者對象能夠駐留內存,每次響應請求都必須執行完整的初始化工作。而anonymous user之所以快,是因為Drupal在執行cached page的時候,不會執行完整的bootstrap過程,它先檢查是否cached page,是的話就讀取緩存,然后結束工作。這樣當然就快了。
以這個結論為前提,可以解釋一些事情:
1. 為什么Drupal的性能在各種環境下相差并不多。無論是雙服務器,單服務器,甚至內存非常小的虛擬機,logged user的RPS值往往總是在10~20之間。數據庫里面有幾百條,或者幾十萬條記錄,影響也不大。因為瓶頸并不在于DB或者內存,而是在于執行代碼的過程。
2. 為什么使用APC/XCache這樣的代碼優化程序,能夠得到極大的性能提升。在我自己的虛擬機環境上,RPS從3~4提升到了12。因為它提升的是PHP代碼的執行時間。
從這個結論出發,列出一些對優化Drupal的logged user性能有明顯作用和沒有明顯作用的措施:
沒有明顯作用的:
1. 加內存。在并發數只有10+的時候,即使每個請求占20M內存,也只有200M+內存而已。
2. DB server和Web server分開,或者增強DB server的配置。一臺中等性能的mysql服務器,應付200~300的并發是很輕松的事情,在并發數只有10+的時候,db server實際上是很空閑的。
3. 基礎軟件的優化,例如從Windows轉移到Linux,從apache轉移到Lighttpd,從html' target='_blank'>MySQL遷移到其他數據庫,除了從Windows轉移到 Linux會有比較明顯的提升以外(因為PHP在Linux上的效率比在Windows上要好),其它的措施可能會快一些,但不會有大幅度的提高,因為瓶頸不在那里。
有明顯作用的:
1. 使用APC/XCache這樣的代碼優化程序,速度會有幾倍的提升。估計大家都已經這樣做過了。
2. 增加web server的CPU數量。雙核的肯定比單核的快,4個CPU肯定比2個CPU快得多。
3. 使用多web server+單db server的配置,把代碼執行的壓力分散到不同的web server上。上文說到,單臺db server可以輕松應付200+的并發,這意味著理論上可以支持10臺以上的web server。
4. 使用Quercus這樣的引擎,把PHP代碼編譯成Java,再在Java VM中運行,理論上會有很大的提高。原因是,第一,Java的運行效率比PHP高,第二,Java代碼是可以cache的,不需要每次都重新加載。這里有個測試結果:http://www.workhabit.org/resin-backed-php-drives-4x-performance-improvements-drupal 。Drupal在Quercus下有4倍的性能提高,但是這個數字跟Drupal在打開APC/eAccelerator下的提升差不多,所以可能沒有太大的實用價值。
另外一種思路是代碼本身的優化。
使用cache API基本上是沒有意義的,因為對于logger user,Drupal不會調用cache API。Drupal.org上有人提出,即使是logged user,有很多頁面也是不用定制化的,這意味著可以cache它們。但是Drupal沒有提供這樣一種機制。只要是logged user,Drupal就會執行完整的bootstrap過程,即使只打印出一個hello world,因此實際上你沒有辦法在logged user狀態下cache單個頁面。
到目前最新版本的Drupal(Drupal 6.4)為止,對于logger user,Drupal只提供了一種cache功能,就是可以將部分block設置為可cache的。在block占用大量服務器時間的情況下,block cache能夠有效地提高效率。但是,由于block cache對于bootstrap過程并無影響,因此當瓶頸在于bootstrap本身時,Block cache是無能為力的。
在Drupal.org的社區,關于logger user的cache問題,一直處于熱烈的討論之中?;镜慕Y論是,由于Drupal的架構就是這樣,目前沒有很好的解決方案,只能期待Drupal在以后的版本中進行改進了。
我研究了一下Drupal的bootstrap過程,發現也許這樣是可行的:實現hook_boot函數,這是bootstrap中執行最靠前的一個函數,它被調用時,bootstrap的大部分過程還沒有執行。在hook_boot中,檢查當前頁面是否需要cache,如果是,直接讀 cache生成頁面,然后調用exit()強行結束。這在理論上是可行的,但太過hack了一點。
Drupal的情況是這樣,那么其他的PHP框架,尤其是半官方的Zend Framework,性能如何呢?通過搜索,我在網上找到了一份PHP framework comparison benchmarks,網址見:http://www.avnetlabs.com/php/php-framework-comparison-benchmarks。根據這份報告的數據,Zend Framework的性能只有原生PHP的10%,如果沒有用APC,連3%都不到。當然,這份報告的數據不一定詳盡,Zend Framework在不同環境下的表現應該也會有出入。但是,Zend Framework的性能大幅度落后于Baseline PHP,應該是確鑿無疑的。
為什么PHP主流框架的性能都存在著這樣的問題呢?其實這也不難理解?;仡橮HP沉思錄系列第一篇中對于PHP工作模型的討論,由于PHP沒有駐留內存的進程,所以每一個request發生時,都必須初始化所有的對象,這導致大量的時間被耗費在進程代碼的執行過程中。當PHP程序僅僅是簡單的腳本時,這無關緊要,但是在結構復雜的架構中,由于每次處理request都要重復調用成千上萬行代碼,這一問題就變得非常突出了。而且,除非PHP以后的版本對這一機制進行改進,否則這個問題無法得到徹底的解決。
那么,這是否意味著,PHP只能適用于小型的網站,而無法在高并發量的大型網站施展拳腳呢?當然不是這樣。事實上,在Yahoo和其他許多知名的巨型網站上,都大量地使用了PHP。原因在于,PHP僅僅被用作一個內容生成器,生成的內容會被轉化為靜態文本,絕大多數用戶瀏覽的都是被cache的靜態文本。這就和PHP程序的性能毫無關系了。但是,當用戶并不是僅僅進行瀏覽,而是需要頻繁地和網站進行互動時,PHP的性能不但無法比擬C和Java,甚至無法與同為腳本語言的Python和Ruby相比。也就是說,PHP更適合于新聞門戶這樣的內容發布站點,而不是web 2.0應用的首選。
在本系列文章告一段落的時候,我們看到的是PHP的局限性。熱愛PHP的人們可能會對此覺得沮喪。但是,這并無損于PHP作為一門優秀語言的聲譽。尺有所短,寸有所長,對于我們熟悉和喜愛的工具,我們更應該了解它們的局限,這也有利于我們更有效地使用它們。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答