Nginx 快取概述
Nginx 快取是一種強大的效能優化技術,能夠將後端伺服器的回應暫存於記憶體或磁碟中,減少重複請求對後端的壓力。透過適當的快取策略,可以顯著提升網站的回應速度,降低伺服器負載,並改善整體使用者體驗。
在 Ubuntu 22.04 上設定 Nginx 快取,我們需要了解幾個核心概念:
- 快取區域 (Cache Zone):定義快取儲存的位置和大小
- 快取鍵 (Cache Key):決定如何識別和儲存不同的快取項目
- 快取有效期 (Cache Validity):控制快取內容的存活時間
- 快取繞過 (Cache Bypass):設定何時不使用快取
快取類型
Proxy Cache
Proxy Cache 用於反向代理情境,當 Nginx 作為前端伺服器代理請求到後端應用程式時使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # /etc/nginx/nginx.conf
http {
# 定義快取區域
proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:2
keys_zone=my_proxy_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_server;
proxy_cache my_proxy_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
}
}
}
|
FastCGI Cache
FastCGI Cache 專門用於 PHP-FPM 等 FastCGI 應用程式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # /etc/nginx/nginx.conf
http {
# 定義 FastCGI 快取區域
fastcgi_cache_path /var/cache/nginx/fastcgi_cache
levels=1:2
keys_zone=my_fastcgi_cache:10m
max_size=1g
inactive=60m;
server {
listen 80;
server_name example.com;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_cache my_fastcgi_cache;
fastcgi_cache_valid 200 10m;
include fastcgi_params;
}
}
}
|
設定快取區域
快取區域是 Nginx 快取的基礎設定,需要在 http 區塊中定義:
1
2
3
4
5
6
| proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:2
keys_zone=main_cache:50m
max_size=2g
inactive=120m
use_temp_path=off;
|
proxy_cache_path 參數說明
| 參數 | 說明 |
|---|
/var/cache/nginx/proxy_cache | 快取檔案儲存路徑 |
levels=1:2 | 目錄層級結構,1:2 表示兩層子目錄 |
keys_zone=main_cache:50m | 快取區域名稱與共享記憶體大小 |
max_size=2g | 快取最大磁碟空間 |
inactive=120m | 未被存取的快取項目存活時間 |
use_temp_path=off | 直接寫入快取目錄,避免額外 I/O |
建立快取目錄並設定權限:
1
2
3
| sudo mkdir -p /var/cache/nginx/proxy_cache
sudo chown -R www-data:www-data /var/cache/nginx
sudo chmod -R 755 /var/cache/nginx
|
快取鍵設定
快取鍵決定了如何唯一識別快取項目,預設使用完整的 URL:
1
2
3
4
5
6
7
8
| # 預設快取鍵
proxy_cache_key $scheme$proxy_host$request_uri;
# 自訂快取鍵(包含查詢參數)
proxy_cache_key "$scheme$request_method$host$request_uri";
# 忽略特定查詢參數
proxy_cache_key "$scheme$host$uri$is_args$args";
|
針對不同需求的快取鍵設定範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| server {
listen 80;
server_name example.com;
location /api/ {
proxy_pass http://api_backend;
proxy_cache main_cache;
# API 快取鍵包含請求方法
proxy_cache_key "$request_method$scheme$host$request_uri";
}
location /static/ {
proxy_pass http://static_backend;
proxy_cache main_cache;
# 靜態資源使用簡單快取鍵
proxy_cache_key "$uri";
}
}
|
快取有效期設定
設定不同 HTTP 狀態碼的快取時間:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_cache main_cache;
# 依狀態碼設定快取時間
proxy_cache_valid 200 301 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 5m;
# 使用後端 Cache-Control 標頭
proxy_cache_use_stale error timeout updating
http_500 http_502 http_503 http_504;
# 快取鎖定,避免驚群效應
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
}
}
|
繞過快取條件
某些情況下需要繞過快取,直接從後端取得資料:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| server {
listen 80;
server_name example.com;
# 定義繞過快取的條件
set $skip_cache 0;
# 登入使用者不使用快取
if ($http_cookie ~* "session_id") {
set $skip_cache 1;
}
# POST 請求不使用快取
if ($request_method = POST) {
set $skip_cache 1;
}
# 管理後台不使用快取
if ($request_uri ~* "/admin/") {
set $skip_cache 1;
}
location / {
proxy_pass http://backend;
proxy_cache main_cache;
# 套用繞過條件
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
# 添加快取狀態標頭
add_header X-Cache-Status $upstream_cache_status;
}
}
|
清除快取
方法一:手動刪除快取檔案
1
2
3
4
5
| # 清除所有快取
sudo rm -rf /var/cache/nginx/proxy_cache/*
# 重新載入 Nginx
sudo systemctl reload nginx
|
方法二:使用 proxy_cache_purge 模組
需要編譯 nginx-cache-purge 模組:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_cache main_cache;
}
# 清除快取端點
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge main_cache "$scheme$request_method$host$1";
}
}
|
使用 curl 清除特定 URL 的快取:
1
| curl -X PURGE http://example.com/purge/path/to/resource
|
監控快取狀態
添加快取狀態標頭
1
2
3
4
5
6
7
8
9
10
11
12
13
| server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_cache main_cache;
# 顯示快取狀態
add_header X-Cache-Status $upstream_cache_status always;
add_header X-Cache-Key $scheme$proxy_host$request_uri always;
}
}
|
快取狀態值說明:
| 狀態 | 說明 |
|---|
HIT | 快取命中,直接回傳快取內容 |
MISS | 快取未命中,從後端取得並快取 |
EXPIRED | 快取已過期,從後端重新取得 |
STALE | 快取過期但後端不可用,回傳舊快取 |
UPDATING | 快取正在更新中 |
BYPASS | 快取被繞過 |
完整設定範例
以下是一個完整的 Nginx 快取設定範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
| # /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日誌格式包含快取狀態
log_format cache_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'cache_status=$upstream_cache_status';
access_log /var/log/nginx/access.log cache_log;
# 定義快取區域
proxy_cache_path /var/cache/nginx/proxy_cache
levels=1:2
keys_zone=main_cache:100m
max_size=5g
inactive=24h
use_temp_path=off;
server {
listen 80;
server_name example.com;
# 快取繞過條件
set $skip_cache 0;
if ($request_method = POST) {
set $skip_cache 1;
}
if ($http_cookie ~* "session_id|logged_in") {
set $skip_cache 1;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_cache main_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 301 302 1h;
proxy_cache_valid 404 10m;
proxy_cache_valid any 1m;
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_cache_use_stale error timeout updating
http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status always;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 靜態資源長期快取
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ {
proxy_pass http://127.0.0.1:8080;
proxy_cache main_cache;
proxy_cache_valid 200 7d;
add_header X-Cache-Status $upstream_cache_status always;
add_header Cache-Control "public, max-age=604800";
}
}
}
|
效能調校建議
- 適當設定 keys_zone 大小:每 1MB 約可儲存 8000 個快取鍵
- 使用 use_temp_path=off:減少磁碟 I/O
- 啟用 proxy_cache_lock:避免多個相同請求同時存取後端
- 設定合理的 inactive 時間:平衡記憶體使用與快取效率
- 監控快取命中率:透過日誌分析優化快取策略
參考資料