2020-06-02 09:41:00
譯者:為之漫筆
來源:http://www.zcfy.cc/article/10-tips-for-10x-application-performance-nginx-22.html
原文:https://www.nginx.com/blog/10-tips-for-10x-application-performance/
提升Web應用的性能從未像今天這樣刻不容緩,
在線經濟活動的比例日益提高,就連發展中國家和地區的經濟活動都已經有5%以上在線進行了(相關資料請參考本文后面的資源),在這個超級鏈接、隨時在線的現代世界,用戶的期望也遠非昔日可比,如果你的網站不能馬上回應,你的應用不能立即運行,用戶轉身就會投奔你的競爭對手,
亞馬遜大約10年前的一項研究表明,頁面加載時間減少1/10秒,能夠使其營收增長1%,另一項近期的調查也顯示,一多半受訪站點所有者提到因為自己應用的性能不佳導致了收入減少或者用戶流失,
一個網站到底多快才行?頁面加載每花1秒鐘,就有大約4%的用戶走掉,排名最靠前的電商站點的首次互動時間為1至3秒,這個區間的轉換率最高,顯而易見,Web應用性能的重要性與日俱增,
提升性能其實不難,難的是怎么看到結果,本文給出能夠提升大約10倍網站性能的10個建議供大家參考,如此全面地涵蓋各種性能優化技術,這還是頭一回,但這些建議可能需要NGINX的一點支持,除了性能,這些建議也會涉及提升安全性,
建議一:使用反向代理服務器讓應用更快更安全

如果你的Web應用只跑在一臺機器上,那要提升其性能非常簡單:換一臺更快的,多配幾個處理器,多加幾條記憶體,磁盤陣列也要高速的,換了以后,這臺機器上跑的WordPress服務器、Node.js或Java應用速度都會加快,(要是應用還會訪問另一臺資料庫服務器,那也簡單:找兩臺更快的機器,用更快的網路連起來就行了,)
麻煩在于,機器速度并不是問題,很多時候Web應用慢,是因為要在各種任務之間切換,一會兒要處理數千個連接上的用戶請求,一會兒要向磁盤讀寫檔案,一會兒又要運行應用的代碼,一會兒又要去干別的,應用服務器因此可能出現各種狀況,耗盡記憶體、交換檔案,或者讓很多請求等待一個硬碟I/O之類的任務,
除了升級硬體,其實你還可以選擇另外一種完全不同的方法:加一臺反向代理服務器,分擔上述一些任務,反向代理服務器位于運行應用的機器之前,負責處理來自外網的請求,反向代理服務器直接連到互聯網,它與應用服務器通信使用的是快速的內部網路,
反向代理服務器可以讓應用服務器專注于構建頁面,然后交給反向代理向外網發送,而不必理會用戶與應用的互動,由于不必等待客戶端的回應,應用服務器的運行速度能達到接近最優的水平,
增加反向代理服務器同時也可以為Web服務器增添靈活性,比如,假設執行某種任務的服務器過載了,那隨時可以再增加一臺同類服務器;而如果這臺服務器掛了,替換它也很容易,
鑒于這種靈活性,反向代理服務器往往也是其他性能優化手段的先決條件,比如:
-
負載均衡(參見“建議二”),反向代理服務器上運行負載均衡服務,把流量平均分配給幾臺應用服務器,有了負載均衡,添加應用服務器根本不需要修改應用,
-
快取靜態檔案(參見“建議三”),圖片或代碼之類的可以直接請求的檔案,都可以保存在反向代理服務器中,以便直接發給客戶端,這樣不僅可以更快地回應請求,還能減輕應用服務器的負擔,加快其運行速度,
-
保證站點安全,可以配置反向代理服務器提升其安全級別,通過它監控來快速識別和回應攻擊,從而保存應用服務器安全,
NGINX專門為使用反向代理服務器做了設計,使其天然支持上述優化,由于使用事件驅動的處理機制,NGINX比傳統服務器效率更高,NGINX Plus則增加了更高端的反向代理功能,如應用體檢、特有的請求路由、高級快取和售后支持,

