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