久久久久无码精品,亚洲国产精品国语在线,国产成人精品热玖玖玖,国产福利一区二区在线观看

高性能 Nginx HTTPS 調優(yōu) - 如何為 HTTPS 提速 30%

2021-11-03 15:54:11 shuai.chang

睿智創(chuàng)新RAIZ,一體化IT服務提供商
為什么要優(yōu)化 Ngin HTTPS 延遲

Nginx 常作為最常見的服務器,常被用作負載均衡 (Load Balancer)、反向代理 (Reverse Proxy),以及網關 (Gateway) 等等。一個配置得當的 Nginx 服務器單機應該可以期望承受住 50K 到 80K 左右[1]每秒的請求,同時將 CPU 負載在可控范圍內。

但在很多時候,負載并不是需要首要優(yōu)化的重點。比如對于卡拉搜索來說,我們希望用戶在每次擊鍵的時候,可以體驗即時搜索的感覺,也就是說,每個搜索請求必須在 100ms - 200ms 的時間內端對端地返回給用戶,才能讓用戶搜索時沒有“卡頓”和“加載”。因此,對于我們來說,優(yōu)化請求延遲才是最重要的優(yōu)化方向。

這篇文章中,我們先介紹 Nginx 中的 TLS 設置有哪些與請求延遲可能相關,如何調整才能最大化加速。然后我們用優(yōu)化卡拉搜索[2] Nginx 服務器的實例來分享如何調整 Nginx TLS/SSL 設置,為首次搜索的用戶提速 30% 左右。我們會詳細討論每一步我們做了一些什么優(yōu)化,優(yōu)化的動機和效果。希望可以對其它遇到類似問題的同學提供幫助。

照例,本文的 Nginx 設置文件放置于 github,歡迎直接使用: 高性能 Nginx HTTPS 調優(yōu)[3]

TLS 握手和延遲

很多時候開發(fā)者會認為:如果不是絕對在意性能,那么了解底層和更細節(jié)的優(yōu)化沒有必要。這句話在很多時候是恰當的,因為很多時候復雜的底層邏輯必須包起來,才能讓更高層的應用開發(fā)復雜度可控。比如說,如果你就只需要開發(fā)一個 APP 或者網站,可能并沒有必要關注匯編細節(jié),關注編譯器如何優(yōu)化你的代碼——畢竟在蘋果或者安卓上很多優(yōu)化在底層就做好了。

那么,了解底層的 TLS 和應用層的 Nginx 延遲優(yōu)化有什么關系呢?

答案是多數情況下,優(yōu)化網絡延遲其實是在嘗試減少用戶和服務器之間的數據傳輸次數,也就是所謂的 roundtrip。由于物理限制,北京到云南的光速傳播差不多就是要跑 20 來毫秒,如果你不小心讓數據必須多次往返于北京和云南之間,那么必然延遲就上去了。

因此如果你需要優(yōu)化請求延遲,那么了解一點底層網絡的上下文則會大有裨益,很多時候甚至是你是否可以輕松理解一個優(yōu)化的關鍵。本文中我們不深入討論太多 TCP 或者 TLS 機制的細節(jié),如果有興趣的話請參考 High Performance Browser Networking[4] 一書,可以免費閱讀。

舉個例子,下圖中展示了如果你的服務啟用了 HTTPS,在開始傳輸任何數據之前的數據傳輸情況。

睿智創(chuàng)新RAIZ,一體化IT服務提供商
在傳輸數據前數據已經跑了好幾個來回 roundtrip

可以看到,在你的用戶拿到他需要的數據前,底層的數據包就已經在用戶和你的服務器之間跑了 3 個來回。

假設每次來回需要 28 毫秒的話,用戶已經等了 224 毫秒之后才開始接收數據。

同時這個 28 毫秒其實是非常樂觀的假設,在國內電信、聯(lián)通和移動以及各種復雜的網絡狀況下,用戶與服務器之間的延遲更不可控。另一方面,通常一個網頁需要數十個請求,這些請求不一定可以全部并行,因此幾十乘以 224 毫秒,頁面打開可能就是數秒之后了。