傳統服務器與NGINX Worker的比較
建議二:增加負載均衡服務器

增加負載均衡服務器相對簡單,但卻能顯著提升站點性能和安全性,通過它把流量分配給多個服務器,就可以不必升級Web服務器了,就算應用本身寫得不太好,或者難以擴展,負載均衡都可以在不做其他改變的情況下提升用戶體驗,
負載均衡服務器首先是一個反向代理服務器(參見“建議一”),負責把來自互聯網的請求轉發給其他服務器,這里關鍵在于負載均衡服務器可以支持兩臺以上的應用服務器,使用一種選擇演算法在不同的服務器間分配請求,最簡單的負載均衡演算法是回圈調度,即把新請求依次轉發給可用服務器中的下一臺服務器,其他演算法還有把請求發給活動連接最少的服務器,NGINX Plus支持一種功能,就是把用戶會話保持在同一臺服務器上,叫做會話保持,
負載均衡服務器可以避免一臺服務器過載而其他服務器過閑,從而極大提升性能,同時,有了它還可以讓Web服務器擴容更簡單,因為可以選用比較便宜的服務器,同時保證物盡其用,
可以通過負載均衡調度的協議包括HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcached,以及其他一些應用形式,包括基于TCP的應用和其他第四層的協議,為此,首先要分析Web應用,看性能短板在哪里,然后再確定使用哪一個,
同一臺服務器或用于負載均衡的服務器也可以承擔其他任務,比如SSL終止、視客戶端不同支持HTTP/1/x或HTTP/2、快取靜態檔案,
NGINX經常被用來做負載均衡,更多資訊請參考我們以前發的介紹性文章、有關配置的文章、電子書和相關的在線視頻,當然還有檔案,我們的商業版本NGINX Plus支持更多的負載均衡功能,如基于服務器回應時間路由負載和支持微軟NTLM協議的負載均衡,
建議三:快取靜態及動態內容
緩存能提升Web應用性能,因為可以更快地把內容交付給客戶端,快取的策略包括預處理內容、在較快的設備上存盤內容、把內容保存在靠近客戶端的地方,以及同時運用這些策略,
快取有兩種,
-
靜態內容快取,不常變化的檔案,如圖片(JPEG、PNG)和代碼(CSS、JavaScript),可以保存在邊緣服務器中,以便快速從內容或磁盤中獲取,
-
動態內容快取,很多Web應用會為每個頁面請求生成全新的HTML,把生成的每個HTML都快取一小段時間,可能顯著減少需要生成的頁面總數,同時又可以保證交付的內容足夠新鮮,
假設一個頁面每秒被查看10次,而你快取它1秒,那么90%針對這個頁面的請求都將來自在快取,如果你單獨快取靜態內容,那么即使全新生成的頁面,很可能大部分都來自快取的內容,
快取Web應用生成內容的技術主要分三種,
-
把內容放到離用戶近的地方,離用戶近,傳輸時間少,
-
把內容放到較快的機器上,機器快,檢索速度快,
-
把內容從過度使用的機器中拿走,有時候機器會比在專注執行特定任務時慢很多,那是因為太多任務讓它們分心,這時候把內容拿到其他機器上,不僅對快取的內容有好處,對非快取的內容同樣有利,因為托管它們的主機的負擔減輕了,
Web應用的快取可以在Web應用服務器內部或外部實作,首先,考慮快取動態內容,以減輕應用服務器的負載,其次,快取用于靜態內容(包括那些動態生成內容的臨時副本),進一步減輕應用服務器的負擔,然后,考慮把快取轉移到其他更快或更靠近用戶的機器,給應用服務器減負,縮短傳輸時間,
用好快取能顯著加快應用的回應速度,對很多網頁來說,大圖片之類的靜態資料,往往占據一半以上的內容,不用快取,查詢和傳輸這類資料可能會花好幾秒鐘,而用快取,則可能只要花幾分之一秒,
可以舉一個例子來說明怎么使用快取,NGINX和NGINX Plus通過兩個指令來設定快取:proxy_cache_path和proxy_cache指定快取的位置和大小、最長快取時間以及其他引數,使用第三個(也是很受歡迎的)指令proxy_cache_use_stale,甚至可以告訴快取在本來應該提供新鮮內容的服務器太忙或宕機時,提供原來的舊檔案,對客戶端來說,拿到內容總比拿不到強,從用戶角度看,這樣也可以樹立你的站點或應用非常穩定的形象,
NGINX Plus支持高級快取功能,包括快取凈化(caching purging)和通過控制板以可視化的形式展示快取狀態,實作實時監控,
要了解NGINX中關于快取的更多資訊,可以看看參考檔案和NGINX Plus Admin Guide中的NGINX Content Caching,另外,關注微信公眾號:Java技術堆疊,也可以獲取我整理的 NGINX 教程,都是干貨,
注意: 快取涉及開發、決策和運維,完善的快取策略,比如本文提到的這些,能夠體現從DevOps角度考慮的價值,也說是說,開發人員、架構師、運維人員此時攜手,共同保障一個網站的功能、回應時間、安全和業務目標,
建議四:壓縮資料

