為什么要優化 Ngin HTTPS 延遲
Nginx 常作為最常見的服務器,常被用作負載均衡 (Load Balancer)、反向代理 (Reverse Proxy),以及網關 (Gateway) 等等,一個配置得當的 Nginx 服務器單機應該可以期望承受住 50K 到 80K 左右每秒的請求,同時將 CPU 負載在可控范圍內, 但在很多時候,負載并不是需要首要優化的重點,比如對于卡拉搜索來說,我們希望用戶在每次擊鍵的時候,可以體驗即時搜索的感覺,也就是說,每個搜索請求必須在 100ms - 200ms 的時間內端對端地回傳給用戶,才能讓用戶搜索時沒有“卡頓”和“加載”,因此,對于我們來說,優化請求延遲才是最重要的優化方向,2021Java面試寶典 這篇文章中,我們先介紹 Nginx 中的 TLS 設定有哪些與請求延遲可能相關,如何調整才能最大化加速,然后我們用優化卡拉搜索 Nginx 服務器的實體來分享如何調整 Nginx TLS/SSL 設定,為首次搜索的用戶提速 30% 左右,我們會詳細討論每一步我們做了一些什么優化,優化的動機和效果,希望可以對其它遇到類似問題的同學提供幫助, 照例,本文的 Nginx 設定檔案放置于 github,歡迎直接使用: 高性能 Nginx HTTPS 調優(https://github.com/Kalasearch/high-performance-nginx-tls-tuning)TLS 握手和延遲
很多時候開發者會認為:如果不是絕對在意性能,那么了解底層和更細節的優化沒有必要,這句話在很多時候是恰當的,因為很多時候復雜的底層邏輯必須包起來,才能讓更高層的應用開發復雜度可控,比如說,如果你就只需要開發一個 APP 或者網站,可能并沒有必要關注匯編細節,關注編譯器如何優化你的代碼——畢竟在蘋果或者安卓上很多優化在底層就做好了, 那么,了解底層的 TLS 和應用層的 Nginx 延遲優化有什么關系呢? 答案是多數情況下,優化網路延遲其實是在嘗試減少用戶和服務器之間的資料傳輸次數,也就是所謂的 roundtrip,由于物理限制,北京到云南的光速傳播差不多就是要跑 20 來毫秒,如果你不小心讓資料必須多次往返于北京和云南之間,那么必然延遲就上去了, 因此如果你需要優化請求延遲,那么了解一點底層網路的背景關系則會大有裨益,很多時候甚至是你是否可以輕松理解一個優化的關鍵,本文中我們不深入討論太多 TCP 或者 TLS 機制的細節,如果有興趣的話請參考 High Performance Browser Networking 一書, 舉個例子,下圖中展示了如果你的服務啟用了 HTTPS,在開始傳輸任何資料之前的資料傳輸情況,可以看到,在你的用戶拿到他需要的資料前,底層的資料包就已經在用戶和你的服務器之間跑了 3 個來回, 假設每次來回需要 28 毫秒的話,用戶已經等了 224 毫秒之后才開始接收資料, 同時這個 28 毫秒其實是非常樂觀的假設,在國內電信、聯通和移動以及各種復雜的網路狀況下,用戶與服務器之間的延遲更不可控,另一方面,通常一個網頁需要數十個請求,這些請求不一定可以全部并行,因此幾十乘以 224 毫秒,頁面打開可能就是數秒之后了, 所以,原則上如果可能的話,我們需要盡量減少用戶和服務器之間的往返程 (roundtrip),在下文的設定中,對于每個設定我們會討論為什么這個設定有可能幫助減少往返程,
Nginx 中的 TLS 設定
那么在 Nginx 設定中,怎樣調整引數會減少延遲呢?開啟 HTTP/2
HTTP/2 標準是從 Google 的 SPDY 上進行的改進,比起 HTTP 1.1 提升了不少性能,尤其是需要并行多個請求的時候可以顯著減少延遲,在現在的網路上,一個網頁平均需要請求幾十次,而在 HTTP 1.1 時代瀏覽器能做的就是多開幾個連接(通常是 6 個)進行并行請求,而 HTTP 2 中可以在一個連接中進行并行請求,HTTP 2 原生支持多個并行請求,因此大大減少了順序執行的請求的往返程,可以首要考慮開啟, 如果你想自己看一下 HTTP 1.1 和 HTTP 2.0 的速度差異,可以試一下:https://www.httpvshttps.com/,我的網路測驗下來 HTTP/2 比 HTTP 1.1 快了 66%,listen 443 ssl; # 改為 listen 443 ssl http2;如果你擔心你的用戶用的是舊的客戶端,比如 Python 的 requests,暫時還不支持 HTTP 2 的話,那么其實不用擔心,如果用戶的客戶端不支持 HTTP 2,那么連接會自動降級為 HTTP 1.1,保持了后向兼容,因此,所有使用舊 Client 的用戶,仍然不受影響,而新的客戶端則可以享受 HTTP/2 的新特性,
如何確認你的網站或者 API 開啟了 HTTP 2
在 Chrome 中打開開發者工具,點開 Protocol 之后在所有的請求中都可以看到請求用的協議了,如果 protocol 這列的值是 h2 的話,那么用的就是 HTTP 2 了? ~ curl --http2 -I https://kalasearch.cn HTTP/2 403 server: Tengine content-type: application/xml content-length: 264 date: Tue, 22 Dec 2020 18:38:46 GMT x-oss-request-id: 5FE23D363ADDB93430197043 x-oss-cdn-auth: success x-oss-server-time: 0 x-alicdn-da-ups-status: endOs,0,403 via: cache13.l2et2[148,0], cache10.l2ot7[291,0], cache4.us13[360,0] timing-allow-origin: * eagleid: 2ff6169816086623266688093e
調整 Cipher 優先級
盡量挑選更新更快的 Cipher,有助于減少延遲:# 手動啟用 cipher 串列 ssl_prefer_server_ciphers on; # prefer a list of ciphers to prevent old and slow ciphers ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
啟用 OCSP Stapling
在國內這可能是對使用 Let's Encrypt 證書的服務或網站影響最大的延遲優化了,如果不啟用 OCSP Stapling 的話,在用戶連接你的服務器的時候,有時候需要去驗證證書,而因為一些不可知的原因(這個就不說穿了)Let's Encrypt 的驗證服務器并不是非常通暢,因此可以造成有時候數秒甚至十幾秒延遲的問題,這個問題在 iOS 設備上特別嚴重 解決這個問題的方法有兩個:- 不使用 Let's Encrypt,可以嘗試替換為阿里云提供的免費 DV 證書
- 開啟 OCSP Stapling
ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /path/to/full_chain.pem;
如何檢測 OCSP Stapling 是否已經開啟?
可以通過以下命令openssl s_client -connect test.kalasearch.cn:443 -servername kalasearch.cn -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"來測驗,如果結果為
OCSP response:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
則表明已經開啟,參考 HTTPS 在 iPhone 上慢的問題 一文
調整 ssl_buffer_size
sslbuffersize 控制在發送資料時的 buffer 大小,默認設定是 16k,這個值越小,則延遲越小,而添加的報頭之類會使 overhead 會變大,反之則延遲越大,overhead 越小, 因此如果你的服務是 REST API或者網站的話,將這個值調小可以減小延遲和 TTFB,但如果你的服務器是用來傳輸大檔案的,那么可以維持 16k,關于這個值的討論和更通用的 TLS Record Size 的討論,可以參考:Best value for nginx's sslbuffersize option 如果是網站或者 REST API,建議值為 4k,但是這個值的最佳取值顯然會因為資料的不同而不一樣,因此請嘗試 2 - 16k 間不同的值,在 Nginx 中調整這個值也非常容易ssl_buffer_size 4k;
啟用 SSL Session 快取
啟用 SSL Session 快取可以大大減少 TLS 的反復驗證,減少 TLS 握手的 roundtrip,雖然 session 快取會占用一定記憶體,但是用 1M 的記憶體就可以快取 4000 個連接,可以說是非常非常劃算的,同時,對于絕大多數網站和服務,要達到 4000 個同時連接本身就需要非常非常大的用戶基數,因此可以放心開啟, 這里 ssl_session_cache 設定為使用 50M 記憶體,以及 4 小時的連接超時關閉時間 ssl_session_timeout# Enable SSL cache to speed up for return visitors ssl_session_cache shared:SSL:50m; # speed up first time. 1m ~= 4000 connections ssl_session_timeout 4h;
卡拉搜索如何減少 30% 的請求延遲
卡拉搜索是國內的 Algolia,致力于幫助開發者快速搭建即時搜索功能(instant search),做國內最快最易用的搜索即服務, 開發者接入后,所有搜索請求通過卡拉 API 即可直接回傳給終端用戶,為了讓用戶有即時搜索的體驗,我們需要在用戶每次擊鍵后極短的時間內(通常是 100ms 到 200ms)將結果回傳給用戶,因此每次搜索需要可以達到 50 毫秒以內的引擎處理時間和 200 毫秒以內的端對端時間,我們用豆瓣電影的資料做了一個電影搜索的 Demo,如果感興趣的話歡迎體驗一下即時搜索,嘗試一下搜索“無間道”或者“大話西游”體驗一下速度和相關度:https://movies-demo.kalasearch.cn/對于每個請求只有 100 到 200 毫秒的延遲預算,我們必須把每一步的延遲都考慮在內, 簡化一下,每個搜索請求需要經歷的延遲有
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/262357.html
標籤:Java
上一篇:學習筆記
