重新思考使用 Nginx 的 map 指令進行快取生成

7 min

language: ja bn en es hi pt ru zh-cn zh-tw

大家好,我是無能。
當我頻繁更新部落格文章時,我不希望它在文章更新時載入舊的快取。
但是,我希望盡可能地從快取中提供內容,所以我想了一下。

停止使用 if 進行快取判斷

在這類文章中介紹的,使用$do_not_cache等方式設定旗標,然後再用if語句修改快取內容的做法,現在似乎已被棄用。
介紹一種架構,即使 Nginx 的 proxy 快取冗餘化,也能讓 WordPress 飛速運行並共通使用 (OpenResty+Redis)

話雖如此,那要在哪裡進行快取判斷呢?

在 map 指令中,Nginx 會判斷變數的內容,並將結果作為值賦予另一個變數。

2022-03-01 嘗試過濾 Nginx 的日誌

在這樣的研究中,我發現了一個非常簡單的語法。
Adding location-block to cache files makes those files return 404

map $uri $expire {
    ~\.(?:j|cs)s$                      180d;
    ~\.(?:jpe?g|png|webp|woff2?|ttf)$  365d;
    default                            off;
}
map $uri $cache_control {
    ~\.(?:js|css|jpe?g|png|webp|woff2?|ttf)$  public;
}
server {
    ...
    expires $expire;
    add_header Pragma $cache_control;
    add_header Cache-Control $cache_control;
    ...
}

原來如此,很清楚。

目標快取

基本上,除了html檔案之外,我希望保持較長的快取時間,而html檔案只需稍微快取即可。
這是因為當遇到 DOS 或洪水攻擊時,我希望Nginx伺服器能夠盡可能地回應。
暫時嘗試以下設定。

map $uri $expire {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ 365d;
    ~\.html$ 5m;
}

map $uri $cache_control {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ public;
    ~\.html$ public;
}

這樣,執行nginx -tservice nginx restart後,再用curl進行測試。

如果請求 URI 中不存在 html,就不會快取...

看來,由於它是以html檔案作為鍵來快取,所以它不會以網域為單位進行快取。

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:20:55 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/index.html
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:21:00 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:26:00 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

當執行curl -I https://soulminingrig.com時,cache-control資訊缺失,這表示它沒有被納入快取判斷中。
實際上它顯示的是index.html,但 Nginx 並未將其識別為判斷條件,所以這次我會這樣嘗試。

map $uri $expire {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ 365d;
    ~\.html$ 5m;
    ~\.*$ 5m;
}

map $uri $cache_control {
    ~\.(jpg|jpeg|png|webp|gif|mp4|css|js|ico|woff2)(\?.*)?$ public;
    ~\.html$ public;
    ~\.*$ public;
}

這樣一來,它就會無條件地使用正規表達式將所有內容快取 5 分鐘。
讓我們再次執行curl -I

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:43 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:49:43 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/top.png
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:47 GMT
content-type: image/png
content-length: 46584
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "b5f8-627935ba12787"
accept-ranges: bytes
expires: Sun, 23 Nov 2025 12:44:47 GMT
cache-control: max-age=31536000
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

alleycat:[haturatu]:~/git$ curl -I https://soulminingrig.com/index.html
HTTP/2 200 
server: nginx/1.27.0
date: Sat, 23 Nov 2024 12:44:51 GMT
content-type: text/html
content-length: 15699
vary: Accept-Encoding
last-modified: Sat, 23 Nov 2024 12:08:31 GMT
etag: "3d53-627935ba8f789"
accept-ranges: bytes
vary: Accept-Encoding
expires: Sat, 23 Nov 2024 12:49:51 GMT
cache-control: max-age=300
content-security-policy: upgrade-insecure-requests
alt-svc: h3=":443"; ma=86400
x-content-type-options: nosniff
pragma: public
cache-control: public

所有內容都成功地被快取了。

透過這種快取方式,設定檔的語法變得相當簡潔,而且當需要更改快取設定時,只需修改map指令即可,這讓操作變得更加方便。
那麼,下次再見了。

Related Posts