壓縮同樣能極大提升性能,圖片、視頻、音樂等檔案都有非常成熟和高效的壓縮標準(JPEG和PNG、MPEG-4、MP3),任何一個標準都可以把檔案大小縮小一個數量級甚至更多,
文本檔案,包括HTML(純文本和HTML標簽)、CSS和JavaScript代碼,經常在不壓縮的情況下傳輸,壓縮這些資料對提升Web應用的感知性能有時候特別明顯,尤其是移動用戶的網路很慢又不穩定的情況下,
因為文本資料通過對于頁面互動能夠起到必要的支援作用,而多媒體資料則更多是錦上添花的作用,聰明的內容壓縮可以把HTML、JavaScript、CSS等文本內容的縮小30%以上,因此能夠相應地減少加載時間,
如果你使用SSL,壓縮又可以減少必須經過SSL編碼的資料量,從而補償了壓縮這些資料的CPU時間,
壓縮資料的方法非常多,比如,建議六中關于HTTP/2的部分就描述了一個新穎的壓縮思路,特別適合首部資料壓縮,還有一個關于文本壓縮的例子,就是可以在NGINX中開啟GZIP壓縮,預壓縮文本資料之后,可以使用gzip_static指令直接發送.gz檔案,
建議五:優化SSL/TLS

