毎回、いまいちなクエリーでDBに問い合わせが発生するページがありまして、googleさんとかのBotでいっぱいいっぱいになることがあります。
かといって、古の遺産なのでいまさらリファクタリングツラい。工数かかる。
じゃあnginxでキャッシュすれば良くね?って思ったんだけど更新内容はなるはやで見せたいって要件もあってまたツラい。
- 人に対しては最新のページ
- Botさんに対しては数日前のキャッシュ
みたいなことができないかなー、と思ったので検証してみます。
検証環境
win10 Homeです。
Docker Toolbox入れます。
https://github.com/docker/toolbox/releases
一緒にdocker-composeも入れてます。
インストールして起動しました。
ひとまずデフォルトなnginxを動かします。
version: '3'
services:
nginx:
image: nginx
ports:
- "8080:80"
volumes:
- ./content:/usr/share/nginx/html/content
- ./conf.d:/etc/nginx/conf.d
- ./cache:/usr/share/nginx/cache
<html>
<body>
Hello, 俺
</body>
</html>
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
$ docker pull nginx:latest
$ docker-compose up -d
$ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------
dockers_nginx_1 nginx -g daemon off; Up 0.0.0.0:8080->80/tcp
$ docker-machine ip
192.168.99.100
で、192.168.99.100を開くとdefaultのやつが表示される。
ただ、192.168.99.100/content/ は403になって、なんか表示されなかったので、
コンテナ入ってindex.htmlを作り直してみた。ファイルのpermissionとかかな。
$ docker-compose.exe exec nginx bash
そしたら表示された。なんか文字化けしてるけどここでは気にしない。
キャッシュの設定
そんなわけでまずはキャッシュの設定。
proxy_cache_path /usr/share/nginx/cache keys_zone=zone1:1m levels=1:2;
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /content {
proxy_cache zone1;
proxy_cache_valid any 60m;
proxy_pass http://localhost:81;
break;
}
}
server {
listen 81;
server_name _;
root /usr/share/nginx/html;
index index.html;
access_log /var/log/nginx/access81.log;
error_log /var/log/nginx/error81.log;
}
これを保存して、docker-compose restart
を実行。
proxy_cacheはproxyで使うみたいなので別ポート立てつつ、同じコンテンツを見てます。
192.168.99.100/content/ を開くと、./cache/
にファイルができてる。
$ curl http://192.168.99.100:8080/content/ <html>
<body>
Hello,俺
</body>
</html>
$ du -l ./cache
4 ./cache/0/81
4 ./cache/0
4 ./cache/e/7a
4 ./cache/e
8 ./cache
ここまでは普通
Botと人で処理を分ける
これでどうだろうか。
proxy_cache_path /usr/share/nginx/cache keys_zone=zone1:1m levels=1:2;
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
set $nocache 1;
if ( $http_user_agent ~* (bot|crawler) ) {
set $nocache 0;
}
location /content {
proxy_no_cache $nocache;
proxy_cache_bypass $nocache;
proxy_cache zone1;
proxy_cache_valid any 60m;
proxy_pass http://localhost:81;
break;
}
}
server {
listen 81;
server_name _;
root /usr/share/nginx/html;
index index.html;
access_log /var/log/nginx/access81.log;
error_log /var/log/nginx/error81.log;
}
htmlを更新しておきます。
$ sed -i 's/Hello/Bye/' content/index.html
$ cat content/index.html
<html>
<body>
Bye, 俺
</body>
</html>
そしてDocker-compose restartして再確認
$ curl http://192.168.99.100:8080/content/
<html>
<body>
Bye,俺
</body>
</html>
キャッシュじゃないのが返ってきた。
でもって、botの場合は・・
$ curl http://192.168.99.100:8080/content/ -H "User-Agent: hogehoge-bo
t (http://hogehoge)"
<html>
<body>
Hello,俺
</body>
</html>
キャッシュが返ってきた!
いけました。
試しにキャッシュ消してみよう。
$ rm -rf ./cache/*
$ curl http://192.168.99.100:8080/content/ -H "User-Agent: hogehoge-bot (http://hogehoge)"
<html>
<body>
Bye,俺
</body>
</html>
当然だけど最新のデータが返ってくる。
いけました!
これ(proxy_no_cache)使えばいけちゃうんですね。
http://www2.matsue-ct.ac.jp/home/kanayama/text/nginx/node65.html