使用Nginx作為緩存伺服器(Cache Server)
緩存伺服器 (Cache Server)
緩存伺服器是用來減輕server loading/traffic的, 怎麼說呢?因為他會將使用者對server的請求結果, 緩存在自己身上; 這樣一來我們的server就不需要對於同樣的請求一直回覆, 因為緩存伺服器會代替我們回覆!
架構解說
第一次請求: 因為CacheServer上面沒資料, 所以回源獲取資料
User --> Cache Server --> Origin Server
User <-- Cache Server <-- Origin Server
第二次請求: CacheServer上面已經有緩存了, 直接代理回應
User --> Cache Server Origin Server
User <-- Cache Server Origin Server
實際配置
環境介紹
這次的lab我們會用兩台ubuntu來示範, 兩台都會安裝nginx
proxy.demosite.com: 緩存伺服器的域名
origin.demosite.com: 源站的域名
緩存伺服器配置
首先編輯/etc/nginx/conf.d/cache.conf
, 這是全域的快取配置, 內容如下
proxy_cache_path /tmp/nginx/cache levels=1:2 keys_zone=myzone:10m inactive=1d max_size=10g;
proxy_cache_key '$scheme$host$request_uri';
接著編輯/etc/nginx/sites-enabled/proxy.conf
起一個新的site, 內容如下
server {
listen 80;
server_name proxy.demosite.com;
location ~ .*\.(html|png)$ {
proxy_cache myzone;
proxy_cache_valid any 100m;
proxy_pass http://origin.demosite.com;
}
location /info {
proxy_cache myzone;
expires -1;
proxy_pass http://origin.demosite.com;
}
add_header X-Cache-Status $upstream_cache_status;
}
配置的緩存路徑資料夾要存在嘿: mkdir -p /tmp/nginx/cache
配置完成就可以重新載入配置文件nginx -s reload
源伺服器配置
源伺服器不需要做其他額外的配置啦~
配置解說
這邊解釋所使用到的基本配置參數, 更完整的內容請參閱Module ngx_http_proxy_module
全域快取配置
先看到上面/etc/nginx/conf.d/cache.conf
這個檔案裡面的內容
proxy_cache_path
: 緩存路徑, 要把緩存的內容放在哪裡
levels=1:2
: 緩存的目錄結構
keys_zone=myzone:10m
: zone的名字和可使用記憶體大小, 配至1MB的zone大約可以存8000筆鍵值的快取
inactive=1d
: 如果一天之內沒人存取, 就會從自己身上刪除啦
max_size=10g
: 允許在身上存放的硬碟容量
proxy_cache_key '$scheme$host$request_uri$is_args$args';
: 每筆快取儲存的鍵值方式
virtual site配置
這配置就是/etc/nginx/sites-enabled/proxy.conf
proxy_cache myzone;
: 代表要使用剛剛定義的zone
proxy_cache_valid any 100m;
: 對於任何結果緩存100分鐘
expires -1;
: 過期時間 -1, 就是不緩存啦~
add_header X-Cache-Status $upstream_cache_status;
: 增加回應的header, 這樣可以清楚知道有沒有中快取
驗證測試
重新載入nginx之後, 就可以來測試我們的緩存狀況囉~
觀察緩存路徑
先看下我們的緩存路徑, 目前空空如也
root@ubuntu-87:/etc/nginx/conf.d# tree /tmp/nginx/cache/
/tmp/nginx/cache/
0 directories, 0 files
首次請求緩存伺服器
接著對緩存伺服器做一次請求看看
❯ curl -v proxy.demosite.com
* Rebuilt URL to: proxy.demosite.com/
* Trying 192.168.41.87...
* TCP_NODELAY set
* Connected to proxy.demosite.com (192.168.41.87) port 80 (#0)
> GET / HTTP/1.1
> Host: proxy.demosite.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.3 (Ubuntu)
< Date: Mon, 21 Jan 2019 08:57:37 GMT
< Content-Type: text/html
< Content-Length: 334
< Connection: keep-alive
< Last-Modified: Tue, 15 Jan 2019 04:20:55 GMT
< ETag: "5c3d5fa7-14e"
< X-Cache-Status: MISS
< Accept-Ranges: bytes
<
<html>
<body>
this is 41.166
gun.png
<img src="gun.jpg" width="50px" height="50px">
<br>
about/about.png
<img src="about/about.png" width="50px" height="50px">
<br>
info/info.png
<img src="info/info.png" width="50px" height="50px">
<br>
<a href="about">about</a>
<a href="info">info</a>
</body>
</html>
* Connection #0 to host proxy.demosite.com left intact
大家注意看到這時候表頭多了這個X-Cache-Status: MISS
代表
- 我們的緩存配置生效囉
MISS
代表身上沒緩存, 因此回源獲取資料; 反之則為HIT
再次查看緩存路徑
經過請求之後, 我們再次查看緩存路徑. 已經有一筆資料囉!
而這個目錄結構就是我們上面配置的level=1:2
root@ubuntu-87:/etc/nginx/conf.d# tree /tmp/nginx/cache/
/tmp/nginx/cache/
└── 3
└── 51
└── 600a83b12cb107e844ddd14077759513
第二次請求緩存伺服器
第二次存取的時候因為緩存伺服器身上已經有資料了, 所以就得到HIT
囉!
❯ curl -v "proxy.demosite.com" 2>&1 | grep X-Cache-Status
< X-Cache-Status: HIT
緩存解說 proxy_cache_key
這部分對於緩存的正確性以及後續的清理緩存還是比較關鍵的, 因此拉出來解釋一下.
鍵值意義
對於每一筆請求, 我們的緩存伺服器是如何知道自己身上有沒有緩存呢? 沒錯就是看proxy_cache_key
!
還記得上面我們配置proxy_cache_key '$scheme$host$request_uri$is_args$args';
以我們剛剛的請求來說, proxy.demosite.com
, 產生的鍵值就會是 httpproxy.demosite.com/
(http) proxy.demosite.com (/)
$scheme $host $request_uri $is_args$args
我們可以看一下剛才產生的緩存文件, 這個快取文件就是完整的html檔案, 裡面就說明了他的鍵值
KEY: httpproxy.demosite.com/
root@ubuntu-87:/etc/nginx/conf.d# cat /tmp/nginx/cache/3/51/600a83b12cb107e844ddd14077759513
0E\_=\E\G"5c3d5fa7-14e"
KEY: httpproxy.demosite.com/
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Mon, 21 Jan 2019 09:07:12 GMT
Content-Type: text/html
Content-Length: 334
Last-Modified: Tue, 15 Jan 2019 04:20:55 GMT
Connection: close
ETag: "5c3d5fa7-14e"
Accept-Ranges: bytes
<html>
<body>
this is 41.166
gun.png
<img src="gun.jpg" width="50px" height="50px">
<br>
about/about.png
<img src="about/about.png" width="50px" height="50px">
<br>
info/info.png
<img src="info/info.png" width="50px" height="50px">
<br>
<a href="about">about</a>
<a href="info">info</a>
</body>
</html>
所以 只要使用者請求的Key不同, nginx就可以生成不同的快取文件
換句話說, 如果您的網站下面這兩個請求應該得到不同的結果,
- proxy.demosite.com?name=foo
- proxy.demosite.com?name=bar
您對於proxy_cache_key
的定義就必須精細到arg
, 否則nginx會忽略存取參數; 一直以為是同樣的一份文件唷!
而如果您的網站http/https可以不用視為兩份緩存, 那key就可以省略scheme這個變數囉!
鍵值計算
那麼md5怎麼來的呢, 就是使用Key得到的; 我們可以驗證看看
❯ echo -n 'httpproxy.demosite.com/' | md5
600a83b12cb107e844ddd14077759513
清理緩存
所以說, 配置了緩存就要可以清理緩存; 否則有時候網站有更新, 使用者還是會持續看到舊的資料.
方法一: 刪除整個目錄
此方法最為直觀簡易啦~ 整個緩存全部清除, 也不用想太多
rm -rf /tmp/nginx/cache/*
nginx -s reload
優點: 快速簡易
缺點: 無法控制要刪除的項目
這個方法適用於網站單純的情況下, 不需要考慮如果緩存伺服器突然失去所有檔案, 進而突發回源造成大量存取
方法二: 刪除指定目錄/域名
什麼是刪除指定目錄呢? 比如我們今天想刪除 /info 下面所有的緩存
或是比如我們的緩存伺服器同時有兩個網站, 而我只想對單一網站進行緩存清理; 就可以使用這個方法囉!
- 首先我們理解我們的緩存檔案裡面都會存放我們定義的鍵值
- 找出鍵值符合的檔案
- 批量刪除
先看一下; 目前我的緩存共有四筆, 其中的鍵值也都取出來觀察
root@ubuntu-87:/etc/nginx/conf.d# tree /tmp/nginx/cache/
/tmp/nginx/cache/
├── 3
│ ├── 51
│ │ └── 600a83b12cb107e844ddd14077759513
│ └── 9b
│ └── 3ace4f08b744df7310abeb90109e19b3
├── 5
│ └── d8
│ └── 80af67f39abf128943025ab5e1498d85
└── c
└── 19
└── 53e313c4a7c020ab414089c28c4c419c
root@ubuntu-87:/etc/nginx/conf.d# grep -ar "KEY: httpproxy.demosit
e.com/" /tmp/nginx/cache
/tmp/nginx/cache/3/51/600a83b12cb107e844ddd14077759513:KEY: httpproxy.demosite.com/
/tmp/nginx/cache/3/9b/3ace4f08b744df7310abeb90109e19b3:KEY: httpproxy.demosite.com/about/about.png
/tmp/nginx/cache/5/d8/80af67f39abf128943025ab5e1498d85:KEY: httpproxy.demosite.com/info/info.png
/tmp/nginx/cache/c/19/53e313c4a7c020ab414089c28c4c419c:KEY: httpproxy.demosite.com/info/info.html
四筆鍵值記錄分別是
- httpproxy.demosite.com/
- httpproxy.demosite.com/about/about.png
- httpproxy.demosite.com/info/info.png
- httpproxy.demosite.com/info/info.html
實際操作: 清除 /info 下面的所有緩存
grep -alr "KEY: httpproxy.demosite.com/info" /tmp/nginx/cache | xargs rm
這時候再看一下我們的緩存目錄, 該目錄之下的緩存都清除完畢囉!
root@ubuntu-87:/etc/nginx/conf.d# tree /tmp/nginx/cache/
/tmp/nginx/cache/
├── 3
│ ├── 51
│ │ └── 600a83b12cb107e844ddd14077759513
│ └── 9b
│ └── 3ace4f08b744df7310abeb90109e19b3
├── 5
│ └── d8
└── c
└── 19
結語
我們下次見啦~