越來越多的網站在使用Secure Sockets Layer(SSL)及后來的Transport Layer Security(TLS)協議,SSL/TLS通過加密從源服務器發送給用戶的資料來提升網站安全性,Google會提升使用SSL/TLS的網站的搜索引擎排名,將有力地推動這一行程,點擊這里了解SSL/TLS運行機制詳解,另外,關注微信公眾號:Java技術堆疊,也可以獲取我整理的更多 HTTPS 教程,都是干貨,
盡管采用率越來越高,但SSL/TLS造成的性能損失也困擾著很多網站,SSL/TLS拖慢網站的原因有兩個,
1、每次打開新連接的初次握手都必須創建加密密鑰,而瀏覽器使用HTTP/1.x對每個2、服務器建立多個連接的方式進一步加劇了這個問題,
服務器端加密資料和客戶端解密資料的操作同樣也是開銷,
▼
為了鼓勵人們使用SSL/TLS,HTTP/2和SPDY(參見建議六)的作者將這兩個協議設計為只讓瀏覽器針對一次會話建立一個連接,這樣就把SSL導致性能降低的兩個主要原因之一消滅掉了,然而,說到優化SSL/TLS性能,還是有很多事情可做,
優化SSL/TLS的方法因Web服務器而異,以NGINX為例,NGINX使用OpenSSL,運行于普通機器上,能夠提供接近定制機器的性能,NGINX SSL performance詳細介紹了如何將SSL/TLS加密和解密的開銷降至最低,
此外,這里還有一篇文章,介紹了很多種提升SSL/TLS性能的方法,簡單總結一下,涉及的技術主要有如下幾種,
-
會話快取,使用ssl_session_cache指令開啟快取,快取每次SSL/STL連接時用到的引數,
-
會話票或ID,把特定SSL/TLS會話的資訊保存為一個會話票或ID,以便連接重用,而不必重新握手,
-
OCSP封套,通過快取SSL/TLS證書資訊減少握手時間,
NGINX和NGINX Plus都可以來終止SSL/TLS,即處理客戶端資訊的加密和解密,同時與其他服務器保持明文通信,在NGINX或NGINX Plus中設定處理SSL/TLS終止可以采取這幾個步驟,而對于在接受TCP連接的服務器上使用NGINX Plus而言,可以參考這里的設定步驟,
建議六:實作HTTP/2或SPDY
已經使用SSL/TLS的站點,如果再使用HTTP/2或SPDY則很可能提升性能,因為一個連接只要一次握手,尚未使用SSL/TLS、HTTP/2和SPDY的站點切換到SSL/TLS(通常會降低性能),從回應速度方面看,可能是一次倒退,點擊這里了解HTTP/2詳解,
谷歌2012年開始SPDY專案,致力于在HTTP/1.x之上實作更快的速度,HTTP/2則是IETF最近批準的基于SPDY的標準,SPDY得到了廣泛支持,但很快就將被HTTP/2取代,
SPDY和HTTP/2的關鍵在于只用一個連接,而非多個連接,這一個連接是多路復用的,因此可以同時承載多個請求和回應,
只維持一個連接,可以省掉多個連接所需的設定和管理消耗,而且一個連接對SSL特別重要,因為可以將SSL/TLS建立安全連接所需的握手時間降至最少,
SPDY協議要求使用SSL/TLS,HTTP/2并沒有正式要求,但目前所有支持HTTP/2的瀏覽器都只會在啟用SSL/TLS的情況下才會使用它,換句話說,支持HTTP/2的瀏覽器只有在網站使用SSL且服務器接受HTTP/2流量的情況下才會使用HTTP/2,否則,瀏覽器會基于HTTP/1.x通信,
實作了SPDY或HTTP/2之后,域名分片、資源合并、圖片精靈等之前針對HTTP的性能優化措施就用不著了,因此也可以簡化代碼和部署,關于HTTP/2會帶來哪些變化,可以參考我們的這個白皮書,