所以,原則上如果可能的話,我們需要盡量減少用戶和服務器之間的往返程 (roundtrip),在下文的設置中,對于每個設置我們會討論為什么這個設置有可能幫助減少往返程。

Nginx 中的 TLS 設置

那么在 Nginx 設置中,怎樣調整參數會減少延遲呢?

開啟 HTTP/2

HTTP/2 標準是從 Google 的 SPDY 上進行的改進,比起 HTTP 1.1 提升了不少性能,尤其是需要并行多個請求的時候可以顯著減少延遲。在現在的網絡上,一個網頁平均需要請求幾十次,而在 HTTP 1.1 時代瀏覽器能做的就是多開幾個連接(通常是 6 個)進行并行請求,而 HTTP 2 中可以在一個連接中進行并行請求。HTTP 2 原生支持多個并行請求,因此大大減少了順序執(zhí)行的請求的往返程,可以首要考慮開啟。

如果你想自己看一下 HTTP 1.1 和 HTTP 2.0 的速度差異,可以試一下:https://www.httpvshttps.com/。我的網絡測試下來 HTTP/2 比 HTTP 1.1 快了 66%。

睿智創(chuàng)新RAIZ,一體化IT服務提供商
HTTP 1.1 與 HTTP 2.0 速度對比

在 Nginx 中開啟 HTTP 2.0 非常簡單,只需要增加一個 http2 標志即可

listen 443 ssl;

# 改為
listen 443 ssl http2;

如果你擔心你的用戶用的是舊的客戶端,比如 Python 的 requests,暫時還不支持 HTTP 2 的話,那么其實不用擔心。如果用戶的客戶端不支持 HTTP 2,那么連接會自動降級為 HTTP 1.1,保持了后向兼容。因此,所有使用舊 Client 的用戶,仍然不受影響,而新的客戶端則可以享受 HTTP/2 的新特性。

如何確認你的網站或者 API 開啟了 HTTP 2

在 Chrome 中打開開發(fā)者工具,點開 Protocol 之后在所有的請求中都可以看到請求用的協(xié)議了。如果 protocol 這列的值是 h2 的話,那么用的就是 HTTP 2 了

睿智創(chuàng)新RAIZ,一體化IT服務提供商
用 Chrome 確認 HTTP/2 已經打開

當然另一個辦法是直接用 curl 如果返回的 status 前有 HTTP/2 的話自然也就是 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 優(yōu)先級

盡量挑選更新更快的 Cipher,有助于減少延遲[5]:

# 手動啟用 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 證書的服務或網站影響最大的延遲優(yōu)化了。如果不啟用 OCSP Stapling 的話,在用戶連接你的服務器的時候,有時候需要去驗證證書。而因為一些不可知的原因(這個就不說穿了)Let's Encrypt 的驗證服務器并不是非常通暢[6],因此可以造成有時候數秒甚至十幾秒延遲的問題[7],這個問題在 iOS 設備上特別嚴重

解決這個問題的方法有兩個:

  1. 不使用 Let's Encrypt,可以嘗試替換為阿里云提供的免費 DV 證書
  2. 開啟 OCSP Stapling

開啟了 OCSP Stapling 的話,跑到證書驗證這一步可以省略掉。省掉一個 roundtrip,特別是網絡狀況不可控的 roundtrip,可能可以將你的延遲大大減少。

在 Nginx 中啟用 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 上慢的問題[8] 一文。

調整 ssl_buffer_size

ssl_buffer_size 控制在發(fā)送數據時的 buffer 大小,默認設置是 16k。這個值越小,則延遲越小,而添加的報頭之類會使 overhead 會變大,反之則延遲越大,overhead 越小。

因此如果你的服務是 REST API[9] 或者網站的話,將這個值調小可以減小延遲和 TTFB,但如果你的服務器是用來傳輸大文件的,那么可以維持 16k。關于這個值的討論和更通用的 TLS Record Size 的討論,可以參考:Best value for nginx's ssl*buffer*size option[10]

如果是網站或者 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[11],致力于幫助開發(fā)者快速搭建即時搜索功能(instant search),做國內最快最易用的搜索即服務。

