1. 502 Bad Gateway
502badgateway要先找到nginx配置的路徑。
然後找到nginx所在的error日誌文件來查看具體原因。
如果是客戶端瀏覽器配置的問題,以360瀏覽器為例,出現502BadGateway可能是設置了代代理導致的。
取消瀏覽器代理之後,刷新一下就可以訪問了。
502BadGateway是一種報錯提示,這一錯誤並不意味著上游伺服器已關閉(無響應網關/代理),而是上游伺服器和網關/代理不同意的協議交換數據。
鑒於互聯網協議是相當清楚的,它往往意味著一個或兩個機器已不正確或不完全編程。
2. 伺服器程序源代碼分析之二:php-fpm
php作為排名top2 互聯網開發工具,非常流行,可以參考:中國最大的25個網站採用技術選型方案
php這個名稱實際上有兩層含義
直接定義:
php-fpm從php5.3.3開始已經進入到php源代碼包,之前是作為patch存在的
很少人會去讀php本身源代碼,我6年前解決php內存泄露問題的時候做了些研究,最近再查看了一番,發現php的開發者很有誠意,這是一款非常出色的伺服器軟體,支持如下
在linux伺服器上,如果不設置 events.mechanism ,那麼默認就是採用epoll,所以
php-fpm的IO模型&並發處理能力和nginx是完全一致
nginx以性能卓越聞名,大部分程序員都認為php效率低下,看了源代碼,才知道這是傳奇啊
在高性能部署的時候,大家往往會針對性的優化nginx 。我自己之前部署php程序也犯了錯誤,8G內存的server,php-fpm的max children都會設置128+,現在看來太多了,參考nginx的部署:
php-fpm配置為 3倍 cpu core number就可以了
php-fpm穩定性比nginx稍差 這是因為php-fpm內置了一個php解析器,php-fpm進程就和php程序捆綁了,如果php腳本寫得不好,有死循環或者阻塞在某個遠端資源上,會拖累載入它的php-fpm進程
而nginx和後端應用伺服器之間通過網路連接,可以設置timeout,不容易堵死的
php-fpm的fastcgi是短連接 我原以為是長連接的,看了代碼才知道也是短連接,處理一個request就關閉掉
php-fpm介面採用fastcgi 非常遺憾,php-fpm和fastcgi完全綁定了,無法獨立使用 。只能部署在支持http-fcgi協議轉換程序背後(nginx)。其實可以考慮在php-fpm代碼包裡面引入http協議支持,這樣php-fpm可以獨立運行,讓nodejs無話可說
php-fpm等同於OpenResty OpenResty是一個國人開發的nginx模塊,就是在nginx引入lua解釋器. 實際上,它和php-fpm的唯一差別就是一個採用php語法,一個用lua,所以OpenResty要作為nginx增強包使用還可以,要選擇它作為一個主要編程工具,沒有任何必要
從架構上來說,php-fpm已經做到最好,超過大多數 python部署工具,我再也不黑它了
3. 如何進行網站性能優化
一、前端優化
網站性能優化是一個很綜合的話題,涉及到伺服器的配置和網站前後端程序等各個方面,我只是從實際經歷出發,分享一下自己所嘗試過的網站性能優化方法。之所以在標題上掛一個web2.0,是因為本文更偏重於中小網站的性能優化,我所使用的系統也是典型web2.0的LAMP架構。
首先講講前端的優化,用戶訪問網頁的等待時間,有80%是發生在瀏覽器前端,特別是頁面和頁面中各種元素(圖片、CSS、javascript、 flash…)的下載之上。因此在很多情況下,相對於把大量的時間花在艱苦而繁雜的程序改進上,前端的優化往往能起到事半功倍的作用。雅虎最近將內部使用的性能測試工具yslow向第三方公開,並發布了著名的網站性能優化的十三條規則,建議你下載並安裝yslow,並作為測評網站優化效果的工具。下面我挑其中特別有價值的具體說明一下優化的方法:
對於第一次訪問您網站,尚未在瀏覽器cache中緩存您網站內容的用戶,我們可以做的事情包括:
1)減少一個頁面訪問所產生的http連接次數
對於第一次訪問你網站的用戶,頁面所產生的http連接次數是影響性能的一個關鍵瓶頸。
對策:
- 盡量簡潔的頁面設計,最大程度減少圖片的使用,通過放棄一些不必要的頁面特效來減少javascript的使用。
- 使用一些優化技巧,比如利用圖片的背景位移減少圖片的個數;image map技術;使用Inline images將css圖片捆綁到網頁中。
- 盡量合並js和css文件,減少獨立文件個數。
2) 使用gzip壓縮網頁內容
使用gzip來壓縮網頁中的靜態內容,能夠顯著減少用戶訪問網頁時的等待時間(據說可達到60%)。主流的web伺服器都支持或提供gzip壓縮,如果使用apache伺服器,只需要在配置文件中開啟 mod_gzip(apache1.x)或mod_deflate(apache2.x)即可。凡是靜態的頁面,使用gzip壓縮都能夠顯著提高伺服器效率並減少帶寬支出,注意圖片內容本身已經是壓縮格式了,務必不要再進行壓縮。
3)將CSS放在頁面頂端,JS文件放在頁面底端
CSS的引用要放在html的頭部header中,JS文件引用盡量放在頁面底端標簽的後面,主要的思路是讓核心的頁面內容盡早顯示出來。不過要注意,一些大量使用js的頁面,可能有一些js文件放在底端會引起一些難以預料的問題,根據實際情況適當運用即可。
4)使JS文件內容最小化
具體來說就是使用一些javascript壓縮工具對js腳本進行壓縮,去除其中的空白字元、注釋,最小化變數名等。在使用gzip壓縮的基礎上,對js內容的壓縮能夠將性能再提高5%。
5)盡量減少外部腳本的使用,減少DNS查詢時間
不要在網頁中引用太多的外部腳本,首先,一次dns的解析過程會消耗20-120毫秒的時間;其次,如果在頁面中引用太多的外部文件(如各種廣告、聯盟等代碼),可能會因為外部文件的響應速度而將你的網站拖得很慢。如果不得不用,那麼就盡量將這些腳本放在頁腳吧。不過有一點需要提及,就是瀏覽器一般只能並行處理同一域名下的兩個請求,而對於不同子的域名則不受此限制,因此適當將本站靜態內容(css,js)放在其他的子域名下(如 static.xxx.com)會有利於提高瀏覽器並行下載網頁內容的能力。
對於您網站的經常性訪問用戶,主要的優化思路就是最大限度利用用戶瀏覽器的cache來減少伺服器的開銷。
1)在header中添加過期時間(Expires Header)
在header中給靜態內容添加一個較長的過期時間,這樣可以使用戶今後訪問只讀取緩存中的文件,而不會與伺服器產生任何的交互。不過這樣做也存在一些問題,當圖片、CSS和js文件更新時,用戶如果不刷新瀏覽器,就無法獲得此更新。這樣,我們在對圖片、css和js文件修改時,必須要進行重命名,才能保證用戶訪問到最新的內容。這可能會給開發造成不小的麻煩,因為這些文件可能被站點中的許多文件所引用。flickr提出的解決辦法是通過url rewrite使不同版本號的URL事實上指向同一個文件,這是一個聰明的辦法,因為url級別的操作效率是很高的,可以給開發過程提供不少便利。
要理解為什麼這樣做,必須要了解瀏覽器訪問url時的工作機制:
a. 第一次訪問url時,用戶從伺服器段獲取頁面內容,並把相關的文件(images,css,js…)放在高速緩存中,也會把文件頭中的expired time,last modified, ETags等相關信息也一同保留下來。
b. 用戶重復訪問url時,瀏覽器首先看高速緩存中是否有本站同名的文件,如果有,則檢查文件的過期時間;如果尚未過期,則直接從緩存中讀取文件,不再訪問伺服器。
c. 如果緩存中文件的過期時間不存在或已超出,則瀏覽器會訪問伺服器獲取文件的頭信息,檢查last modifed和ETags等信息,如果發現本地緩存中的文件在上次訪問後沒被修改,則使用本地緩存中的文件;如果修改過,則從伺服器上獲取最新版本。
我的經驗,如果可能,盡量遵循此原則給靜態文件添加過期時間,這樣可以大幅度減少用戶對伺服器資源的重復訪問。
2)將css和js文件放在獨立外部文件中引用
將css和js文件放在獨立文件中,這樣它們會被單獨緩存起來,在訪問其他頁面時可以從瀏覽器的高速緩存中直接讀取。一些網站的首頁可能是例外的,這些首頁的自身瀏覽可能並不大,但卻是用戶訪問網站的第一印象以及導向到其他頁面的起點,也可能這些頁面本身使用了大量的ajax局部刷新及技術,這時可以將 css和js文件直接寫在頁面中。
3)去掉重復的腳本
在IE中,包含重復的js腳本會導致瀏覽器的緩存不被使用,仔細檢查一下你的程序,去掉重復引用的腳本應該不是一件很難的事情。
4)避免重定向的發生
除了在header中人為的重定向之外,網頁重定向常在不經意間發生,被重定向的內容將不會使用瀏覽器的緩存。比如用戶在訪問,伺服器會通過301轉向到/,在後面加了一個「/」。如果伺服器的配置不好,這也會給伺服器帶來額外的負擔。通過配置apache的 alias或使用mod_rewrite模塊等方法,可以避免不必要的重定向。
還有一些,比如使用CDN分發機制、避免CSS表達式等、避免使用ETags等,因為不太常用,這里就不再贅述了。
做完了上述的優化,可以試著用yslow測試一下網頁的性能評分,一般都可以達到70分以上了。
當然,除了瀏覽器前端和靜態內容的優化之外,還有針對程序腳本、伺服器、資料庫、負載的優化,這些更深層次的優化方法對技術有更高的要求。本文的後半部分將重點探討後端的優化。
二、後端優化
上次寫完web2.0網站前端優化篇之後,一直想寫寫後端優化的方法,今天終於有時間將思路整理了出來。
前端優化可以避免我們造成無謂的伺服器和帶寬資源浪費,但隨著網站訪問量的增加,僅靠前端優化已經不能解決所有問題了,後端軟體處理並行請求的能力、程序運 行的效率、硬體性能以及系統的可擴展性,將成為影響網站性能和穩定的關鍵瓶頸所在。優化系統和程序的性能可以從以下的方面來入手:
1)apache、mysql等軟體的配置的優化
盡管apache和mysql等軟體在安裝後使用的默認設置足以使你的網站運行起來,但是通過調整mysql和apache的一些系統參數,還是可以追求更高的效率和穩定性。這個領域中有很多專業的文章和論壇(比如: ),要想掌握也需要進行深入的研究和實踐,這里就不重點討論了。
2)應用程序環境加速
這里僅以我最常應用的php開發環境為例,有一些工具軟體可以通過優化PHP運行環境來達到提速的目的,其基本原理大致是將PHP代碼預編譯並緩存起來,而不需要改變任何代碼,所以比較簡單,可以將php的運行效率提升50%以上。比較常用的php加速工具有:APC( http: //pecl.php.net/package-info.php?package=APC)、Turck MMCache( )、php accelebrator(),還有收費的Zend Performance Suite
3)將靜態內容和動態內容分開處理
apache是一個功能完善但比較龐大的web server,它的資源佔用基本上和同時運行的進程數呈正比,對伺服器內存的消耗比較大,處理並行任務的效率也一般。在一些情況下,我們可以用比較輕量級的web server來host靜態的圖片、樣式表和javascript文件,這樣可以大大提升靜態文件的處理速度,還可以減少對內存佔用。我使用的web server是來自俄羅斯的nginx,其他選擇方案還包括lighttpd和thttpd等。
4)基於反向代理的前端訪問負載均衡
當一台前端伺服器不足以應付用戶訪問時,通過前端機實現web訪問的負載均衡是最快速可行的方案。通過apache的mod_proxy可以實現基於反向代理的負載均衡,這里推薦使用nginx做代理伺服器,處理速度較apache更快一些。
5)應用緩存技術提高資料庫效能,文件緩存和分布式緩存
資料庫訪問處理並發訪問的能力是很多網站應用的關鍵瓶頸,在想到使用主從結構和多farm的方式構建伺服器集群之前,首先應該確保充分使用了資料庫查詢的緩存。一些資料庫類型(如mysql的innoDB)自身內置對緩存的支持,此外,還可以利用程序方法將常用的查詢通過文件或內存緩存起來。比如通過 php中的ob_start和文件讀寫函數可以很方便的實現文件形式的緩存,而如果你擁有多台伺服器,可以通過memcache技術通過分布式共享內存來對資料庫查詢進行緩存,不僅效率高而且擴展性好,memcache技術在livejournal和Craigslist.org等知名網站應用中都得到了檢驗。
6)伺服器運行狀態的檢測,找到影響性能的瓶頸所在
系統優化沒有一勞永逸的方法,需要通過檢測伺服器的運行狀態來及時發現影響性能的瓶頸,以及可能存在的潛在問題,因為網站的性能,永遠取決於木桶中的短板。可以編寫一些腳本來檢測web服務的運行,也有一些開源的軟體也提供了很好的功能
7)良好的擴展架構是穩定和性能的基礎
一些技巧和竅門可以幫你度過眼前的難關,但要想使網站具備應付大規模訪問的能力,則需要從系統架構上進行徹底的規劃,好在很多前人無私的把他們架構
網站的經驗分享給我們,使我們可以少走甚多彎路。我最近讀到的兩篇有啟發的文章:
- 從LiveJournal後台發展看大規模網站性能優化方法
- Myspace的六次重構
最後不得不提到程序編碼和資料庫結構對性能的影響,一系列糟糕的循環語句,一個不合理的查詢語句、一張設計不佳的數據表或索引表,都足以會使應用程序運行的速度成倍的降低。培養全局思考的能力,養成良好的編程習慣,並對資料庫運行機制有所了解,是提高編程質量的基礎。
4. PHP的性能探討和測試
1.緣起
關於PHP,很多人的直觀感覺是PHP是一種靈活的腳本語言,庫類豐富,使用簡單,安全,非常適合WEB開發,但性能低下。PHP的性能是否真的就如同大家的感覺一樣的差呢?本文就是圍繞這么一個話題來進陵搏行探討的。從源碼、應用場景、基準性能、對比分析等幾個方面深入分析PHP之性能問題,並通過真實的數據來說話。
2.從原理分析PHP性能
從原理分析PHP的性能,主要從以下幾個方面:內存管理、變數、函數、運行機制來進行分析。
2.1內存管理
類似Nginx的內存管理方式,PHP在內部也是基於內存池,並且引入內存池的生命周期概念。在內存池方面,PHP對PHP腳本和擴展的所有內存相關操作都進行了託管。對大內存和小內存的管理採用了不同的實現方式和優化,具體可以參考以下文檔:
2.2變數
總所周知,PHP是一種弱變數類型的語言,所以在PHP內部,所有的PHP變數都對應成一種類型Zval,其中具體定義如下:
在變數方面,PHP做了大量的優化工作,比如說Reference counting和 on writer機制。這樣能夠保證內存使用上的優化,並且減少內存拷貝次數(請參考
2.3函數
在PHP內部,所有的PHP函數都回轉化成內部的一個函數指針。比如說擴展中函數
ZEND_FUNCTION(my_function);//類似functionmy_function(){}
在內部展開後就會是一個函數
voidzif_my_function(INTERNAL_FUNCTION_PARAMETERS);
voidzif_my_function(intht,
zval*return_value,
zval*this_ptr,
intreturn_value_used,
zend_executor_globals*executor_globals);
從這個角度來看,PHP函數在內部也是對應一個函數指針。
2.4運行機制
在話說PHP性能的時候,很多人都會說「C/C++是編譯型,JAVA是半編譯型,PHP是解釋型」。也就是說PHP是先動態解析再代碼運行的,所以從這個角度來看,PHP性能必然很差。
的確,從PHP腳本運行來輸出,的確是一個動態解析再代碼運行的過程。具體來說,PHP腳本的運行機制如下圖所示:
PHP的運行階段也分成三個階段:
Parse。語法分析階段。
Compile。編譯產出opcode中間碼。
Execute。運行,動態運行進行輸出。
所以說,在PHP內部,本身也是存在編譯的過程。並且據此產生了大量的opcode cache工具,比如說apc、eacc、xcache等等。這些opcode cache在生產環境基本上在標配。基於opcode cache,能到做到「PHP腳本編譯一次,多次運行」的效果。從這點上,PHP就和JAVA的半編譯機制非常類似。
所以,從運行機制上來看,PHP的運行模式和JAVA是非常類似的,都是先產生中間碼,然後運行在不同虛擬機上。
2.5動態運行
從上面的幾個分析來看,PHP在內存管理、變數、函數、運行機制等幾個方面都做了大量的工作,所以從原理來看,PHP不應該存在性能尺御祥問題,性能至少也應該和Java比較接近。
這個時候就不得不談PHP動態語言的特性所帶來的性能問題了,由於PHP是動態運行時,所以所有的變數、函數、對象調用、作用域實現等等都是在執行階段中才確定的。這個從根本上決定了PHP性能中很難改變的一些東西:在C/C++等拆蔽能夠在靜態編譯階段確定的變數、函數,在PHP中需要在動態運行中確定,也就決定了PHP中間碼不能直接運行而需要運行在Zend Engine上。
說到PHP變數的具體實現,又不得不說一個東西了:Hashtable。Hashtable可以說在PHP靈魂之一,在PHP內部廣泛用到,包含變數符號棧、函數符號棧等等都是基於hashtable的。
以PHP變數為例來說明下PHP的動態運行特點,比如說代碼:
?php
$var=「hello,」;
?
該代碼的執行結果就是在變數符號棧(是一個hashtable)中新增一個項
當要使用到該變數時候,就去變數符合棧中去查找(也就是變數調用對出了一個hash查找的過程)。
同樣對於函數調用也基本上類似有一個函數符號棧(hashtable)。
其實關於動態運行的變數查找特點,在PHP的運行機制中也能看出一些。PHP代碼通過解釋、編譯後的流程下圖:
從上圖可以看出,PHP代碼在compile之後,產出的了類符號表、函數符號表、和OPCODE。在真正執行的時候,zend Engine會根據op code去對應的符號表中進行查找,處理。
從某種程度上,在這種問題的上,很難找到解決方案。因為這是由於PHP語言的動態特性所決定的。但是在國內外也有不少的人在尋找解決方案。因為通過這樣,能夠從根本上完全的優化PHP。典型的列子有facebook的hiphop。
2.6結論
從上面分析來看,在基礎的內存管理、變數、函數、運行機制方面,PHP本身並不會存在明顯的性能差異,但由於PHP的動態運行特性,決定了PHP和其他的編譯型語言相比,所有的變數查找、函數運行等等都會多一些hash查找的CPU開銷和額外的內存開銷,至於這種開銷具體有多大,可以通過後續的基準性能和對比分析得出。
因此,也可以大體看出PHP不太適合的一些場景:大量計算性任務、大數據量的運算、內存要求很嚴格的應用場景。如果要實現這些功能,也建議通過擴展的方式實現,然後再提供鉤子函數給PHP調用。這樣可以減低內部計算的變數、函數等系列開銷。
3.基準性能
對於PHP基準性能,目前缺少標準的數據。大多數同學都存在感性的認識,有人認為800QPS就是PHP的極限了。此外,對於框架的性能和框架對性能的影響很沒有響應的權威數字。
本章節的目的是給出一個基準的參考性能指標,通過數據給大家一個直觀的了解。
具體的基準性能有以下幾個方面:
1.裸PHP性能。完成基本的功能。
2.裸框架的性能。只做最簡單的路由分發,只走通核心功能。
3.標准模塊的基準性能。所謂標准模塊的基準性能,是指一個具有完整服務模塊功能的基準性能。
3.1環境說明
測試環境:
Uname -aPnux db-forum-test17.db01..com 2.6.9_5-7-0-0 #1 SMP Wed Aug 12
17:35:51 CST 2009 x86_64 x86_64 x86_64 GNU/Pnux
Red Hat Enterprise Pnux AS release 4 (Nahant Update 3)
8 Intel(R) Xeon(R) CPU E5520 @ 2.27GHz
軟體相關:
Nginx:nginx version: nginx/0.8.54 built by gcc 3.4.5 20051201 (Red Hat 3.4.5-2)
Php5:(採用php-fpm)
PHP 5.2.8 (cP) (built: Mar 6 2011 17:16:18)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
with eAccelerator v0.9.5.3, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
bingo2:
PHP框架。
其他說明:
目標機器的部署方式:nginx-php-fpm-php腳本。
測試壓力機器和目標機器獨立部署。
3.2裸PHP性能
最簡單的PHP腳本。
?php
require_once『./actions/indexAction.php』;
$objAction=newindexAction();
$objAction-init();
$objAction-execute();
?
Acitons/indexAction.php裡面的代碼如下
?php
classindexAction
{
pubPcfunctionexecute()
{
echo『hello,world!』;
}
}
?
通過壓力工具測試結果如下:
3.3裸PHP框架性能
為了和3.2的對比,基於bingo2框架實現了類似的功能。代碼如下
?php
require_once『Bingo/Controller/Front.php』;
$objFrontController=Bingo_Controller_Front::getInstance(array(『actionDir』=『./actions』,));
$objFrontController-dispatch();
壓力測試結果如下:
從該測試結果可以看出:框架雖然有一定的消耗,但對整體的性能來說影響是非常小的。
3.4標准PHP模塊的基準性能
所謂標准PHP模塊,是指一個PHP模塊所必須要具體的基本功能:
路由分發。
自動載入。
LOG初始化Notice日誌列印。所以的UI請求都一條標準的日誌。
錯誤處理。
時間校正。
自動計算每個階段耗時開銷。
編碼識別編碼轉化。
標准配置文件的解析和調用
採用bingo2的代碼自動生成工具產生標準的測試PHP模塊:test。
測試結果如下:
3.5結論
從測試數據的結論來看,PHP本身的性能還是可以的。基準性能完全能夠達到幾千甚至上W的QPS。至於為什麼在大多數的PHP模塊中表現不佳,其實這個時候更應該去找出系統的瓶頸點,而是簡單的說OK,PHP不行,那我們換C來搞吧。(下一個章節,會通過一些例子來對比,採用C來處理不見得有特別的優勢)
通過基準數據,可以得出以下幾個具體的結論:
1.PHP本身性能也很不錯。簡單功能下能夠達到5000QPS,極限也能過W。
2.PHP框架本身對性能影響非常有限。尤其是在有一定業務邏輯和數據交互的情況下,幾乎可以忽略。
3.一個標準的PHP模塊,基準性能能夠達到2000QPS(80 cpu idle)。
4.對比分析
很多時候,大家發現PHP模塊性能不行的時候,就來一句「ok,我們採用C重寫吧」。在公司內,採用C/C++來寫業務邏輯模塊的現象到處都有,在前幾年甚至幾乎全部都是採用C來寫。那時候大家寫的真是一個痛苦:調試難、敏捷不要談。