1. 程式人生 > >使用靜態快取提升網站效能的五種方法!

使用靜態快取提升網站效能的五種方法!

一、瀏覽器快取

瀏覽器快取,也稱為客戶端快取,是靜態快取中最常見最直接的表現形式,很多時候都往往被人忽略掉。

案例1:

我們經常在nginx的配置檔案中看到以下快取配置:

6d000037ed9f276fc6c

案例2:

在經常寫 jsp 的時候,html 標籤中關於 http 頭資訊也可以注意到“ expires ”的字樣:

6d100037e15c8ded90d

對於案例1和案例2中(nginx設定的expires優先順序大於程式碼中設定的expires優先順序),expires是給一個資源設定一個過期時間,也就是說無需去服務端驗證,直接通過瀏覽器自身確認是否過期即可,所以不會產生額外的流量。此種方法非常適合不經常變動的資源。如果檔案變動較頻繁,就不要使用 expires 來快取。

比如對於常見類web網站來說,css 樣式和 js 指令碼基本已經定型,所以最適合的方法是 expires 來快取一些內容到訪問者瀏覽器。

案例3:

通過 chrome 訪問伺服器端的一張圖片,用F12鍵開啟開發者前端除錯工具:

6d000037eda08b47417

第一次訪問,響應200狀態,當第二次及後續訪問的時候,變成304狀態,客戶端已經開始獲取瀏覽器快取內容,而不需要去伺服器端獲取對應的請求內容,即 nginx 中 expires 引數設定已經生效。等待客戶端快取時間過期後,會再次請求伺服器端內容來更新本地快取。

6d000037edbc442d9b9

介紹到這裡,突然想起一個有意思的需求。比如,訪問一張靜態檔案,不想客戶端快取,需要每次都去伺服器端取資料。我們可以用“ last-modified ”引數來實現,即“ last-modified ”是根據檔案更新時間來確定是否再次傳送載入。

Nginx核心配置如下:

6d000037ed8acbc1f97

我們更改掉伺服器傳回客戶端的“ last-modified ”檔案修改時間引數的值,這樣導致客戶端本地儲存的檔案時間每次跟伺服器端傳回來的時間不一致,所以每次客戶端“ 誤認為 ”伺服器端有靜態檔案更新,每次都會去伺服器端取“ 所謂的最新資料 ”。這樣我們可以看到,不管在瀏覽器訪問多少次,返回的 http 狀態都是200,再也找不到304狀態了。

誤區:在 nginx 中設定 expires,並不是指把靜態內容快取在 nginx 中,而是設定客戶端瀏覽器快取的時間,這是很多人的誤區所在。

二、磁碟快取

除了儲存在客戶端的靜態快取(瀏覽器靜態)技術外,在伺服器端的靜態快取技術主要分為磁碟快取和記憶體快取兩大類。單純圍繞 nginx 的 squid、varnish 等一類中介軟體,處理靜態資料的效能十分優秀。核心是 nginx 基於 epoll 網路模型,而相比 apache 基於 select 網路模型。所以 apache 的優勢在於密計算型,穩定性好。而 nginx 偏向靜態處理,反向代理,高併發。比如 apache+php 的穩定性比 nginx+php 要好,而效能是明顯 nginx 要優秀許多。

以上僅單純是對磁碟中靜態資料處理的能力,所謂磁碟快取,指另外的一種快取靜態檔案的技術。以 nginx 配置為例:

6d100037e19d4127df6

可以看出 nginx 主要通過 proxy_cache 來實現 web cache,熟悉 nginx 的同學,不難看出,以上配置在 location 這裡,不僅可以實現靜態檔案的快取,還可以實現動態檔案的快取(這裡放在下章節詳細介紹)。我們編寫個 test.html測試檔案,然後並訪問。test.html 原始碼如下:

6d000037edc9ba52346

我們發現伺服器的 cache 目錄裡面,多了兩個快取檔案:

6d100037e1746809432

有意思的,這兩個檔案裡面的內容分別為(通過 less 命令檢視):

