提高 web 應(yīng)用的性能從來沒有比現(xiàn)在更重要過。網(wǎng)絡(luò)經(jīng)濟(jì)的比重一直在增長;全球經(jīng)濟(jì)超過 5% 的價(jià)值是在因特網(wǎng)上產(chǎn)生的(數(shù)據(jù)參見下面的資料)。這個(gè)時(shí)刻在線的超連接世界意味著用戶對(duì)其的期望值也處于歷史上的最高點(diǎn)。如果你的網(wǎng)站不能及時(shí)的響應(yīng),或者你的 app 不能無延時(shí)的工作,用戶會(huì)很快的投奔到你的競爭對(duì)手那里。
舉一個(gè)例子,一份亞馬遜十年前做過的研究可以證明,甚至在那個(gè)時(shí)候,網(wǎng)頁加載時(shí)間每減少100毫秒,收入就會(huì)增加1%。另一個(gè)最近的研究特別強(qiáng)調(diào)一個(gè)事實(shí),即超過一半的網(wǎng)站擁有者在調(diào)查中承認(rèn)它們會(huì)因?yàn)閼?yīng)用程序性能的問題流失用戶。
網(wǎng)站到底需要多快呢?對(duì)于頁面加載,每增加1秒鐘就有4%的用戶放棄使用。頂級(jí)的電子商務(wù)站點(diǎn)的頁面在第一次交互時(shí)可以做到1秒到3秒加載時(shí)間,而這是提供最高舒適度的速度。很明顯這種利害關(guān)系對(duì)于 web 應(yīng)用來說很高,而且在不斷的增加。
想要提高效率很簡單,但是看到實(shí)際結(jié)果很難。為了在你的探索之旅上幫助到你,這篇文章會(huì)給你提供10條最高可以提升10倍網(wǎng)站性能的建議。
Tip #1: 通過反向代理來提高性能和增加安全性
如果你的 web 應(yīng)用運(yùn)行在單個(gè)機(jī)器上,那么這個(gè)辦法會(huì)明顯的提升性能:只需要換一個(gè)更快的機(jī)器,更好的處理器,更多的內(nèi)存,更快的磁盤陣列,等等。然后新機(jī)器就可以更快的運(yùn)行你的 WordPress 服務(wù)器, Node.js 程序, Java 程序,以及其它程序。(如果你的程序要訪問數(shù)據(jù)庫服務(wù)器,那么解決方法依然很簡單:添加兩個(gè)更快的機(jī)器,以及在兩臺(tái)電腦之間使用一個(gè)更快的鏈路。)
問題是,機(jī)器速度可能并不是問題。web 程序運(yùn)行慢經(jīng)常是因?yàn)橛?jì)算機(jī)一直在不同的任務(wù)之間切換:通過成千上萬的連接和用戶交互,從磁盤訪問文件,運(yùn)行代碼,等等。應(yīng)用服務(wù)器可能會(huì)抖動(dòng)thrashing-比如說內(nèi)存不足、將內(nèi)存數(shù)據(jù)交換到磁盤,以及有多個(gè)請(qǐng)求要等待某個(gè)任務(wù)完成,如磁盤I/O。
你可以采取一個(gè)完全不同的方案來替代升級(jí)硬件:添加一個(gè)反向代理服務(wù)器來分擔(dān)部分任務(wù)。反向代理服務(wù)器 位于運(yùn)行應(yīng)用的機(jī)器的前端,是用來處理網(wǎng)絡(luò)流量的。只有反向代理服務(wù)器是直接連接到互聯(lián)網(wǎng)的;和應(yīng)用服務(wù)器的通訊都是通過一個(gè)快速的內(nèi)部網(wǎng)絡(luò)完成的。
使用反向代理服務(wù)器可以將應(yīng)用服務(wù)器從等待用戶與 web 程序交互解放出來,這樣應(yīng)用服務(wù)器就可以專注于為反向代理服務(wù)器構(gòu)建網(wǎng)頁,讓其能夠傳輸?shù)交ヂ?lián)網(wǎng)上。而應(yīng)用服務(wù)器就不需要等待客戶端的響應(yīng),其運(yùn)行速度可以接近于優(yōu)化后的性能水平。
添加反向代理服務(wù)器還可以給你的 web 服務(wù)器安裝帶來靈活性。比如,一個(gè)某種類型的服務(wù)器已經(jīng)超載了,那么就可以輕松的添加另一個(gè)相同的服務(wù)器;如果某個(gè)機(jī)器宕機(jī)了,也可以很容易替代一個(gè)新的。
因?yàn)榉聪虼韼淼撵`活性,所以反向代理也是一些性能加速功能的必要前提,比如:
負(fù)載均衡 (參見 Tip #2) – 負(fù)載均衡運(yùn)行在反向代理服務(wù)器上,用來將流量均衡分配給一批應(yīng)用。有了合適的負(fù)載均衡,你就可以添加應(yīng)用服務(wù)器而根本不用修改應(yīng)用。
緩存靜態(tài)文件 (參見 Tip #3) – 直接讀取的文件,比如圖片或者客戶端代碼,可以保存在反向代理服務(wù)器,然后直接發(fā)給客戶端,這樣就可以提高速度、分擔(dān)應(yīng)用服務(wù)器的負(fù)載,可以讓應(yīng)用運(yùn)行的更快。
網(wǎng)站安全 – 反向代理服務(wù)器可以提高網(wǎng)站安全性,以及快速的發(fā)現(xiàn)和響應(yīng)攻擊,保證應(yīng)用服務(wù)器處于被保護(hù)狀態(tài)。
NGINX 軟件為用作反向代理服務(wù)器而專門設(shè)計(jì),也包含了上述的多種功能。NGINX 使用事件驅(qū)動(dòng)的方式處理請(qǐng)求,這會(huì)比傳統(tǒng)的服務(wù)器更加有效率。NGINX plus 添加了更多高級(jí)的反向代理特性,比如應(yīng)用的健康度檢查,專門用來處理請(qǐng)求路由、高級(jí)緩沖和相關(guān)支持。
Tip #2: 添加負(fù)載平衡
添加一個(gè)負(fù)載均衡服務(wù)器 是一個(gè)相當(dāng)簡單的用來提高性能和網(wǎng)站安全性的的方法。與其將核心 Web 服務(wù)器變得越來越大和越來越強(qiáng),不如使用負(fù)載均衡將流量分配到多個(gè)服務(wù)器。即使程序?qū)懙牟缓?,或者在擴(kuò)容方面有困難,僅是使用負(fù)載均衡服務(wù)器就可以很好的提高用戶體驗(yàn)。
負(fù)載均衡服務(wù)器首先是一個(gè)反向代理服務(wù)器(參見Tip #1)——它接受來自互聯(lián)網(wǎng)的流量,然后轉(zhuǎn)發(fā)請(qǐng)求給另一個(gè)服務(wù)器。特別是負(fù)載均衡服務(wù)器支持兩個(gè)或多個(gè)應(yīng)用服務(wù)器,使用分配算法將請(qǐng)求轉(zhuǎn)發(fā)給不同服務(wù)器。最簡單的負(fù)載均衡方法是輪轉(zhuǎn)法round robin,每個(gè)新的請(qǐng)求都會(huì)發(fā)給列表里的下一個(gè)服務(wù)器。其它的復(fù)制均衡方法包括將請(qǐng)求發(fā)給活動(dòng)連接最少的服務(wù)器。NGINX plus 擁有將特定用戶的會(huì)話分配給同一個(gè)服務(wù)器的能力。
負(fù)載均衡可以很好的提高性能是因?yàn)樗梢员苊饽硞€(gè)服務(wù)器過載而另一些服務(wù)器卻沒有需要處理的流量。它也可以簡單的擴(kuò)展服務(wù)器規(guī)模,因?yàn)槟憧梢蕴砑佣鄠€(gè)價(jià)格相對(duì)便宜的服務(wù)器并且保證它們被充分利用了。
可以進(jìn)行負(fù)載均衡的協(xié)議包括 HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、 memcached 等,以及幾種其它的應(yīng)用類型,包括基于 TCP 的應(yīng)用和其它的第4層協(xié)議的程序。分析你的 web 應(yīng)用來決定你要使用哪些以及哪些地方性能不足。
相同的服務(wù)器或服務(wù)器群可以被用來進(jìn)行負(fù)載均衡,也可以用來處理其它的任務(wù),如 SSL 末端服務(wù)器,支持客戶端的 HTTP/1.x 和 HTTP/2 請(qǐng)求,以及緩存靜態(tài)文件。
Tip #3: 緩存靜態(tài)和動(dòng)態(tài)的內(nèi)容
緩存可以通過加速內(nèi)容的傳輸速度來提高 web 應(yīng)用的性能。它可以采用以下幾種策略:當(dāng)需要的時(shí)候預(yù)處理要傳輸?shù)膬?nèi)容,保存數(shù)據(jù)到速度更快的設(shè)備,把數(shù)據(jù)存儲(chǔ)在距離客戶端更近的位置,或者將這幾種方法結(jié)合起來使用。
有兩種不同類型數(shù)據(jù)的緩沖:
靜態(tài)內(nèi)容緩存。不經(jīng)常變化的文件,比如圖像(JPEG、PNG) 和代碼(CSS,JavaScript),可以保存在外圍服務(wù)器上,這樣就可以快速的從內(nèi)存和磁盤上提取。
動(dòng)態(tài)內(nèi)容緩存。很多 web 應(yīng)用會(huì)針對(duì)每次網(wǎng)頁請(qǐng)求生成一個(gè)新的 HTML 頁面。在短時(shí)間內(nèi)簡單的緩存生成的 HTML 內(nèi)容,就可以很好的減少要生成的內(nèi)容的數(shù)量,而且這些頁面足夠新,可以滿足你的需要。
舉個(gè)例子,如果一個(gè)頁面每秒會(huì)被瀏覽10次,你將它緩存 1 秒,90%請(qǐng)求的頁面都會(huì)直接從緩存提取。如果你分開緩存靜態(tài)內(nèi)容,甚至新生成的頁面可能都是由這些緩存構(gòu)成的。
下面由是 web 應(yīng)用發(fā)明的三種主要的緩存技術(shù):
1.縮短數(shù)據(jù)與用戶的網(wǎng)絡(luò)距離。把一份內(nèi)容的拷貝放的離用戶更近的節(jié)點(diǎn)來減少傳輸時(shí)間。
2.提高內(nèi)容服務(wù)器的速度。內(nèi)容可以保存在一個(gè)更快的服務(wù)器上來減少提取文件的時(shí)間。
3.從過載服務(wù)器上移走數(shù)據(jù)。機(jī)器經(jīng)常因?yàn)橐瓿赡承┢渌娜蝿?wù)而造成某個(gè)任務(wù)的執(zhí)行速度比測(cè)試結(jié)果要差。將數(shù)據(jù)緩存在不同的機(jī)器上可以提高緩存資源和非緩存資源的性能,而這是因?yàn)橹鳈C(jī)沒有被過度使用。
對(duì) web 應(yīng)用的緩存機(jī)制可以在 web 應(yīng)用服務(wù)器內(nèi)部實(shí)現(xiàn)。首先,緩存動(dòng)態(tài)內(nèi)容是用來減少應(yīng)用服務(wù)器加載動(dòng)態(tài)內(nèi)容的時(shí)間。其次,緩存靜態(tài)內(nèi)容(包括動(dòng)態(tài)內(nèi)容的臨時(shí)拷貝)是為了更進(jìn)一步的分擔(dān)應(yīng)用服務(wù)器的負(fù)載。而且緩存之后會(huì)從應(yīng)用服務(wù)器轉(zhuǎn)移到對(duì)用戶而言更快、更近的機(jī)器,從而減少應(yīng)用服務(wù)器的壓力,減少提取數(shù)據(jù)和傳輸數(shù)據(jù)的時(shí)間。
改進(jìn)過的緩存方案可以極大的提高應(yīng)用的速度。對(duì)于大多數(shù)網(wǎng)頁來說,靜態(tài)數(shù)據(jù),比如大圖像文件,構(gòu)成了超過一半的內(nèi)容。如果沒有緩存,那么這可能會(huì)花費(fèi)幾秒的時(shí)間來提取和傳輸這類數(shù)據(jù),但是采用了緩存之后不到1秒就可以完成。
舉一個(gè)在實(shí)際中緩存是如何使用的例子, NGINX 和 NGINX Plus 使用了兩條指令來設(shè)置緩存機(jī)制:proxy_cache_path 和 proxy_cache。你可以指定緩存的位置和大小、文件在緩存中保存的最長時(shí)間和其它一些參數(shù)。使用第三條(而且是相當(dāng)受歡迎的一條)指令 proxy_cache_use_stale,如果提供新鮮內(nèi)容的服務(wù)器忙碌或者掛掉了,你甚至可以讓緩存提供較舊的內(nèi)容,這樣客戶端就不會(huì)一無所得。從用戶的角度來看這可以很好的提高你的網(wǎng)站或者應(yīng)用的可用時(shí)間。
NGINX plus 有個(gè)高級(jí)緩存特性,包括對(duì)緩存清除的支持和在儀表盤上顯示緩存狀態(tài)信息。
注意:緩存機(jī)制分布于應(yīng)用開發(fā)者、投資決策者以及實(shí)際的系統(tǒng)運(yùn)維人員之間。本文提到的一些復(fù)雜的緩存機(jī)制從 DevOps 的角度來看很具有價(jià)值,即對(duì)集應(yīng)用開發(fā)者、架構(gòu)師以及運(yùn)維操作人員的功能為一體的工程師來說可以滿足它們對(duì)站點(diǎn)功能性、響應(yīng)時(shí)間、安全性和商業(yè)結(jié)果(如完成的交易數(shù))等需要。
Tip #4: 壓縮數(shù)據(jù)
壓縮是一個(gè)具有很大潛力的提高性能的加速方法?,F(xiàn)在已經(jīng)有一些針對(duì)照片(JPEG 和PNG)、視頻(MPEG-4)和音樂(MP3)等各類文件精心設(shè)計(jì)和高壓縮率的標(biāo)準(zhǔn)。每一個(gè)標(biāo)準(zhǔn)都或多或少的減少了文件的大小。
文本數(shù)據(jù) —— 包括HTML(包含了純文本和 HTML 標(biāo)簽),CSS 和代碼,比如 Javascript —— 經(jīng)常是未經(jīng)壓縮就傳輸?shù)摹嚎s這類數(shù)據(jù)會(huì)在對(duì)應(yīng)用程序性能的感覺上,特別是處于慢速或受限的移動(dòng)網(wǎng)絡(luò)的客戶端,產(chǎn)生更大的影響。
這是因?yàn)槲谋緮?shù)據(jù)經(jīng)常是用戶與網(wǎng)頁交互的有效數(shù)據(jù),而多媒體數(shù)據(jù)可能更多的是起提供支持或者裝飾的作用。智能的內(nèi)容壓縮可以減少 HTML,Javascript,CSS和其它文本內(nèi)容對(duì)帶寬的要求,通??梢詼p少 30% 甚至更多的帶寬和相應(yīng)的頁面加載時(shí)間。
如果你使用 SSL,壓縮可以減少需要進(jìn)行 SSL 編碼的的數(shù)據(jù)量,而這些編碼操作會(huì)占用一些 CPU 時(shí)間而抵消了壓縮數(shù)據(jù)減少的時(shí)間。
壓縮文本數(shù)據(jù)的方法很多,舉個(gè)例子,在 HTTP/2 中,小說文本的壓縮模式就特別調(diào)整了頭部數(shù)據(jù)。另一個(gè)例子是可以在 NGINX 里打開使用 GZIP 壓縮。你在你的服務(wù)里預(yù)先壓縮文本數(shù)據(jù)之后,你就可以直接使用 gzip_static 指令來處理壓縮過的 .gz 版本。
Tip #5: 優(yōu)化 SSL/TLS
安全套接字(SSL) 協(xié)議和它的下一代版本傳輸層安全(TLS)協(xié)議正在被越來越多的網(wǎng)站采用。SSL/TLS 對(duì)從原始服務(wù)器發(fā)往用戶的數(shù)據(jù)進(jìn)行加密提高了網(wǎng)站的安全性。影響這個(gè)趨勢(shì)的部分原因是 Google 正在使用 SSL/TLS,這在搜索引擎排名上是一個(gè)正面的影響因素。
盡管 SSL/TLS 越來越流行,但是使用加密對(duì)速度的影響也讓很多網(wǎng)站望而卻步。SSL/TLS 之所以讓網(wǎng)站變的更慢,原因有二:
任何一個(gè)連接第一次連接時(shí)的握手過程都需要傳遞密鑰。而采用 HTTP/1.x 協(xié)議的瀏覽器在建立多個(gè)連接時(shí)會(huì)對(duì)每個(gè)連接重復(fù)上述操作。
數(shù)據(jù)在傳輸過程中需要不斷的在服務(wù)器端加密、在客戶端解密。
為了鼓勵(lì)使用 SSL/TLS,HTTP/2 和 SPDY(在下一章會(huì)描述)的作者設(shè)計(jì)了新的協(xié)議來讓瀏覽器只需要對(duì)一個(gè)瀏覽器會(huì)話使用一個(gè)連接。這會(huì)大大的減少上述第一個(gè)原因所浪費(fèi)的時(shí)間。然而現(xiàn)在可以用來提高應(yīng)用程序使用 SSL/TLS 傳輸數(shù)據(jù)的性能的方法不止這些。
web 服務(wù)器有對(duì)應(yīng)的機(jī)制優(yōu)化 SSL/TLS 傳輸。舉個(gè)例子,NGINX 使用 OpenSSL 運(yùn)行在普通的硬件上提供了接近專用硬件的傳輸性能。NGINX 的 SSL 性能 有詳細(xì)的文檔,而且把對(duì) SSL/TLS 數(shù)據(jù)進(jìn)行加解密的時(shí)間和 CPU 占用率降低了很多。
Tip #6: 使用 HTTP/2 或 SPDY
對(duì)于已經(jīng)使用了 SSL/TLS 的站點(diǎn),HTTP/2 和 SPDY 可以很好的提高性能,因?yàn)槊總€(gè)連接只需要一次握手。而對(duì)于沒有使用 SSL/TLS 的站點(diǎn)來說,從響應(yīng)速度的角度來說 HTTP/2 和 SPDY 將讓遷移到 SSL/TLS 沒有什么壓力(原本會(huì)降低效率)。
Google 在2012年開始把 SPDY 作為一個(gè)比 HTTP/1.x 更快速的協(xié)議來推薦。HTTP/2 是目前 IETF 通過的標(biāo)準(zhǔn),是基于 SPDY 的。SPDY 已經(jīng)被廣泛的支持了,但是很快就會(huì)被 HTTP/2 替代。
SPDY 和 HTTP/2 的關(guān)鍵是用單一連接來替代多路連接。單個(gè)連接是被復(fù)用的,所以它可以同時(shí)攜帶多個(gè)請(qǐng)求和響應(yīng)的分片。
通過使用單一連接,這些協(xié)議可以避免像在實(shí)現(xiàn)了 HTTP/1.x 的瀏覽器中一樣建立和管理多個(gè)連接。單一連接在對(duì) SSL 特別有效,這是因?yàn)樗梢宰钚』?SSL/TLS 建立安全鏈接時(shí)的握手時(shí)間。
SPDY 協(xié)議需要使用 SSL/TLS,而 HTTP/2 官方標(biāo)準(zhǔn)并不需要,但是目前所有支持 HTTP/2 的瀏覽器只有在啟用了 SSL/TLS 的情況下才能使用它。這就意味著支持 HTTP/2 的瀏覽器只有在網(wǎng)站使用了 SSL 并且服務(wù)器接收 HTTP/2 流量的情況下才會(huì)啟用 HTTP/2。否則的話瀏覽器就會(huì)使用 HTTP/1.x 協(xié)議。
作為支持這些協(xié)議的一個(gè)樣例,NGINX 已經(jīng)從一開始就支持了 SPDY,而且大部分使用 SPDY 協(xié)議的網(wǎng)站都運(yùn)行的是 NGINX。NGINX 同時(shí)也很早對(duì) HTTP/2 的提供了支持,從2015 年9月開始,開源版 NGINX 和 NGINX Plus 就支持它了。
經(jīng)過一段時(shí)間,我們 NGINX 希望更多的站點(diǎn)完全啟用 SSL 并且向 HTTP/2 遷移。這將會(huì)提高安全性,同時(shí)也會(huì)找到并實(shí)現(xiàn)新的優(yōu)化手段,簡化的代碼表現(xiàn)的會(huì)更加優(yōu)異。
Tip #7: 升級(jí)軟件版本
一個(gè)提高應(yīng)用性能的簡單辦法是根據(jù)軟件的穩(wěn)定性和性能的評(píng)價(jià)來選在你的軟件棧。進(jìn)一步說,因?yàn)楦咝阅芙M件的開發(fā)者更愿意追求更高的性能和解決 bug ,所以值得使用最新版本的軟件。新版本往往更受開發(fā)者和用戶社區(qū)的關(guān)注。更新的版本往往會(huì)利用到新的編譯器優(yōu)化,包括對(duì)新硬件的調(diào)優(yōu)。
穩(wěn)定的新版本通常比舊版本具有更好的兼容性和更高的性能。一直進(jìn)行軟件更新,可以非常簡單的保持軟件保持最佳的優(yōu)化,解決掉 bug,以及提高安全性。
一直使用舊版軟件也會(huì)阻止你利用新的特性。比如上面說到的 HTTP/2,目前要求 OpenSSL 1.0.1。在2016 年中期開始將會(huì)要求1.0.2 ,而它是在2015年1月才發(fā)布的。
NGINX 用戶可以開始遷移到 NGINX 最新的開源軟件 或者 NGINX Plus;它們都包含了最新的能力,如 socket 分割和線程池(見下文),這些都已經(jīng)為性能優(yōu)化過了。然后好好看看的你軟件棧,把它們升級(jí)到你能升級(jí)到的最新版本吧。
Tip #8: Linux 系統(tǒng)性能調(diào)優(yōu)
Linux 是大多數(shù) web 服務(wù)器使用的操作系統(tǒng),而且作為你的架構(gòu)的基礎(chǔ),Linux 顯然有不少提高性能的可能。默認(rèn)情況下,很多 Linux 系統(tǒng)都被設(shè)置為使用很少的資源,以符合典型的桌面應(yīng)用使用。這就意味著 web 應(yīng)用需要一些微調(diào)才能達(dá)到最大效能。
這里的 Linux 優(yōu)化是專門針對(duì) web 服務(wù)器方面的。以 NGINX 為例,這里有一些在加速 Linux 時(shí)需要強(qiáng)調(diào)的變化:
緩沖隊(duì)列。如果你有掛起的連接,那么你應(yīng)該考慮增加 net.core.somaxconn 的值,它代表了可以緩存的連接的最大數(shù)量。如果連接限制太小,那么你將會(huì)看到錯(cuò)誤信息,而你可以逐漸的增加這個(gè)參數(shù)直到錯(cuò)誤信息停止出現(xiàn)。
文件描述符。NGINX 對(duì)一個(gè)連接使用最多2個(gè)文件描述符。如果你的系統(tǒng)有很多連接請(qǐng)求,你可能就需要提高sys.fs.file_max ,以增加系統(tǒng)對(duì)文件描述符數(shù)量整體的限制,這樣才能支持不斷增加的負(fù)載需求。
臨時(shí)端口。當(dāng)使用代理時(shí),NGINX 會(huì)為每個(gè)上游服務(wù)器創(chuàng)建臨時(shí)端口。你可以設(shè)置net.ipv4.ip_local_port_range 來提高這些端口的范圍,增加可用的端口號(hào)。你也可以減少非活動(dòng)的端口的超時(shí)判斷來重復(fù)使用端口,這可以通過 net.ipv4.tcp_fin_timeout 來設(shè)置,這可以快速的提高流量。
Tip #9: web 服務(wù)器性能調(diào)優(yōu)
無論你是用哪種 web 服務(wù)器,你都需要對(duì)它進(jìn)行優(yōu)化來提高性能。下面的推薦手段可以用于任何 web 服務(wù)器,但是一些設(shè)置是針對(duì) NGINX 的。關(guān)鍵的優(yōu)化手段包括:
訪問日志。不要把每個(gè)請(qǐng)求的日志都直接寫回磁盤,你可以在內(nèi)存將日志緩存起來然后批量寫回磁盤。對(duì)于NGINX 來說,給指令 access_log 添加參數(shù) buffer=size 可以讓系統(tǒng)在緩存滿了的情況下才把日志寫到磁盤。如果你添加了參數(shù) flush=time ,那么緩存內(nèi)容會(huì)每隔一段時(shí)間再寫回磁盤。
緩存。緩存會(huì)在內(nèi)存中存放部分響應(yīng),直到滿了為止,這可以讓與客戶端的通信更加高效。內(nèi)存放不下的響應(yīng)會(huì)寫回磁盤,而這就會(huì)降低效能。當(dāng) NGINX 啟用了緩存機(jī)制后,你可以使用指令 proxy_buffer_size 和 proxy_buffers 來管理緩存。
客戶端?;?。?;钸B接可以減少開銷,特別是使用 SSL/TLS 時(shí)。對(duì)于 NGINX 來說,你可以從 keepalive_requests 的默認(rèn)值 100 開始增加最大連接數(shù),這樣一個(gè)客戶端就可以在一個(gè)指定的連接上請(qǐng)求多次,而且你也可以通過增加 keepalive_timeout 的值來允許保活連接存活更長時(shí)間,這樣就可以讓后來的請(qǐng)求處理的更快速。
上游保活。上游的連接——即連接到應(yīng)用服務(wù)器、數(shù)據(jù)庫服務(wù)器等機(jī)器的連接——同樣也會(huì)受益于連接?;睢?duì)于上游連接來說,你可以增加 keepalive,即每個(gè)工人進(jìn)程的空閑?;钸B接個(gè)數(shù)。這就可以提高連接的復(fù)用次數(shù),減少需要重新打開全新連接的次數(shù)。
限制。限制客戶端使用的資源可以提高性能和安全性。對(duì)于 NGINX 來說,指令 limit_conn 和 limit_conn_zone 限制了給定來源的連接數(shù)量,而 limit_rate 限制了帶寬。這些限制都可以阻止合法用戶扒取資源,同時(shí)也避免了攻擊。指令 limit_req 和 limit_req_zone 限制了客戶端請(qǐng)求。對(duì)于上游服務(wù)器來說,可以在 upstream 的配置塊里的 server 指令使用 max_conns 參數(shù)來限制連接到上游服務(wù)器的連接數(shù)。 這樣可以避免服務(wù)器過載。關(guān)聯(lián)的 queue 指令會(huì)創(chuàng)建一個(gè)隊(duì)列來在連接數(shù)抵達(dá) max_connS 限制時(shí)在指定長度的時(shí)間內(nèi)保存特定數(shù)量的請(qǐng)求。
工人進(jìn)程。工人進(jìn)程負(fù)責(zé)處理請(qǐng)求。NGINX 采用事件驅(qū)動(dòng)模型和操作系統(tǒng)特定的機(jī)制來有效的將請(qǐng)求分發(fā)給不同的工人進(jìn)程。這條建議推薦設(shè)置 worker_processes 為每個(gè) CPU 一個(gè) 。worker_connections 的最大數(shù)(默認(rèn)512)可以在大部分系統(tǒng)上根據(jù)需要增加,實(shí)驗(yàn)性地找到最適合你的系統(tǒng)的值。
套接字分割。通常一個(gè)套接字*會(huì)把新連接分配給所有工人進(jìn)程。套接字分割會(huì)為每個(gè)工人進(jìn)程創(chuàng)建一個(gè)套接字*,這樣一來以當(dāng)套接字*可用時(shí),內(nèi)核就會(huì)將連接分配給它。這可以減少鎖競爭,并且提高多核系統(tǒng)的性能,要啟用套接字分隔需要在 listen 指令里面加上 reuseport 參數(shù)。
線程池。計(jì)算機(jī)進(jìn)程可能被一個(gè)單一的緩慢的操作所占用。對(duì)于 web 服務(wù)器軟件來說,磁盤訪問會(huì)影響很多更快的操作,比如計(jì)算或者在內(nèi)存中拷貝。使用了線程池之后慢操作可以分配到不同的任務(wù)集,而主進(jìn)程可以一直運(yùn)行快速操作。當(dāng)磁盤操作完成后結(jié)果會(huì)返回給主進(jìn)程的循環(huán)。在 NGINX 里有兩個(gè)操作——read() 系統(tǒng)調(diào)用和 sendfile() ——被分配到了線程池
技巧。當(dāng)改變?nèi)魏尾僮飨到y(tǒng)或支持服務(wù)的設(shè)置時(shí),一次只改變一個(gè)參數(shù)然后測(cè)試性能。如果修改引起問題了,或者不能讓你的系統(tǒng)更快,那么就改回去。
Tip #10: 監(jiān)視系統(tǒng)活動(dòng)來解決問題和瓶頸
在應(yīng)用開發(fā)中要使得系統(tǒng)變得非常高效的關(guān)鍵是監(jiān)視你的系統(tǒng)在現(xiàn)實(shí)世界運(yùn)行的性能。你必須能通過特定的設(shè)備和你的 web 基礎(chǔ)設(shè)施上監(jiān)控程序活動(dòng)。
監(jiān)視活動(dòng)是最積極的——它會(huì)告訴你發(fā)生了什么,把問題留給你發(fā)現(xiàn)和最終解決掉。
監(jiān)視可以發(fā)現(xiàn)幾種不同的問題。它們包括:
服務(wù)器宕機(jī)。
服務(wù)器出問題一直在丟失連接。
服務(wù)器出現(xiàn)大量的緩存未命中。
服務(wù)器沒有發(fā)送正確的內(nèi)容。
應(yīng)用的總體性能監(jiān)控工具,比如 New Relic 和 Dynatrace,可以幫助你監(jiān)控到從遠(yuǎn)程加載網(wǎng)頁的時(shí)間,而 NGINX 可以幫助你監(jiān)控到應(yīng)用交付端。當(dāng)你需要考慮為基礎(chǔ)設(shè)施添加容量以滿足流量需求時(shí),應(yīng)用性能數(shù)據(jù)可以告訴你你的優(yōu)化措施的確起作用了。
為了幫助開發(fā)者快速的發(fā)現(xiàn)、解決問題,NGINX Plus 增加了應(yīng)用感知健康度檢查 ——對(duì)重復(fù)出現(xiàn)的常規(guī)事件進(jìn)行綜合分析并在問題出現(xiàn)時(shí)向你發(fā)出警告。NGINX Plus 同時(shí)提供會(huì)話過濾功能,這可以阻止當(dāng)前任務(wù)完成之前接受新的連接,另一個(gè)功能是慢啟動(dòng),允許一個(gè)從錯(cuò)誤恢復(fù)過來的服務(wù)器追趕上負(fù)載均衡服務(wù)器群的進(jìn)度。當(dāng)使用得當(dāng)時(shí),健康度檢查可以讓你在問題變得嚴(yán)重到影響用戶體驗(yàn)前就發(fā)現(xiàn)它,而會(huì)話過濾和慢啟動(dòng)可以讓你替換服務(wù)器,并且這個(gè)過程不會(huì)對(duì)性能和正常運(yùn)行時(shí)間產(chǎn)生負(fù)面影響。下圖就展示了內(nèi)建的 NGINX Plus 模塊實(shí)時(shí)活動(dòng)監(jiān)視的儀表盤,包括了服務(wù)器群,TCP 連接和緩存信息等 Web 架構(gòu)信息。
總結(jié): 看看10倍性能提升的效果
這些性能提升方案對(duì)任何一個(gè) web 應(yīng)用都可用并且效果都很好,而實(shí)際效果取決于你的預(yù)算、你能花費(fèi)的時(shí)間、目前實(shí)現(xiàn)方案的差距。所以你該如何對(duì)你自己的應(yīng)用實(shí)現(xiàn)10倍性能提升?
為了指導(dǎo)你了解每種優(yōu)化手段的潛在影響,這里是上面詳述的每個(gè)優(yōu)化方法的關(guān)鍵點(diǎn),雖然你的情況肯定大不相同:
反向代理服務(wù)器和負(fù)載均衡。沒有負(fù)載均衡或者負(fù)載均衡很差都會(huì)造成間歇的性能低谷。增加一個(gè)反向代理,比如 NGINX ,可以避免 web 應(yīng)用程序在內(nèi)存和磁盤之間波動(dòng)。負(fù)載均衡可以將過載服務(wù)器的任務(wù)轉(zhuǎn)移到空閑的服務(wù)器,還可以輕松的進(jìn)行擴(kuò)容。這些改變都可以產(chǎn)生巨大的性能提升,很容易就可以比你現(xiàn)在的實(shí)現(xiàn)方案的最差性能提高10倍,對(duì)于總體性能來說可能提高的不多,但是也是有實(shí)質(zhì)性的提升。
緩存動(dòng)態(tài)和靜態(tài)數(shù)據(jù)。如果你有一個(gè)負(fù)擔(dān)過重的 web 服務(wù)器,那么毫無疑問肯定是你的應(yīng)用服務(wù)器,只通過緩存動(dòng)態(tài)數(shù)據(jù)就可以在峰值時(shí)間提高10倍的性能。緩存靜態(tài)文件可以提高幾倍的性能。
壓縮數(shù)據(jù)。使用媒體文件壓縮格式,比如圖像格式 JPEG,圖形格式 PNG,視頻格式 MPEG-4,音樂文件格式 MP3 可以極大的提高性能。一旦這些都用上了,然后壓縮文件數(shù)據(jù)可以將初始頁面加載速度提高兩倍。
優(yōu)化 SSL/TLS。安全握手會(huì)對(duì)性能產(chǎn)生巨大的影響,對(duì)它們的優(yōu)化可能會(huì)對(duì)初始響應(yīng)產(chǎn)生2倍的提升,特別是對(duì)于大量文本的站點(diǎn)。優(yōu)化 SSL/TLS 下媒體文件只會(huì)產(chǎn)生很小的性能提升。
使用 HTTP/2 和 SPDY。當(dāng)你使用了 SSL/TLS,這些協(xié)議就可以提高整個(gè)站點(diǎn)的性能。
對(duì) Linux 和 web 服務(wù)器軟件進(jìn)行調(diào)優(yōu)。比如優(yōu)化緩存機(jī)制,使用?;钸B接,分配時(shí)間敏感型任務(wù)到不同的線程池可以明顯的提高性能;舉個(gè)例子,線程池可以加速對(duì)磁盤敏感的任務(wù)近一個(gè)數(shù)量級(jí)。
申請(qǐng)創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!