使用 NGINX 進行微程式快取的好處
【編者按】本文作者為 Owen Garrett,主要介紹使用 nginx 進行微程式快取的好處,輔之以生動的例項。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現。
NGINX 和 NGINX Plus 被廣泛應用於網站內容快取,小到個人網站,大到一些世界大型內容分發網站(CDNs),例如 MaxCDN 和 CloudFlare。
微程式快取通過將動態、非個人化的內容快取很短的時間,能有效加速這些內容的傳遞。在本文中,筆者將展示如何利用微程式快取技術將一個基於 WordPress 的應用程式最高提速400倍。
為什麼要快取內容?
快取能夠一舉兩得:通過更快地傳遞內容,快取可以改善網站效能,同時減輕源伺服器的負擔。快取的效率取決於內容的快取度。這些內容可以儲存多長時間,如何檢查更新,相同的快取內容可以發給多少使用者?
快取靜態內容,例如圖片、JavaScript 和 CSS 檔案和幾乎不變的網頁內容是個相當簡單的過程。快取更新的處理方法包括常規暫停、條件 Get,如果有必要,還可以用cache-busting技術來替換引用物件的URL。
快取個人化內容(即通過伺服器應用為每位使用者定製的內容)幾乎不可能,因為伺服器對同一資源的每次請求的回覆都不相同。伺服器端引用(SSI)和頁面片段快取(ESI)等技術可以協助組合網頁,但是這些技術很難實行,而且不一定能改善效能。
兩者中間是個有趣的待快取物件:可能會無計劃更換,但是並非針對每位使用者(或者在客戶端通過 JavaScript實現個性化)的動態內容。這類內容的生成代價很高,提供過時版本又會帶來新的問題。
適合快取的動態內容包括:
- 經常更新的新聞或部落格網站的首頁,每隔幾秒就有新文章釋出
- 最近資訊 RSS
- 持續整合(CI)或搭建平臺的進度頁面
- 庫存、進度或籌款計數
- 彩票開獎結果
- 日曆資料
- 在客戶端呈現的個人化動態內容,例如利用 cookie 資料展示的廣告內容或資料(“你好,你的名字”)
動態內容的微程式快取
微程式快取是一種快取技術,將內容快取1秒左右很短的時間。這意味著網站更新會延遲不到1秒鐘,這在很多情況下是可以接受的。
這種短暫快取能給網站效能帶來可察覺的改觀嗎?來試試看!
測試應用程式
在本次測試中,筆者用的是標準 WordPress 設定,並填充了一些樣本內容。
顯然,即便是處理基本內容,WordPress 伺服器也存在效能問題:以 ab 為基準時,它一秒鐘只能服務5.53個請求:
root@nginx-client:~## ab -c 10 -t 30 -k http://nginx-server/
Requests per second: 5.53 [#/sec] (mean)
Time per request: 1809.260 [ms] (mean)
Time per request: 180.926 [ms] (mean, across all concurrent requests)
Transfer rate: 319.74 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 3
Processing: 1430 1735 259.4 1580 2228
Waiting: 537 683 119.7 624 980
Total: 1430 1735 259.4 1580 2228
測試中,vmstat 顯示造成瓶頸的原因是利用 PHP 生成頁面的 CPU 消耗(在 cpu 範圍的 us 一列,數值為96到98。)
root@nginx-server:/var/www/html## vmstat 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
10 0 0 136076 44944 585920 0 0 0 0 476 1665 96 4 0 0 0
10 0 0 140112 44952 585924 0 0 0 4 506 1773 98 2 0 0 0
10 0 0 136208 44952 585924 0 0 0 0 576 2057 97 3 0 0 0
熱門使用量顯示,CPU 被10個執行 PHP 直譯器的 Apache httpd 程式佔用。
這種設定本身就是問題——它限制了網站每秒鐘處理請求的數量不能超過5個,很容易遭到 DOS攻擊,而通過新增 CPU 來解決這個問題意味著每年的託管費用都要增加1000美元。
利用 NGINX 簡化微程式快取
利用 NGINX 來加速服務只需兩步。
第一步: 通過 NGINX 代理伺服器
在 WordPress 伺服器安裝 NGINX 或 NGINX Plus 並進行配置,讓它接收訪問流量並在內部轉發到 WordPress 伺服器:
NGINX 代理伺服器配置比較簡單:
server {
listen external-ip:80; # External IP address
location / {
proxy_http_version 1.1; # Always upgrade to HTTP/1.1
proxy_set_header Connection ""; # Enable keepalives
proxy_set_header Accept-Encoding ""; # Optimize encoding
proxy_pass http://wordpress-upstreams;
}
status_zone wordpress; # NGINX Plus status monitoring
}
upstream wordpress-upstreams {
zone wordpress 128k;
keepalive 20; # Keepalive pool to upstream
server localhost:80;
}
筆者還修改了 Apache 配置(監聽埠號和虛擬伺服器),這樣 Apache 就繫結到了 localhost:80。
你可能以為新增額外的代理伺服器會對效能造成負面影響,但是實際上效能變化可以忽略不計:
root@nginx-client:~# ab -c 10 -t 30 -k http://nginx-server/
Requests per second: 5.63 [#/sec] (mean)
Time per request: 1774.708 [ms] (mean)
Time per request: 177.471 [ms] (mean, across all concurrent requests)
Transfer rate: 324.44 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.2 0 1
Processing: 1423 1709 341.3 1532 2794
Waiting: 554 703 165.0 608 1165
Total: 1423 1709 341.4 1532 2794
在更繁忙的伺服器(處理更多併發請求)中,僅靠 NGINX 實現的優化就能帶來顯著的效能提升。
第二步: 啟動短期快取
在伺服器配置中只新增了兩條指令,NGINX 或 NGINX Plus 就可以快取所有可快取的響應。帶有 200 OK 狀態碼的響應只快取1秒鐘。
proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;
server {
proxy_cache cache;
proxy_cache_valid 200 1s;
...
}
筆者再次執行基準測試時,看到了效能顯著提升:
root@nginx-client:~# ab -c 10 -t 30 -k http://nginx-server/
Complete requests: 18022
Requests per second: 600.73 [#/sec] (mean)
Time per request: 16.646 [ms] (mean)
Time per request: 1.665 [ms] (mean, across all concurrent requests)
Transfer rate: 33374.96 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.5 1 10
Processing: 0 16 141.5 3 2119
Waiting: 0 6 54.6 1 818
Total: 1 17 141.5 4 2121
這是120倍的效能優化,從每秒鐘處理5條請求到600條;這聽起來太棒了,不過還有個問題。
快取進展順利,筆者驗證了內容的確是每秒更新的(因此永不過時),但是未曾預料到的情況發生了。你會發現處理時間的標準偏差很大(141.5毫秒)。CPU 使用率還是100%(用 vmstat 測量),熱門使用量顯示有10個活躍的 httpd 程式。
筆者還從 NGINX Plus 的活動檢測控制皮膚找到進一步的線索。測試前:
測試後:
控制皮膚報告顯示,NGINX 在測試期間處理了18032條請求(ab 彙報的18022條請求,以及基準在30秒結束時突出的10條請求)。但是,NGINX 轉發了150條請求到上游伺服器,在快取內容1秒鐘的情況下,這比我們期望的30秒測試應有的請求數多得多。
怎麼回事?為什麼 CPU 使用率很高,快取更新比預期數字更大?
這是因為每次快取條目過期時,NGINX 就會停止使用它。NGINX 將所有請求都轉發給上游 WordPress 伺服器,直到它收到響應,可以用新內容來快取。
這導致了 WordPress 伺服器收到的請求經常激增到10條。這些請求會佔用 CPU,比快取響應的請求延遲更多,這就解釋了測試結果中的高標準差。
用 NGINX 優化微程式快取
筆者想要的策略很清晰:需要在確保快取內容最新的情況下,儘可能少地向上遊源伺服器轉發請求。在快取內容不斷更新的前提下,筆者願意從快取獲取舊的(延後1到2秒)響應。要實現這一目標,需要新增兩條指令:
- proxy_cache_lock ——限制填充快取的併發嘗試數量,這樣當一條快取入口被建立後,對該資源的請求將會在 NGINX 中排隊。
- proxy_cache_use_stale ——配置 NGINX,使它提供舊的(最近快取的)內容,同時更新快取入口。
加上之前已經新增的快取指令,筆者得到如下伺服器配置:
server {
proxy_cache one;
proxy_cache_lock on;
proxy_cache_valid 200 1s;
proxy_cache_use_stale updating;
...
}
基準測試結果的變化十分驚人。每秒鐘的請求數量從600跳躍到接近2200:
root@nginx-client:~# ab -c 10 -t 30 -n 100000 -k http://nginx-server/
Concurrency Level: 10
Time taken for tests: 30.001 seconds
Complete requests: 65553
Failed requests: 0
Keep-Alive requests: 0
Total transferred: 3728905623 bytes
HTML transferred: 3712974057 bytes
Requests per second: 2185.03 [#/sec] (mean)
Time per request: 4.577 [ms] (mean)
Time per request: 0.458 [ms] (mean, across all concurrent requests)
Transfer rate: 121379.72 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.3 1 5
Processing: 1 4 8.1 3 661
Waiting: 0 1 2.6 1 250
Total: 1 5 8.1 4 661
CPU 使用率也低多了(注意 cpu 下面 id 一欄的空閒時間):
root@nginx-server:/var/www/html# vmstat 3
procs -----------memory---------- ---swap-- -----io---- -system--- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 106512 53192 641116 0 0 0 37 11016 3727 19 45 36 0 0
1 0 0 105832 53192 641808 0 0 0 68 17116 3521 13 56 31 0 0
1 0 0 104624 53192 643132 0 0 0 64 14120 4487 15 51 33 0 0
資料傳輸率(121379.72千位元組/秒,或121兆位元組每秒)相當於0.97千兆,因此該測試受網路限制。CPU 平均使用率為66%,該伺服器的峰值效能應該大概為2185/0.66 = 3300 個請求/秒。
另外,關注 ab 報告的連續響應時間(標準偏差只有8.1毫秒),以及操作皮膚顯示的30秒測試中轉發給上游伺服器的請求數量很少(16):
為什麼只有16條請求?我們知道快取到1秒鐘時會清零,這個更新過程最多需要0.661秒(從 ab 結果來看),因此可以推測,更新頻率不會快於每1.66秒一次。在30秒鐘的時間之外,只會收到最多18(30/1.66)條請求。
瞭解更多
本文簡單展示了在短時間內快取動態內容可能帶來的好處,以及 NGINX Plus 的活動監測資料在調整和診斷快取配置時的用處。如果你想在生產環境中使用微程式快取,筆者建議你建立並測試一個更為複雜的快取規則,針對更長時間內的微程式快取動態和靜態內容。
NGINX Plus 還有一項快取清除功能,可以用來迅速清除 NGINX 快取中的特定內容。如果你想快取更長時間的內容,可以將該功能編入程式,但是一旦你更改原始內容,就要立即更新該程式。
要想了解更多資訊,請查閱以下資源:
- 利用 NGINX 快取指南——概述和方法介紹
- 內容快取——NGINX Plus 嚮導
- 利用 NGINX Plus 進行內容快取— NGINX Plus 功能描述
本文系 OneAPM 工程師編譯呈現。OneAPM Browser Insight 是一個基於真實使用者的 Web 前端效能監控平臺,能夠幫大家定位網站效能瓶頸,網站加速效果視覺化;支援瀏覽器、微信、App 瀏覽 HTML 和 HTML5 頁面。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
本文轉自 OneAPM 官方部落格
原文地址: https://www.nginx.com/blog/benefits-of-microcaching-nginx/
相關文章
- nginx快取使用詳解,nginx快取使用及配置步驟Nginx快取
- 使用代理進行SEO的好處有什麼?
- Nginx 快取使用指南-簡單Nginx快取
- Nginx 代理快取Nginx快取
- 使用Redis和Java進行資料庫快取RedisJava資料庫快取
- 使用看板進行任務管理有哪些好處?
- 微信、企微小程式使用taro對位置許可權進行處理
- 使用MFT進行加密檔案傳輸的7個好處加密
- 使用 NGINX 和 NGINX Plus 實現智慧高效的位元組範圍快取Nginx快取
- 程式設計中快取的使用程式設計快取
- 使用nginx快取伺服器上的靜態檔案Nginx快取伺服器
- 微信小程式使用JSEncrypt進行RSA加密微信小程式JS加密
- nginx反向代理快取教程。Nginx快取
- Nginx瀏覽器快取Nginx瀏覽器快取
- Nginx快取設定教程Nginx快取
- 使用nginx進行負載均衡Nginx負載
- springboot整合redis2.x,使用spring註解進行快取Spring BootRedis快取
- 好程式設計師Java培訓分享Redis快取使用場景概述程式設計師JavaRedis快取
- Nginx 是如何讓你的快取延期的Nginx快取
- 深入Nginx + PHP 快取詳解NginxPHP快取
- Nginx快取伺服器配置Nginx快取伺服器
- Nginx快取原理及機制Nginx快取
- 009.Nginx快取及配置Nginx快取
- Nginx配置瀏覽器快取Nginx瀏覽器快取
- 使用Redis和Java進行資料庫快取 - DZone資料庫RedisJava資料庫快取
- Laravel ORM 對 Model::find 方法進行快取LaravelORM快取
- 使用go mod結合docker分層快取進行自動CI/CDGoDocker快取
- Nginx越界讀取快取漏洞 CVE-2017-7529Nginx快取
- 使用 prefetchComponents 進行元件預取元件
- SpringBoot整合Canal進行資料庫 快取同步Spring Boot資料庫快取
- service worker 對靜態資源進行快取快取
- 由Nginx的DNS快取導致的訪問404NginxDNS快取
- 開發微信小程式分銷商城的好處有哪些?微信小程式
- 【譯】Google - 使用 webpack 進行 web 效能優化(二):利用好持久化快取GoWeb優化持久化快取
- 如何使用Nginx對Artifactory進行http應用NginxHTTP
- Mybatis的二級快取、使用Redis做二級快取MyBatis快取Redis
- 簡訊跳轉微信小程式有哪些好處?微信小程式
- jetcache快取使用快取
- SpringBoot使用快取Spring Boot快取