Nginx是一個免費開源且穩定高效的Web伺服器程式,擁有反向代理以及負載平衡的功能,經常作為最前端的伺服器。當它用作反向代理伺服器或是PHP網頁伺服器時,無論是proxy_pass
還是fastcgi_pass
,均有提供快取的功能。然而,免費版本的Nginx並沒有內建刪除快取的機制(早期Nginx免費版本可以使用proxy_cache_purge
、fastcgi_cache_purge
命令來清除快取,只不過後來這功能要在商業版本上才能使用了),在沒有額外腳本或程式的幫助下,我們大概也只能用rm
等Linux指令來手動刪除快取目錄中的檔案,十分不方便,而且有一定的危險性。
如果您不知道如何在Ubuntu Server架設Nginx伺服器,也不知道怎麼使用proxy_pass
的快取功能的話,可以先參考這篇文章:
如果您是架設PHP網站的話,可以再參考這篇文章來了解fastcgi_pass
的快取功能:
Nginx Cache Purge
「Nginx Cache Purge」是一個高效Nginx快取清除工具,是解決免費版本的Nginx不能使用proxy_cache_purge
和fastcgi_cache_purge
命令的替代方案。
GitHub:
安裝和解除安裝Nginx Cache Purge
透過Cargo
如果系統環境中有安裝「Cargo」的話,可以直接使用以下指令來下載「Nginx Cache Purge」的原始碼專案,並進行編譯安裝。
cargo install nginx-cache-purge
若要解除安裝,執行以下這個指令即可:
cargo uninstall nginx-cache-purge
透過GitHub
(適用於Linux x86_64)
執行以下指令,將最新的Nginx Cache Purge執行檔從GitHub上下載下來,並移動到/usr/local/bin
目錄中。
(curl -s https://api.github.com/repos/magiclen/nginx-cache-purge/releases/latest | sed -r -n 's/.*"browser_download_url": *"(.*\/nginx-cache-purge_'$(uname -m)')".*/\1/p' | wget -i -) && sudo mv nginx-cache-purge_$(uname -m) /usr/local/bin/nginx-cache-purge && sudo chmod +x /usr/local/bin/nginx-cache-purge
若要解除安裝,執行以下這個指令即可:
sudo rm /usr/local/bin/nginx-cache-purge
使用Nginx Cache Purge
命令列介面
Nginx Cache Purge只有提供CLI(命令列介面),指令用法如下:
CACHE_PATH
是使用Nginx的proxy_cache_path
或是fastcgi_cache_path
命令時所設定的快取儲存目錄路徑。LEVELS
是使用Nginx的proxy_cache_path
或是fastcgi_cache_path
命令時所設定的目錄和目錄檔名結構,格式為x[:y[:z]]
。KEY
是使用Nginx的proxy_cache_key
或是fastcgi_cache_key
命令時所設定的快取鍵值。
建議把快取的鍵值以Nginx的$request_uri
為結尾,因為Nginx Cache Purge還有Wildcard清除功能。如果KEY
的結尾字元是星號*
的話,就會去尋找快取目錄中,所有鍵值前綴是KEY
(去除結尾星號)的快取。
Nginx + lua-nginx-module
+ Nginx Cache Purge
lua-nginx-module
是Nginx的Lua腳本程式語言擴充套件,可以在Nginx的設定檔中於content_by_lua_block
命令形成的的區塊內直接撰寫Lua腳本。若是使用Debian或是其衍生的Linux作業系統,可以直接用以下的指令來安裝lua-nginx-module
:
利用Lua提供的os.execute
函數,可以在Nginx設定檔中去執行外部的執行檔,也就可以在指定的location
區塊中,或是location
區塊內的if
區塊中,去執行Nginx Cache Purge。
至於要在哪個location
區塊中或是if
區塊中去執行Nginx Cache Purge,其實也沒有一定的標準,大致上有兩種作法。
HTTP的PURGE
請求方法
在有使用到proxy_cache
或是fastcgi_cache
命令的區塊中,可以去判斷客戶端的請求方法是不是PURGE
。雖然PURGE
請求方法並不在HTTP標準中,但許多人會用它來當作清除快取的請求方法,有點約定俗成的感覺。
若要用這個方式來清除快取,可以在/etc/nginx/conf.d
目錄中,新增purge.conf
檔案,檔案內容如下:
map $request_method $is_purge {
default 0;
PURGE 1;
}
以上的map
命令,可以去判斷客戶端的請求方法是不是PURGE
,如果是的話,$is_purge
變數的值就是1
,否則是0
。
接著就是在location
區塊內使用if
命令判斷$is_purge
變數,並在if
區塊中使用content_by_lua_block
命令執行Lua腳本。假設Nginx Cache Purge的執行檔路徑是/usr/local/bin/nginx-cache-purge
,設定方式如下:
http {
...
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m;
proxy_cache_key $scheme$proxy_host$request_uri;
server {
...
location / {
if ($is_purge) {
set $my_cache_key $scheme$proxy_host$request_uri;
content_by_lua_block {
local exitStatus = os.execute("/usr/local/bin/nginx-cache-purge /path/to/cache 1:2 "..ngx.var.my_cache_key)
if exitStatus == 0 then
ngx.exit(ngx.HTTP_OK)
else
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
}
}
proxy_pass upstream;
include proxy_params;
}
}
}
不過當然,我們還需要加入自己的存取驗證機制,避免隨便一個陌生人都可以連到我們的伺服器上清除快取。
以上的設定若成功,
- 發送
PURGE /path/to/abc
請求,表示要清除GET /path/to/abc
產生的快取。 - 發送
PURGE /path/to/*
請求,表示要清除GET /path/to/**/*
產生的快取,像是GET /path/to/
、GET /path/to/abc
、GET /path/to/123/456
。
專門用來清除快取的location
區塊
如果不想把清除快取的功能和proxy_cache
或是fastcgi_cache
命令放在同一個location
區塊,並使用PURGE
請求方法來切換功能。也是可以另外再建立出location
區塊,專門用來清除快取,不過鍵值中$request_uri
的部份就可能會需要使用Lua額外處理一下。
例如:
http {
...
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m;
proxy_cache_key $scheme$proxy_host$request_uri;
server {
...
location / {
proxy_pass upstream;
include proxy_params;
}
location /purge/ {
set $my_cache_key_part $scheme$proxy_host;
content_by_lua_block {
local exitStatus = os.execute("/usr/local/bin/nginx-cache-purge /path/to/cache 1:2 "..ngx.var.my_cache_key_part..string.sub(ngx.var.request_uri, 7))
if exitStatus == 0 then
ngx.exit(ngx.HTTP_OK)
else
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
}
}
}
}
以上設定中,利用Lua的string.sub
來抓取Nginx的$request_uri
變數的子字串,消除URI前面的/purge
,以對應/
。