6d100037e1ae69f0753

(b0ad5d3e7f099bfff9e4fc6a159d868c)

6d100037e1e193e6dbb

(53edc39ed253e14415a29412cfc01faf)

所以不難看出,nginx 把 html 內容和圖片二進位制全部快取到本地磁碟上了。下次使用者再次來訪問 test.html 的時候,nginx 直接將快取在本地磁碟的檔案返回給使用者。特別是後端如若是部署的 tomcat、iis 等,nginx 強大的靜態快取能力,有效減少了伺服器壓力。

三、記憶體快取

緊接上面描述的磁碟快取,記憶體快取顧名思義,就是把靜態檔案快取在伺服器端的記憶體中。所以這種快取,如若命中快取的話,取記憶體中的快取資料返回比取磁碟中的快取資料返回,效能要高很多。以 varnish 為例,varnish 核心配置如下:

啟動命令:

6d100037e18e22f534b

引數簡介:

6d000037ee413494231

default.vcl核心配置如下:

6d000037ee6dd062ae8

Varnish對.gif、.jpg、.jpeg、.png等結尾的 URL 快取時間設定1小時。varnish設定完畢後,我們用命令列方式,通過檢視網頁頭來檢視命中情況:

6d000037ee881153360

6d100037e203342923b

最後,我們可以通過 varnishadm 命令來清理快取,也可以通過 varnishstat 命令來檢視 varnish 系統快取狀態。

四、Nginx 的記憶體快取

以上主要以 Varnish 為例,介紹了記憶體快取靜態資源的方法。其實 nginx 也有記憶體快取,相比 squid、varnish 而言,nginx 的記憶體快取需要通過編碼實現。如下配置:

6d000037ee7f70a3812

memcached_pass 指定伺服器地址,使用變數 $memcache_key 為 key 查詢值,去 memcache 查詢對應 value 值。

如我們訪問:http://***.***.***.***/image/test.jpg ,則 nginx 去 memcache 中查詢key 為“ test.jpg ”的 value 值並返回。如果沒有相應的值,則返回 error_page 404。介紹到這裡,關鍵在於儲存在 memcache 中的靜態檔案,需要通過程式碼寫入 memcache 中。怎麼樣通過 php/java 等程式碼把靜態資源的資料寫入 memcache 中,關於這塊的示例就不再過多介紹了。

Nginx的記憶體快取因為需要通過編碼實現,所以靈活性特別高。這塊可以結合自身業務系統的特點,讓靜態快取的靈活性和效率都能得到保障。可能唯一的缺陷就是,通過編碼實現的方式,給我們維護管理帶來了負擔。在之前我曾參與的一個電商系統,就是把客戶的訂單照片通過 php 程式碼寫入 memcache,客戶訪問取圖的時候,從 memcache 中獲取,速度效率特別高。Nginx 作為一款在七層無所不能且輕量級高效能的中介軟體,能夠直接去 memcache 中取資料,來實現靜態快取的效果,這塊相應的功能是其他軟體無法相媲美的。

五、CDN

說起 CDN,大家都不陌生,它是靜態快取加速最典型的代表。CDN技術並不是一門新的技術,它是基於傳統 nginx、squid、varnish 等 web 快取技術,結合 DNS 智慧解析的靜態快取加速技術。值得注意的是,他對動態連結訪問並沒有加速效果。架構原理圖如下:

6d100037e2349afb0db

所以CDN的靜態快取技術核心主要在於兩點:

節點快取:對需要加速的網站應用,相應的靜態資源通過記憶體快取+磁碟快取的方式快取在伺服器端。

精準排程:對訪問的使用者 ip 進行智慧解析排程,實現就近快取節點訪問。比如以上圖例中,北京使用者訪問 www.a.com。通過 dns 解析的時候,分析使用者 ip,發現是北京使用者。則 dns 返回對應北京快取節點的 ip 地址給到使用者,則使用者 www.a.com 預設訪問北京伺服器上面的快取資料,實現就近訪問的策略,大大提升了訪問速度。