NGINX很早就開始支持SPDY,而且今天使用SPDY的大多數站點都在運行NGIN
X,NGINX同樣率先支持了HTTP/2,2015年9月,NGINX開源和NGINX Plus開始支持 HTTP/2,
隨著時間推移,NGINX希望大多數站點啟用SSL并遷移到HTTP/2,這樣不僅可以讓網站更安全,而且隨著新的優化技術不斷涌現,也可以通過簡單的代碼實作更高的性能,
建議七:升級軟體
提升應用性能的一個簡單的方法,就是根據可靠性及性能選擇軟體,此外,高質量組件的開發者更可能不斷提升性能和修復問題,因此使用最新的穩定版本是劃算,新發布的版本會得到開發者和用戶更多的關注,同時也會利用新的編譯器優化技術,包括針對新硬體的調優,
相對舊版本,新發布的穩定版本明顯性能更高,堅持升級,也可以保證在調優、問題修復和安全警報方面與時俱進,
不升級軟體也會妨礙利用新能力,比如,HTTP/2目前要求OpenSSL 1.0.1,從2016年下半年開始,HTTP/2會要求OpenSSL 1.0.2,該版本發布于2015年1月,
NGINX用戶可以從NGINX開源軟體的最新版本或NGINX Plus開始,它們支持套接字共享、執行緒池(參見下文),而且都會持續優化性能,因此,檢查一下自己的軟體,盡量把它們升級到最新的版本,
建議八:調優Linux
Linux是今天大多數Web服務器的底層作業系統,作為一切基礎設施的基礎,Linux對提升性能至關重要,默認情況下,很多Linux系統都比較保守,僅以桌面辦公為需求,以占用少量資源為調優目標,對于Web應用而言,為達到性能最佳,肯定需要重新調優,
Linux優化因Web服務器而異,以NGINX為例,可以從以下幾方面考慮,另外,關注微信公眾號:Java技術堆疊,也可以獲取我整理的 NGINX 教程,都是干貨,
存量佇列,如果發現有一些連接得不到處理,可以增大net.core.somaxconn,即等待NGINX處理的最大連接數,如果這個連接數限制過小,應該可以看到錯誤訊息,可以逐步提高這個值,直到錯誤訊息不再出現,
-
檔案描述符,NGINX對每個連接最多使用兩個檔案描述符,如果系統服務于很多連接,可能需要增大sys.fs.file_max這個對描述符的系統級限制,以及nofile這個用戶檔案描述符限制,以支持增大后的負載,
-
臨時埠,在作為代理使用時,NGINX會為每個上游服務器創建臨時埠,可以設定net.ipv4.ip_local_port_range,增大埠值的范圍,以增加可用的埠量,此外,還可以減小net.ipv4.tcp_fin_timeout的值,它控制非活動埠釋放重用的等待時間,加快周轉,
-
對NGINX而言,請參考NGINX性能調優指南,了解如何不費吹灰之力將你的Linux系統優化為能夠支持更大的吞吐量,
建議九:調優Web服務器
無論使用什么Web服務器,都需要針對應用對其調優,以下建議適用于任何Web服務器,但會給出只有NGINX的設定說明,
-
訪問日志,不要每個請求的日志都馬上寫到磁盤,可以在記憶體里做個快取,然后批量定入,對NGINX而言,將buffer=_size_引數添加到access_log指令,等記憶體緩沖區寫滿后再把日志寫到磁盤,如果你添加了**flush=_time_**引數,那么緩沖區的內容也會按照指定時間寫入磁盤,
-
緩沖,緩沖用于在記憶體里保存部分回應,直到緩沖區被填滿,可以實作對客戶端更有效的回應,無法寫入記憶體的回應會被寫到磁盤,從而降低性能,在NGINX的緩沖啟用時,可以使用proxy_buffer_size和proxy_buffers指令來管理它,
-
客戶端活動連接,活動連接可以減少時間消耗,特別是在使用SSL/TLS的情下,對NGINX而言,可以針對客戶端提高keepalive_requests的數值,默認值為100;也可以增大keepalive_timeout的值,讓活動連接持續時間更長,從而讓后續請求得到更快回應,
-
上游活動連接,上游連接,即連接到應用服務器、資料庫服務器的連接,同樣可以從活動連接的設定中獲得好處,對上游連接來說,可以增加活動連接,也就是每個作業行程可用的空閑活動連接的數量,這樣可以增進連接重用,減少重開連接,關于活動連接的更多資訊,請參考這篇博客,
-
限制,限制客戶端使用的資源可以提升性能和安全性,對NGINX而言,limit_conn和limit_conn_zone指令限制指定源的連接數,而limit_rate限制帶寬,這些設定可以防止合法用戶“侵吞”資源,同時也有助于防止攻擊,limit_req和limit_req_zone指令限制客戶端請求,對于到上游服務器的連接,可以在上游配置區的服務器指令中使用max_conns引數,它限制對上游服務器的連接,防止過載,相關的佇列指令會創建一個佇列,在max_conns限制到達后將指定的請求數保存指定的時間,
-
作業行程,作業行程負責處理請求,NGINX采用基于事件的模型和OS相關的機制有效地在作業行程間分配請求,建議將worker_processes的值設定為每個CPU一個作業行程,如果需要,大多數系統都支持提高worker_connections的值(默認為512),可以通過試驗找到最適合你系統的這個值,
-
套接字分片,通常,一個套接字監聽器向所有作業行程分發新連接,套按字分片則為每個作業行程都創建一個套接字監聽器,由內核在套接字監聽器可用時為其指定連接,這樣可以減少鎖爭用,提升多核系統上的性能,要啟用套接字分片,在listen指令中包含reuseport引數,
-
執行緒池,一個費時的操作會阻塞任何計算機行程,對Web服務器軟體來說,磁盤訪問可能阻礙很多較快的操作,比如記憶體中的計算和復制,在使用執行緒池的情況下,慢操作會被指定給一組獨立的任務,而主處理回圈會繼續運行較快的操作,磁盤操作完成后,結果會回傳到主處理回圈,在NGINX中,read()系統呼叫和sendfile()被轉載到了執行緒池,

