Web 應(yīng)用性能優(yōu)化迫在眉睫。線上經(jīng)濟(jì)活動(dòng)份額不斷增長,發(fā)達(dá)世界的互聯(lián)網(wǎng)經(jīng)濟(jì)已占經(jīng)濟(jì)總量的 5%?以上(請(qǐng)參見下文的互聯(lián)網(wǎng)統(tǒng)計(jì)數(shù)據(jù)來源)。在這個(gè)始終在線、超級(jí)互聯(lián)的現(xiàn)代世界,用戶的期望已經(jīng)今非昔比。如果您的網(wǎng)站沒有立即做出響應(yīng),或者如果您的應(yīng)用無法毫不延遲地運(yùn)行,用戶轉(zhuǎn)身就會(huì)投向您的競(jìng)爭(zhēng)對(duì)手。
例如,Amazon 近 10 年前的一項(xiàng)研究證明,頁面加載時(shí)間每減少 100 毫秒,收入就會(huì)增加 1% —— 10 年前就已如此,更何況是現(xiàn)在。最近的另一項(xiàng)研究也強(qiáng)調(diào)指出,超過一半的受訪網(wǎng)站所有者表示他們由于應(yīng)用性能不佳失去了收入或客戶。
一個(gè)網(wǎng)站到底多快才行?頁面加載每延長 1 秒鐘,就有大約 4% 的用戶走掉。主要電商網(wǎng)站的首次交互時(shí)間從 1 秒到 3 秒不等,這個(gè)區(qū)間的轉(zhuǎn)化率最高。Web 應(yīng)用性能的重要性由此可見,并且可能還會(huì)與日俱增。
想要提高性能很容易,難的是怎么看到結(jié)果。為此,本文提出了幫您實(shí)現(xiàn) 10 倍網(wǎng)站性能提升的 10 個(gè)技巧。本文是一系列博文的開帖之作,詳細(xì)介紹了如何借助一些久經(jīng)考驗(yàn)的優(yōu)化技術(shù)以及 NGINX 的一些支持提高應(yīng)用性能。該系列還概括介紹了您可能因此而獲得的安全性方面的改進(jìn)。
技巧 1
使用反向代理服務(wù)器加速并保護(hù)應(yīng)用
如果您的 Web 應(yīng)用在一臺(tái)機(jī)器上運(yùn)行,那要提升其性能非常簡(jiǎn)單:換一臺(tái)更快的機(jī)器、多加幾顆處理器、增加 RAM、換成高速磁盤陣列即可,這樣新機(jī)器就可以更快地運(yùn)行 WordPress 服務(wù)器、Node.js 應(yīng)用和 Java 應(yīng)用了。(如果您的應(yīng)用需要訪問數(shù)據(jù)庫服務(wù)器,解決辦法仍然很簡(jiǎn)單:找兩臺(tái)更快的機(jī)器,用更快的網(wǎng)絡(luò)連起來就行了。)
問題是,機(jī)器的速度可能并不是問題所在。Web 應(yīng)用通常運(yùn)行很慢,因?yàn)橛?jì)算機(jī)要在不同類型的任務(wù)之間切換:通過數(shù)千個(gè)連接與用戶交互、訪問磁盤文件、運(yùn)行應(yīng)用代碼等等。應(yīng)用服務(wù)器可能會(huì)因此而崩潰 —— 內(nèi)存耗盡、將內(nèi)存塊交換到磁盤、讓許多請(qǐng)求等待一個(gè)任務(wù)(比如磁盤 I/O)等。
除了升級(jí)硬件之外,您還可以采用一種完全不同的方法:添加反向代理服務(wù)器來卸載一些任務(wù)。反向代理服務(wù)器位于運(yùn)行應(yīng)用的機(jī)器的前面,負(fù)責(zé)處理互聯(lián)網(wǎng)流量。只有反向代理服務(wù)器直接連接到互聯(lián)網(wǎng),與應(yīng)用服務(wù)器的通信是通過一個(gè)高速內(nèi)網(wǎng)進(jìn)行的。
反向代理服務(wù)器可以讓應(yīng)用服務(wù)器不必再等待用戶與 Web 應(yīng)用的交互,而是專注于構(gòu)建頁面,剩下的發(fā)送任務(wù)則交由反向代理來執(zhí)行。由于無需等待客戶端響應(yīng),應(yīng)用服務(wù)器可以以接近優(yōu)化基準(zhǔn)測(cè)試所達(dá)到的速度運(yùn)行。
添加反向代理服務(wù)器還可以增加 Web 服務(wù)器設(shè)置的靈活性。例如,如果執(zhí)行既定任務(wù)的服務(wù)器過載了,您可以輕松添加一臺(tái)同類型的服務(wù)器;如果一臺(tái)服務(wù)器宕機(jī),那么替換它也不難。
鑒于這種靈活性,反向代理服務(wù)器往往也是許多其他性能優(yōu)化手段的先決條件,例如:
負(fù)載均衡(見技巧 2) ?
在反向代理服務(wù)器上運(yùn)行負(fù)載均衡器,以便在多個(gè)應(yīng)用服務(wù)器之間均勻地共享流量。借助負(fù)載均衡器,您無需更改應(yīng)用即可添加應(yīng)用服務(wù)器。
緩存靜態(tài)文件(見技巧 3) ?
直接請(qǐng)求的文件(如圖像文件或代碼文件)可以存儲(chǔ)在反向代理服務(wù)器上,并直接發(fā)送到客戶端,這樣不僅可以更快地提供資產(chǎn),還能減輕應(yīng)用服務(wù)器的負(fù)擔(dān),進(jìn)而加快應(yīng)用運(yùn)行速度。
保護(hù)站點(diǎn)安全
反向代理服務(wù)器可以配置為高安全性并進(jìn)行監(jiān)控,以便快速識(shí)別和響應(yīng)攻擊,保護(hù)應(yīng)用服務(wù)器的安全。
NGINX 軟件一開始的設(shè)計(jì)定位就是具有上述附加功能的反向代理服務(wù)器。NGINX 采用了事件驅(qū)動(dòng)型處理方法,因此比傳統(tǒng)服務(wù)器效率更高。NGINX Plus 增添了更多高級(jí)反向代理功能,比如應(yīng)用健康檢查、特定請(qǐng)求的路由、高級(jí)緩存,并提供技術(shù)支持。
技巧 2
添加負(fù)載均衡器
添加負(fù)載均衡器相對(duì)簡(jiǎn)單,但卻能顯著提升站點(diǎn)性能和安全性。您不需要升級(jí)核心 Web 服務(wù)器的硬件性能或規(guī)模,而是直接使用負(fù)載均衡器將流量分發(fā)到多臺(tái)服務(wù)器。即使應(yīng)用寫得不好或者難以擴(kuò)展,負(fù)載均衡器也可以在應(yīng)用不做出任何更改的情況下改善用戶體驗(yàn)。
負(fù)載均衡器首先是一個(gè)反向代理服務(wù)器(見技巧 1),負(fù)責(zé)接收互聯(lián)網(wǎng)流量并將請(qǐng)求轉(zhuǎn)發(fā)給其他服務(wù)器。這里的關(guān)鍵在于負(fù)載均衡服務(wù)器可以支持兩臺(tái)或更多應(yīng)用服務(wù)器,使用您選擇的算法在不同的服務(wù)器間分配請(qǐng)求。最簡(jiǎn)單的負(fù)載均衡方法是輪詢,其中每個(gè)新請(qǐng)求都會(huì)被發(fā)送到列表中的下一臺(tái)服務(wù)器。將請(qǐng)求發(fā)送到活動(dòng)連接數(shù)最少的服務(wù)器也是常用的方法之一。NGINX Plus 還具有會(huì)話保持功能,即將當(dāng)前用戶的多個(gè)會(huì)話保持在同一臺(tái)服務(wù)器上。
負(fù)載均衡器可以避免出現(xiàn)一臺(tái)服務(wù)器過載而其他服務(wù)器過閑的情況,從而顯著提性能。此外,Web 服務(wù)器擴(kuò)容也會(huì)變得簡(jiǎn)單,您可以添加相對(duì)便宜的服務(wù)器,并確保物盡其用。
可以進(jìn)行負(fù)載均衡的協(xié)議包括 HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcached 以及其他應(yīng)用類型,包括了基于 TCP 的應(yīng)用和其他四層協(xié)議。您應(yīng)該分析您的 Web 應(yīng)用,確定它的類型以及性能短板是什么。
用于負(fù)載均衡的一臺(tái)或若干臺(tái)服務(wù)器還可以同時(shí)處理其他任務(wù),例如 SSL 終止、按客戶端來選擇HTTP/1.x?和 HTTP/2 的使用、靜態(tài)文件緩存等。
技巧 3
緩存靜態(tài)和動(dòng)態(tài)內(nèi)容
緩存可以通過更快地向客戶端交付內(nèi)容來改善 Web 應(yīng)用的性能。緩存可以運(yùn)用多種策略:預(yù)處理內(nèi)容以便在需要時(shí)快速交付內(nèi)容、將內(nèi)容存儲(chǔ)在更快的設(shè)備上、將內(nèi)容存儲(chǔ)在靠近客戶端的地方等等,這些策略也可以組合運(yùn)用。
緩存有兩種類型:
靜態(tài)內(nèi)容緩存
圖像文件 (JPEG、PNG) 和代碼文件 (CSS、JavaScript) 等不常更改的文件可以存儲(chǔ)在邊緣服務(wù)器上,以便快速從內(nèi)存或磁盤中檢索。
動(dòng)態(tài)內(nèi)容緩存
許多 Web 應(yīng)用都會(huì)為每個(gè)頁面請(qǐng)求生成新的 HTML。通過短暫緩存一份生成的 HTML 副本,您可以大大減少必須要生成的頁面總數(shù),同時(shí)仍然提供足夠滿足需求的新鮮內(nèi)容。
例如,假設(shè)一個(gè)頁面每秒被查看 10 次,那么緩存 1 秒就代表這個(gè)頁面有 90% 的請(qǐng)求來自緩存。如果您單獨(dú)緩存各個(gè)靜態(tài)內(nèi)容,那么即使是全新生成的頁面,也可能大部分來自緩存的內(nèi)容。
緩存 Web 應(yīng)用生成的內(nèi)容主要會(huì)用到三種技術(shù):
將內(nèi)容放到更靠近用戶的地方
離用戶越近,傳輸時(shí)間越少。
將內(nèi)容放到更快的機(jī)器上
機(jī)器越快,檢索越快。
將內(nèi)容從過度使用的機(jī)器上移除
在執(zhí)行某個(gè)特定任務(wù)時(shí),機(jī)器的運(yùn)行速度有時(shí)會(huì)比基準(zhǔn)性能慢得多,因?yàn)樗鼈兠τ谄渌蝿?wù)。在不同的機(jī)器上緩存可以提高緩存資源和非緩存資源的性能,因?yàn)橹鳈C(jī)過載較少。
Web 應(yīng)用緩存可以由內(nèi)(Web 應(yīng)用服務(wù)器)而外的實(shí)施。首先,緩存動(dòng)態(tài)內(nèi)容,以減少應(yīng)用服務(wù)器的負(fù)載。其次,緩存靜態(tài)內(nèi)容(包括動(dòng)態(tài)內(nèi)容的臨時(shí)副本),以進(jìn)一步減少應(yīng)用服務(wù)器的負(fù)載。然后,將緩存從應(yīng)用服務(wù)器轉(zhuǎn)移到更快和/或更靠近用戶的機(jī)器上,從而減輕應(yīng)用服務(wù)器的負(fù)擔(dān),縮短檢索和傳輸時(shí)間。
優(yōu)化的緩存可以極大地加快應(yīng)用速度。對(duì)于很多網(wǎng)頁來說,靜態(tài)數(shù)據(jù)(例如大圖像文件)往往占據(jù)一半以上的內(nèi)容。如果不緩存,檢索和傳輸此類數(shù)據(jù)可能會(huì)花好幾秒鐘,但是如果將數(shù)據(jù)緩存在本地,可能只花幾分之一秒。
對(duì)于緩存的實(shí)踐應(yīng)用,我們可以看這樣一個(gè)例子:NGINX 和 NGINX Plus 使用兩個(gè)指令來設(shè)置緩存:proxy_cache_path?和 proxy_cache。您可以指定緩存的位置和大小、文件的最長緩存時(shí)間以及其他參數(shù)。
您甚至還可以使用指令 proxy_cache_use_stale(相當(dāng)受歡迎),指示緩存在本應(yīng)提供新鮮內(nèi)容的服務(wù)器太忙或停機(jī)時(shí)提供舊文件,畢竟對(duì)客戶端來說,有總比沒有強(qiáng)。這可能會(huì)極大地改善您的網(wǎng)站或應(yīng)用的正常運(yùn)行時(shí)間,給用戶樹立一種十分穩(wěn)定的形象。
NGINX Plus 具有高級(jí)緩存功能,包括支持緩存清除、在儀表盤上以可視化的形式顯示緩存狀態(tài)(以監(jiān)控實(shí)時(shí)活動(dòng))等。
有關(guān) NGINX 緩存的更多信息,請(qǐng)參見參考文檔和《NGINX Plus 管理員指南》。
注意:緩存跨越了應(yīng)用開發(fā)人員、資本投資決策人員和實(shí)時(shí)網(wǎng)絡(luò)運(yùn)營人員之間的組織界線。復(fù)雜的緩存策略(比如本文提到的這些)很好地體現(xiàn)了 DevOps 的價(jià)值,其中應(yīng)用開發(fā)人員、架構(gòu)師和運(yùn)營人員攜手合作,朝著保障網(wǎng)站功能、響應(yīng)時(shí)間、安全和業(yè)務(wù)成效(比如完成的交易或銷售)的目標(biāo)共同發(fā)力。
技巧 4
壓縮數(shù)據(jù)
壓縮是一個(gè)重要的、潛在的性能加速器。圖片(JPEG 和 PNG)、視頻 (MPEG-4) 和音樂 (MP3) 等文件都有著精心打造和非常高效的壓縮標(biāo)準(zhǔn),其中任何一個(gè)標(biāo)準(zhǔn)都可以將文件縮小一個(gè)數(shù)量級(jí)甚至更多。
HTML(包括純文本和 HTML 標(biāo)簽)、CSS 和代碼(如 JavaScript)等文本數(shù)據(jù)經(jīng)常在不壓縮的情況下進(jìn)行傳輸。壓縮這些數(shù)據(jù)可能會(huì)對(duì)感知到的 Web 應(yīng)用性能產(chǎn)生特別明顯的影響,尤其是對(duì)速度緩慢或移動(dòng)連接受限的客戶端來說。
這是因?yàn)槲谋緮?shù)據(jù)通常足以讓用戶與頁面進(jìn)行交互,而多媒體數(shù)據(jù)可能更多的體現(xiàn)支持性或錦上添花的作用。智能內(nèi)容壓縮通常可以將 HTML、Javascript、CSS 和其他文本內(nèi)容的帶寬需求減少 30% 及以上,并相應(yīng)地減少加載時(shí)間。
如果使用 SSL,壓縮可以減少必須進(jìn)行 SSL 編碼的數(shù)據(jù)量,從而抵消壓縮數(shù)據(jù)所需的一些 CPU 時(shí)間。
壓縮文本數(shù)據(jù)的方法有很多。例如,技巧 6?中就提到了一種在 SPDY 和 HTTP/2 中壓縮文本的新穎機(jī)制,該機(jī)制專門針對(duì)請(qǐng)求頭數(shù)據(jù)進(jìn)行了調(diào)整。還有一個(gè)文本壓縮的例子,那就是您可以在 NGINX 中啟用 GZIP?壓縮功能。在服務(wù)中預(yù)壓縮文本數(shù)據(jù)之后,您可以使用 gzip_static?指令直接提供壓縮的 .gz?文件。
技巧 5
優(yōu)化 SSL/TLS
安全套接字層 (SSL) 協(xié)議及其升級(jí)版?zhèn)鬏攲影踩?(TLS) 協(xié)議在網(wǎng)站中的應(yīng)用越來越廣泛。SSL/TLS 通過加密從源服務(wù)器傳輸給用戶的數(shù)據(jù)來提高站點(diǎn)安全性。Google 現(xiàn)在將 SSL/TLS 的使用作為搜索引擎排名的加分項(xiàng),這在某種程度上加速了這一技術(shù)的普及。
雖然 SSL/TLS 變得越來越受歡迎,但它們帶來的相關(guān)性能問題也困擾著許多網(wǎng)站。SSL/TLS 拖慢網(wǎng)站的原因有兩個(gè):
1.?每當(dāng)打開新連接時(shí),建立加密密鑰都需要進(jìn)行初始握手。瀏覽器使用 HTTP/1.x?時(shí)對(duì)每臺(tái)服務(wù)器建立多個(gè)連接的方式加劇了這個(gè)問題。
2.?服務(wù)器端加密數(shù)據(jù)和客戶端解密數(shù)據(jù)也會(huì)帶來持續(xù)的開銷。
為了鼓勵(lì)人們使用 SSL/TLS,HTTP/2 和 SPDY 協(xié)議(見技巧 6)應(yīng)運(yùn)而生,這樣瀏覽器只需為每次會(huì)話建立一個(gè)連接便可,同時(shí)也搞定了 SSL 的一大開銷來源。但是,通過 SSL/TLS 交付的應(yīng)用還有很大的性能提升空間。
SSL/TLS 的優(yōu)化機(jī)制因 Web 服務(wù)器而異。例如,NGINX 使用在標(biāo)準(zhǔn)商用硬件上運(yùn)行的 OpenSSL?來提供與專用硬件解決方案相媲美的性能。NGINX 的 SSL 性能優(yōu)化是有據(jù)可查的,可以將執(zhí)行 SSL/TLS 加密和解密的時(shí)間及 CPU 消耗降到最低。
此外,本博文還詳細(xì)介紹了提升 SSL/TLS 性能的其他方式,簡(jiǎn)而言之,這些技術(shù)是:
會(huì)話緩存
使用 ssl_session_cache?指令緩存保護(hù)每個(gè) SSL/STL 新連接時(shí)使用的參數(shù)。
Session Ticket 或 ID
將特定 SSL/TLS 會(huì)話的信息存儲(chǔ)在 ticket 或 ID 中,這樣無需再次握手即可順利重用連接。
OCSP Stapling
通過緩存 SSL/TLS 證書信息縮短握手時(shí)間。
NGINX 和 NGINX PLUS 支持 SSL/TLS 終止,即在處理客戶端流量加密和解密的同時(shí),與其他服務(wù)器進(jìn)行明文通信。如欲設(shè)置 NGINX 或 NGINX Plus 的 SSL/TLS 終止功能,請(qǐng)參見 HTTPS 連接和?TCP 加密連接的說明。
技巧 6
實(shí)施 HTTP/2 或 SPDY
對(duì)于已經(jīng)使用 SSL/TLS 的站點(diǎn),HTTP/2 和 SPDY 可能會(huì)讓性能更上一層樓,因?yàn)橐粋€(gè)連接僅需要一次握手。對(duì)于尚未使用 SSL/TLS 的站點(diǎn),HTTP/2 和 SPDY 從響應(yīng)性的角度來看,轉(zhuǎn)向 SSL/TLS(通常會(huì)降低性能)是一種洗禮。
Google 在 2012 年推出了 SPDY,致力于在 HTTP/1.x?之上實(shí)現(xiàn)更快的速度。HTTP/2 是 IETF 最近批準(zhǔn)的基于 SPDY 的標(biāo)準(zhǔn)。SPDY 得到了廣泛的支持,但很快就會(huì)被 HTTP/2 取代。
SPDY 和 HTTP/2 的關(guān)鍵功能是使用單個(gè)連接而非多個(gè)連接。單個(gè)連接是多路復(fù)用的,因此它可以同時(shí)承載多個(gè)請(qǐng)求和響應(yīng)。
通過充分利用一個(gè)連接,這些協(xié)議避免了設(shè)置和管理多個(gè)連接(瀏覽器實(shí)施 HTTP/1.x?的必要條件)的開銷。使用單個(gè)連接對(duì) SSL 尤為有用,因?yàn)檫@可以將 SSL/TLS 建立安全連接所需的握手時(shí)間降到最少。
SPDY 協(xié)議要求使用 SSL/TLS;HTTP/2 沒有對(duì)此作出正式要求,但目前所有支持 HTTP/2 的瀏覽器都只會(huì)在啟用 SSL/TLS 的情況下使用它。也就是說,只有當(dāng)網(wǎng)站使用 SSL 且其服務(wù)器接受 HTTP/2 流量時(shí),支持 HTTP/2 的瀏覽器才能使用 HTTP/2,否則瀏覽器將通過 HTTP/1.x?通信。
實(shí)施 SPDY 或 HTTP/2 后,就用不到域分片 (domain sharding)、資源合并、圖像拼合 (image spriting) 等典型的 HTTP 性能優(yōu)化技術(shù)了。這些變動(dòng)也可以簡(jiǎn)化代碼和部署的管理。如欲詳細(xì)了解 HTTP/2 帶來的變化,請(qǐng)參閱我們的白皮書:《面向 Web 應(yīng)用開發(fā)人員的 HTTP/2》。
在對(duì)這些協(xié)議的支持方面,NGINX 從很早就開始支持 SPDY 了,并且現(xiàn)在使用 SPDY 的大多數(shù)站點(diǎn)都部署了 NGINX。NGINX 也是率先支持?HTTP/2 的開拓者之一,從 2015 年 9 月起,NGINX 開源版和 NGINX Plus 就引入了對(duì) HTTP/2 的支持。
NGINX 希望隨著時(shí)間的推移,大多數(shù)站點(diǎn)都能完全啟用 SSL 并遷移到 HTTP/2。這不僅有助于提高安全性,而且隨著新型優(yōu)化技術(shù)的發(fā)現(xiàn)和實(shí)施,性能更高的代碼也將得到進(jìn)一步簡(jiǎn)化。
技巧 7
更新軟件版本
提高應(yīng)用性能的一種簡(jiǎn)單方法是根據(jù)穩(wěn)定性和性能為您的軟件棧選擇組件。此外,由于高質(zhì)量組件的開發(fā)人員可能會(huì)不斷增強(qiáng)性能和修復(fù) bug,使用最新的穩(wěn)定版軟件是非常劃算的。新版本會(huì)受到開發(fā)人員和用戶社區(qū)的更多關(guān)注,同時(shí)也會(huì)利用新的編譯器優(yōu)化技術(shù),包括對(duì)新硬件的調(diào)優(yōu)。
從兼容性和性能角度來看,新發(fā)布的穩(wěn)定版本通常也比舊版本更勝一籌。堅(jiān)持軟件更新還可以讓您在調(diào)優(yōu)、bug 修復(fù)和安全警報(bào)方面保持優(yōu)勢(shì)。
使用舊版本會(huì)妨礙新功能使用。例如,上文提到的 HTTP/2 目前要求使用 OpenSSL 1.0.1.。從 2016 年年中開始,HTTP/2 會(huì)要求使用 OpenSSL 1.0.2(于 2015 年 1 月發(fā)布)。
NGINX 用戶可以先從升級(jí)到最新版的 NGINX?或 NGINX Plus?入手,它們具備套接字分片 (socket sharding) 和線程池(見技巧 9)等新功能,并且均會(huì)持續(xù)進(jìn)行性能調(diào)優(yōu)。然后再深入檢查一下堆棧中的軟件,盡量遷移到最新版本。
技巧 8
優(yōu)化 Linux 性能
Linux 是當(dāng)今大多數(shù) Web 服務(wù)器的底層操作系統(tǒng)。作為基礎(chǔ)架構(gòu)的基石,Linux 蘊(yùn)藏著重大的調(diào)優(yōu)潛能。默認(rèn)情況下,許多 Linux 系統(tǒng)的優(yōu)化都比較保守,以占用少量資源、滿足常規(guī)桌面工作負(fù)載為目標(biāo)。這意味著在 Web 應(yīng)用用例中,要想達(dá)到最高性能,調(diào)優(yōu)是必不可少的。
Linux 優(yōu)化因 Web 服務(wù)器而異。以 NGINX 為例,您可以重點(diǎn)考慮從以下幾個(gè)方面給 Linux 提速:
積壓隊(duì)列 (Backlog Queue)?
如果有一些連接得不到處理,可以考慮增大 net.core.somaxconn?的值,即等待 NGINX 處理的最大連接數(shù)。如果當(dāng)前連接限制數(shù)太小,就會(huì)收到錯(cuò)誤消息,您可以逐漸增加此參數(shù),直到錯(cuò)誤消息不再出現(xiàn)。
文件描述符
NGINX 最多對(duì)每個(gè)連接使用兩個(gè)文件描述符。如果系統(tǒng)服務(wù)于很多連接,則可能需要增大 sys.fs.file_max(整個(gè)系統(tǒng)范圍內(nèi)對(duì)文件描述符的限制)以及 nofile(用戶文件描述符限制),以支持增加的負(fù)載。
臨時(shí)端口
當(dāng)用作代理時(shí),NGINX 會(huì)為每個(gè)上游服務(wù)器創(chuàng)建臨時(shí)端口。您可以使用 net.ipv4.ip_local_port_range?拉寬端口的值閾,以增加可用端口的數(shù)量。您還可以使用 net.ipv4.tcp_fin_timeout?減少重用非活動(dòng)端口之前的超時(shí),從而加快周轉(zhuǎn)。
對(duì)于 NGINX,請(qǐng)參見《NGINX 性能調(diào)優(yōu)指南》,了解如何優(yōu)化您的 Linux 系統(tǒng),使其輕松處理大量網(wǎng)絡(luò)流量!
技巧 9
優(yōu)化 Web 服務(wù)器的性能
無論您使用哪種 Web 服務(wù)器,都要對(duì)其進(jìn)行調(diào)優(yōu)才能提升 Web 應(yīng)用的性能。以下建議通常適用于任何 Web 服務(wù)器,其中包含一些針對(duì) NGINX 的特定設(shè)置。主要的優(yōu)化技術(shù)有:
訪問日志
不要立即將每個(gè)請(qǐng)求的日志寫到磁盤,可以先將條目放到內(nèi)存緩沖區(qū),然后再批量寫入。對(duì)于?NGINX,將?buffer=size?參數(shù)添加到?access_log?指令中,等內(nèi)存緩沖區(qū)寫滿后再把日志寫入磁盤。如果添加?flush=time?參數(shù),緩沖區(qū)的內(nèi)容也會(huì)在指定的時(shí)間過后寫入磁盤。
緩沖
緩沖用于在內(nèi)存中保存一部分響應(yīng),直到緩沖區(qū)填滿為止,可以實(shí)現(xiàn)與客戶端更高效的通信。不適合寫入內(nèi)存的響應(yīng)會(huì)被寫入磁盤,導(dǎo)致性能降低。啟用?NGINX?緩沖功能后,可以使用?proxy_buffer_size?和?proxy_buffers?指令進(jìn)行管理。
客戶端?keepalive?連接
Keepalive?連接可以減少開銷,尤其是在使用?SSL/TLS?時(shí)。對(duì)于?NGINX,您可以增加客戶端通過現(xiàn)有連接發(fā)出的?keepalive_requests?的最大數(shù)量(默認(rèn)值為?100),同時(shí)增大?keepalive_timeout?的值,讓?keepalive?連接保持更長時(shí)間的打開狀態(tài),從而加快后續(xù)請(qǐng)求的速度。
Upstream keepalive?連接
Upstream?連接,即與應(yīng)用服務(wù)器、數(shù)據(jù)庫服務(wù)器等服務(wù)器的連接,同樣可以從?keepalive?連接的設(shè)置中獲得好處。對(duì)于Upstream連接,您可以增加?keepalive,即為每個(gè)?worker?進(jìn)程保持打開狀態(tài)的空閑?keepalive?連接的數(shù)量。這可以增加對(duì)連接的重復(fù)使用,減少打開全新連接的需求。有關(guān)更多信息,請(qǐng)參閱我們的博文:《HTTP Keepalive?連接和?Web?性能》。
限流
限制客戶端使用的資源可以提升性能和安全性。對(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ù)器的連接,防止過載。關(guān)聯(lián)的?queue?指令會(huì)創(chuàng)建一個(gè)隊(duì)列,在達(dá)到?max_conns?限制后在指定的時(shí)間長度內(nèi)保存指定數(shù)量的請(qǐng)求。
Worker?進(jìn)程
Worker?進(jìn)程負(fù)責(zé)處理請(qǐng)求。NGINX?采用基于事件的模型和依賴操作系統(tǒng)的機(jī)制在?worker?進(jìn)程之間高效地分發(fā)請(qǐng)求。建議將?worker_processes?的值設(shè)置為每個(gè)?CPU?一個(gè)。如果需要,大多數(shù)系統(tǒng)都支持提高?worker_connections?的最大數(shù)值(默認(rèn)為?512),可以通過試驗(yàn)找出最適合您的系統(tǒng)的值。
套接字分片?(Socket Sharding)
套接字監(jiān)聽器通常會(huì)向所有?worker?進(jìn)程分發(fā)新連接。套接字分片?(Socket Sharding)?為每個(gè)?worker?進(jìn)程創(chuàng)建一個(gè)套接字監(jiān)聽器,由內(nèi)核在套接字監(jiān)聽器可用時(shí)為其指定連接。這可以減少鎖爭(zhēng)用并提高多核系統(tǒng)的性能。要啟用套接字分片功能,請(qǐng)?jiān)?listen?指令中添加?reuseport參數(shù)。
線程池
任何計(jì)算機(jī)進(jìn)程都可能會(huì)被一個(gè)緩慢的操作所拖累。對(duì)于 Web 服務(wù)器軟件,磁盤訪問可能阻礙很多較快的操作,例如內(nèi)存中的計(jì)算或信息復(fù)制。使用線程池時(shí),慢操作會(huì)被分配給一組單獨(dú)的任務(wù),而主處理循環(huán)仍然繼續(xù)運(yùn)行較快的操作。磁盤操作完成后,結(jié)果會(huì)返回到主處理循環(huán)。NGINX 將 read()?系統(tǒng)調(diào)用和 sendfile()?這兩個(gè)操作卸載到了線程池。
小貼士:如果要更改任何操作系統(tǒng)或支持服務(wù)的設(shè)置,請(qǐng)一次先更改一項(xiàng)設(shè)置,然后測(cè)試性能。如果更改引發(fā)了問題或者不會(huì)加快網(wǎng)站運(yùn)行速度,那就再改回去。
有關(guān) NGINX Web 服務(wù)器調(diào)優(yōu)的更多信息,請(qǐng)參見我們的博文:《優(yōu)化 NGINX 的性能》。
技巧 10
監(jiān)控實(shí)時(shí)活動(dòng),以解決問題和發(fā)現(xiàn)瓶頸
高效的應(yīng)用開發(fā)和交付方法的關(guān)鍵在于實(shí)時(shí)密切監(jiān)控應(yīng)用的真實(shí)性能。您必須要監(jiān)控特定設(shè)備和 Web 基礎(chǔ)架構(gòu)中的活動(dòng)。
監(jiān)控站點(diǎn)活動(dòng)多數(shù)時(shí)候是被動(dòng)的 —— 它只告訴您發(fā)生了什么,至于如何發(fā)現(xiàn)和解決問題,則是我們自己的事情。
監(jiān)控可以捕獲以下幾種不同的問題:
服務(wù)器停機(jī)。
服務(wù)器運(yùn)行不穩(wěn)定,導(dǎo)致連接中斷。
服務(wù)器出現(xiàn)大量緩存未命中問題。
服務(wù)器沒有發(fā)送正確的內(nèi)容。
全局應(yīng)用性能監(jiān)控工具(例如 New Relic 或 Dynatrace)可幫助您遠(yuǎn)程監(jiān)控頁面加載時(shí)間,NGINX 則可幫助您監(jiān)控應(yīng)用交付這一端。應(yīng)用性能數(shù)據(jù)可以顯示,您的優(yōu)化在什么情況下對(duì)用戶產(chǎn)生了真正的影響,以及什么情況下要為基礎(chǔ)架構(gòu)擴(kuò)容以滿足流量需求。
為了幫助快速發(fā)現(xiàn)和解決問題,NGINX Plus 增加了應(yīng)用感知型健康檢查功能,這類綜合事務(wù)(synthetic transaction)會(huì)定期重復(fù),在發(fā)現(xiàn)問題后向您發(fā)出告警。NGINX Plus 還具有會(huì)話耗盡功能,能夠在現(xiàn)有任務(wù)完成時(shí)停止新連接,其慢啟動(dòng)特性還允許恢復(fù)的服務(wù)器在負(fù)載均衡組內(nèi)逐漸升到正常水平。
只要使用得當(dāng),健康檢查就會(huì)幫助您及時(shí)發(fā)現(xiàn)問題,以免對(duì)用戶體驗(yàn)造成重大影響,會(huì)話耗盡和慢啟動(dòng)則允許您在不降低感知到的性能或正常運(yùn)行時(shí)間的情況下替換服務(wù)器。下圖展示了 NGINX Plus 內(nèi)置了 Web 基礎(chǔ)架構(gòu)的實(shí)時(shí)活動(dòng)監(jiān)控儀表盤,涵蓋了服務(wù)器、TCP 連接和緩存。
結(jié)論
實(shí)現(xiàn) 10 倍的性能提升
不同的 Web 應(yīng)用有著不同的性能提升空間,實(shí)際的效果取決于您的預(yù)算、投入的時(shí)間以及當(dāng)前實(shí)施的差距。那么,如何才能讓您的應(yīng)用實(shí)現(xiàn) 10 倍的性能提升呢?
為了幫助您理解每種優(yōu)化技術(shù)的潛在影響,下面分條列出了文中所述的各項(xiàng)技巧可能帶來的一些改進(jìn),希望大家各取所需。
反向代理服務(wù)器及負(fù)載均衡
沒有負(fù)載均衡或者負(fù)載均衡不好可能會(huì)導(dǎo)致性能極低。添加反向代理服務(wù)器(例如?NGINX)可以防止?Web?應(yīng)用在內(nèi)存和磁盤之間來回奔波。負(fù)載均衡可以將處理任務(wù)從過載的服務(wù)器轉(zhuǎn)移到可用的服務(wù)器,也可以簡(jiǎn)化擴(kuò)展。這些改變能夠顯著提升性能,與原有部署方式最差的時(shí)候相比,10?倍性能提升是很輕松的事,即使不到?10?倍也在總體上有了質(zhì)的飛躍。
緩存動(dòng)態(tài)和靜態(tài)內(nèi)容
如果您的?Web?服務(wù)器同時(shí)又超負(fù)荷地充當(dāng)應(yīng)用服務(wù)器,那么僅緩存動(dòng)態(tài)內(nèi)容就可以在高峰期達(dá)到?10?倍的性能提升,緩存靜態(tài)文件也可以實(shí)現(xiàn)幾倍的性能提升。
壓縮數(shù)據(jù)
使用?JPEG(照片)、PNG(圖形)、MPEG-4(電影)和?MP3(音樂文件)等媒體文件壓縮格式可以顯著提升性能。如果這些方式都用上了,那么壓縮文本數(shù)據(jù)(代碼和?HTML)可以將初始頁面加載速度提高兩倍。
優(yōu)化?SSL/TLS
安全握手對(duì)性能的影響很大,因此對(duì)其進(jìn)行優(yōu)化可能會(huì)讓初次響應(yīng)加快兩倍,尤其是對(duì)文本內(nèi)容較多的網(wǎng)站來說。如果是在?SSL/TLS?下優(yōu)化媒體文件傳輸,性能優(yōu)化的效果可能不是很大。
實(shí)施?HTTP/2?和?SPDY
當(dāng)與?SSL/TLS?一起使用時(shí),這些協(xié)議可能會(huì)對(duì)網(wǎng)站整體性能帶來增量改進(jìn)。
Linux?和?Web?服務(wù)器軟件(如?NGINX)調(diào)優(yōu)
優(yōu)化緩沖、使用?keepalive?連接、將耗時(shí)的任務(wù)卸載到獨(dú)立的線程池等修復(fù)措施可以顯著提升性能,例如線程池可以將磁盤操作密集型任務(wù)的速度提高大約一個(gè)數(shù)量級(jí)。
我們希望大家多多嘗試這些技術(shù),也期待聽到大家在改進(jìn)應(yīng)用性能方面的心得。
編輯:黃飛
?
評(píng)論
查看更多