開發(fā)者接入后,所有搜索請求通過卡拉 API 即可直接返回給終端用戶。為了讓用戶有即時搜索的體驗,我們需要在用戶每次擊鍵后極短的時間內(通常是 100ms 到 200ms)將結果返回給用戶。因此每次搜索需要可以達到 50 毫秒以內的引擎處理時間和 200 毫秒以內的端對端時間。

我們用豆瓣電影的數據做了一個電影搜索的 Demo,如果感興趣的話歡迎體驗一下即時搜索,嘗試一下搜索“無間道”或者“大話西游”體驗一下速度和相關度:https://movies-demo.kalasearch.cn/

對于每個請求只有 100 到 200 毫秒的延遲預算,我們必須把每一步的延遲都考慮在內。

簡化一下,每個搜索請求需要經歷的延遲有

睿智創(chuàng)新RAIZ,一體化IT服務提供商
卡拉搜索的端對端延遲圖示

總延遲 = 用戶請求到達服務器(T1) + 反代處理(Nginx T2) + 數據中心延遲(T3) + 服務器處理 (卡拉引擎 T4) + 用戶請求返回(T3+T1)

在上述延遲中,T1 只與用戶與服務器的物理距離相關,而 T3 非常小(參考Jeff Dean Number[12])可以忽略不計。

所以我們能控制的大致只有 T2 和 T4,即 Nginx 服務器的處理時間和卡拉的引擎處理時間。

Nginx 在這里作為反向代理,處理一些安全、流量控制和 TLS 的邏輯,而卡拉的引擎則是一個在 Lucene 基礎上的倒排引擎。

我們首先考慮的第一個可能性是:延遲是不是來自卡拉引擎呢?

在下圖展示的 Grafana 儀表盤[13]中,我們看到除了幾個時不時的慢查詢,搜索的 95% 服務器處理延遲小于 20 毫秒。對比同樣的數據集上 benchmark 的 Elastic Search 引擎的 P95 搜索延遲則在 200 毫秒左右,所以排除了引擎速度慢的可能。

睿智創(chuàng)新RAIZ,一體化IT服務提供商
Search Grafana

而在阿里云監(jiān)控中,我們設置了從全國各地向卡拉服務器發(fā)送搜索請求。我們終于發(fā)現 SSL 處理時間時常會超過 300 毫秒,也就是說在 T2 這一步,光處理 TLS 握手之類的事情,Nginx 已經用掉了我們所有的請求時間預算。

同時檢查之后我們發(fā)現,在蘋果設備上搜索速度格外慢,特別是第一次訪問的設備。因此我們大致判斷應該是因為我們使用的 Let's Encrypt 證書的問題。

我們按照上文中的步驟對 Nginx 設置進行了調整,并將步驟總結出來寫了這篇文章。在調整了 Nginx TLS 的設置后,SSL 時間從平均的 140ms 降低到了 110ms 左右(全國所有省份聯(lián)通和移動測試點),同時蘋果設備上首次訪問慢的問題也消失了。

睿智創(chuàng)新RAIZ,一體化IT服務提供商
調整后延遲

在調整過后,全國范圍內測試的搜索延遲降低到了 150 毫秒左右。

總結

調整 Nginx 中的 TLS 設置對于使用 HTTPS 的服務和網站延遲有非常大的影響。本文中總結了 Nginx 中與 TLS 相關的設置,詳細討論各個設置可能對延遲的影響,并給出了調整建議。之后我們會繼續(xù)討論 HTTP/2 對比 HTTP 1.x 有哪些具體改進,以及在 REST API 使用 HTTP/2 有哪些優(yōu)缺點,請繼續(xù)關注。


我要咨詢
安庆市| 昭平县| 汉中市| 吴川市| 怀安县| SHOW| 涞水县| 镇宁| 榆树市| 铜山县| 苍梧县| 博湖县| 子洲县| 喜德县| 杂多县| 文山县| 贵溪市| 闽清县| 闻喜县| 德昌县| 常熟市| 长沙县| 阜新市| 崇义县| 广平县| 金川县| 沧源| 绥中县| 瓦房店市| 英山县| 连平县| 定安县| 襄樊市| 望奎县| 柳林县| 华宁县| 肥西县| 庆阳市| 高阳县| 麻栗坡县| 铜鼓县|