提示 修改任何作業系統及周邊設備的設定時,每次只修改一項,然后測驗性能,如果該項修改導致了問題,或者并未提升性能,再改回去,
建議十:監控實時動態以發現問題和瓶頸
保存應用高性能的關鍵是實時監控應用性能,必須實時監控特定設備及相應Web基礎設施中應用的動態,
監控站點活動多數情況下是被動的,它只告訴你發生了什么,至于如何發現和解決問題,則是你自己的事情,
監控可以捕獲以下幾種問題:
1、服務器停機
2、服務器不穩,漏處理連接
3、服務器出現大面積快取失效
4、服務器發送的內容不對
New Relic或Dynatrace等全域性的性能監控工具,可以幫我們監控遠程加載頁面的時間,而NGINX則可以幫你監控應用交付這一端,應用的性能資料可以告訴你優化手段什么時候真正給用戶帶去了不同的體驗,以及什么時候需要擴容以滿足越來越多的流量,
為了幫助用戶盡快發現問題,NGINX Plus增加了應用程式體檢功能,會報告經常重復出現的問題,NGINX Plus還具備session draining特性,會在已有任務完成前阻止新連接,以及慢啟動容量,從而讓恢復的服務器在負載均衡集群中達到應有的速度,使用得當的情況下,健康體檢會在問題顯著影響用戶體驗之前幫你定位問題,而session draining和慢啟動則讓你替換服務器時不影響感知的性能和在線時間,這張圖展示了NGINX Plus內置的實時活動監控的控制板,涵蓋了服務器、TCP連接和快取,

結論:10倍性能提升
性能提升因Web應用不同會有巨大差異,實際的提升取決于預算、時間,以及現有實作的與理想性能的差距,那么怎么讓你的應用獲得10倍的性能提升呢?
為了幫大家理解每項優化建議的潛能,下面再針對之前的建議給出一些實施方針,希望大家各取所需,
-
反向代理服務器及負載均衡,沒有負載均衡或池負載均衡,可能導致極低的性能,添加一個反向代理服務器,比如NGINX,可以減少Web應用在記憶體和磁盤之間的往返,負載均衡可以把任務從過載的服務器轉移到空閑的服務器,也便于擴展,這些改變能極大地提升性能,與原有的部署方式最差的時候相比,10倍性能提升是很輕松的事,即使不到10倍那也在總體上有了質的飛躍,
-
快取動態和靜態內容,如果你的Web服務器同時又充當了應用服務器,那么通過快取動態內容就可以達到高峰期10倍的性能提升,快取靜態內容也可以有幾倍的性能提升,
-
壓縮資料,使用JPEG、PNG、MPEG-4以及MP3等壓縮格式能顯著提升性能,如果這些手段都用上了,那么壓縮的文本資料(代碼及HTML)可以將初始頁面加載時間提升兩倍,
-
優化SSL/TLS,安全握手對性能有很大影響,因此對其進行優化可以讓初次回應加快兩倍,對于文本內容較多的網站尤其如此,優化SSL/TLS下的媒體檔案帶來的性能提升很小,
-
實施HTTP/2和SPDY,在使用SSL/TLS的情況下,這兩個協議有可能提升網站的整體性能,
-
調優Linux和Web服務器,使用優化的緩沖策略、使用活動連接,將耗時的任務轉載至獨立的執行緒池,可以顯著提升性能,比如執行緒池可以將磁盤操作密集性任務的性能提升至少一個數量級,
希望大家自己多嘗試以上技術,也希望大家分享自己在性能改進方面的心得,
關注公眾號Java技術堆疊回復"面試"獲取我整理的2020最全面試題及答案,
推薦去我的博客閱讀更多:
1.Java JVM、集合、多執行緒、新特性系列教程
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
4.Java、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/122630.html
標籤:Java
上一篇:Dart語言學習(九) 運算子
