Nginx 快取機制詳解!非常詳細實用

民工哥發表於2021-09-30

Nginx 快取作為效能優化的一個重要手段,可以極大減輕後端伺服器的負載。下面我們將介紹 Nginx 快取配置的相關指令以及 http 快取機制,以及 Nginx 快取實踐案例分析。

Nginx 快取示例

例項演示,快取是怎麼出現的,怎麼檢視!

當我們代開某個網站,如 baidu.com,我們可以看到 size 這一列有一些 js 標識為 disk cache,這裡就是應用到了快取。

HTTP 快取機制

HTTP 的快取流程如下圖所示

快取,可以分為強制快取和對比快取

Nginx 強制快取

介紹強制快取是什麼?以及可能造成這個原因的配置引數!

瀏覽器不會向伺服器傳送任何請求,直接從本地快取中讀取快取資料並返回 200 狀態碼,如下圖所示。如果快取過期再找伺服器,其過程如下:

可以造成強制快取的欄位,有如下幾個:

Expires

位置: HTTP Response Header

說明: Expires 是服務端返回的到期時間。如果下一次請求如果小於服務端返回的過期時間,則直接使用快取資料。Expires 是 HTTP1.0 的東西,現在瀏覽器預設都是使用 HTTP1.1。而且由於該值是有服務端生成,而客戶端的時間和服務端的時間有可能不一致,導致存在一定誤差。所以 HTTP1.1 使用 Cache-Control 替代。

# 示例
Expires: Mon, 22 Jul 2019 11:08:59 GMT
Cache-Control

位置: HTTP Response Header

說明: 快取策略定義

  • max-age: 標識資源能夠被快取的最大時間
  • public: 表示該響應任何中間人,包括客戶端和代理伺服器都可以快取
  • private: 表示該響應只能用於瀏覽器私有快取中,中間人(代理伺服器)不能快取此響應
  • no-cache: 需要使用對比快取(Last-Modified/If-Modified-Since/Etag/If-None-Match)來驗證快取資料
  • no-store: 所有內容都不會快取,強制快取和對比快取都不會觸發

Nginx 對比快取

介紹使用快取和不使用快取的區別和對比!

瀏覽器在第一次請求資料時,伺服器會將快取的標識與資料一起返回給瀏覽器,瀏覽器將這兩個快取到本地快取資料庫中。

再次請求資料時,就會在請求 header 中帶上快取的標識傳送給伺服器,伺服器根據快取標識對比,如果發生變化,則返回 200 狀態碼,返回完整的響應資料給瀏覽器,如果未發生更新,則返回 304 狀態碼告訴瀏覽器繼續使用快取資料。

如下圖比較所示,在第一次請求時,沒有使用快取。而在第二次使用快取時,可以明顯看到兩者請求的時間不一樣,後者時間少很多。這是因為服務端如果進行快取比較後發現未更新,只返回 header 部分,並返回 304 狀態碼通知客戶端使用本地快取,沒有將報文的 body 部分返回給瀏覽器,所以請求時間和報文大小才明顯優化。別小看這幾十毫秒,當訪問量很大時,這裡就優化了很多時間、減少了很多伺服器壓力。

第一次訪問,未使用快取:

第二次訪問,使用快取:

HTTP 請求和響應報文結構如下圖所示:

會造成對比快取的欄位如下:

  • Last-Modified

    • 位置: HTTP Response Header
    • 說明: 第一次請求時,伺服器會在響應頭裡設定該引數,告訴瀏覽器該資源的最後修改時間。

      # 示例
      Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
  • If-Modified-Since

    • 位置: HTTP Request Header
    • 說明: 再次(注意不是第一次)請求伺服器時,客戶端瀏覽器通過此欄位通知伺服器上次請求時,伺服器返回的資源最後修改時間。伺服器收到請求後,發現 header 中有 If-Modified-Since 欄位,則與被請求資源的最後修改時間進行對比。若資源的最後修改時間大於 If-Modified-Since,則說明資源被修改過,則響應返回完整的內容,返回狀態碼 200。 若資源的最後修改時間小於或等於 If-Modified-Since,則說明資源未修改,則返回 304 狀態碼,告訴瀏覽器繼續使用所儲存的快取資料。
  • Etag
  • 位置: HTTP Response Header

    • 說明: 伺服器響應請求時,告訴瀏覽器當前資源在伺服器的唯一標識(由服務端生成)。
    • 優先順序: 高於 Last-Modified 與 If-Modified-Since

  • If-None-Match

    • 位置: HTTP Request Header
    • 說明: 再次請求伺服器時,通過此欄位通知伺服器客戶端快取的資源的唯一標識。伺服器收到請求 header 周發現有 If-None-Match 欄位,則與被請求資源的唯一標識進行對比。 如果不一樣,說明資源被修改過,則返回完整的響應,狀態碼 200。 如果一樣,說明資源未被修改過,則返回 304 狀態碼,告訴瀏覽器繼續使用快取的資料。

Nginx 快取實踐

實際配置和演示一下,使用快取的效果!

配置檔案的內容,如下所示:

nginx
user  nginx;
pid /run/nginx.pid;
worker_processes  auto;
worker_rlimit_nofile 100000;

events {
    worker_connections  2048;
    multi_accept on;
}

http {
    sendfile on;

    access_log off;
    error_log  /data/log/nginx-1.0/error.log  error;

    proxy_cache_path /data/nginx-1.0/cache levels=1:2 keys_zone=cache_zone:10m inactive=60m;

    server {
        listen 80;
        server_name localhost;
        root /usr/local/services/nginx-1.0/html/;

        location / {

        }

        location ~.*\.(gif|jpg|png|css|js)(.*) {
            proxy_cache cache_zone;
            proxy_cache_valid 200 302 24h;
            expires 1d;
            add_header X-Proxy-Cache $upstream_cache_status;
        }
    }
}

實際的測試情況,如下所示:

[root@VM_16_4_centos conf]# curl -I http://localhost/test.js
HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Sun, 21 Jul 2019 12:35:06 GMT
Content-Type: text/plain
Content-Length: 12
Last-Modified: Sun, 21 Jul 2019 12:33:32 GMT
Connection: keep-alive
ETag: "5d345b9c-c"
Expires: Mon, 22 Jul 2019 12:35:06 GMT
Cache-Control: max-age=86400
Accept-Ranges: bytes

我們再以圖片為例,當我們第一次請求 http://localhost/google_logo.jpg,服務端返回了該資源的唯一標識 Etag 給我們。

我們第二次請求時,可以發現 http 報文的體積和響應實踐大大縮減,說明我們的快取發回了作用。

作者: Escape
連結: escapelife.site/posts/b167e14a.html

相關文章