Nginx反向代理缓存架构设计

朋友站点是CMS门户类网站经常需要被各种爬虫蹂躏,服务器亚历山大。现使用Nginx缓存降低服务器压力。

首先http段增加

proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2 keys_zone=cache_item:10m max_size=5g inactive=1d;
proxy_cache_path 指定硬盘缓存路径
levels 缓存目录最高级别,每层1-2个字符表示。如1:1:2三层
key_cache_zone 缓存名称及内存块大小,如cache_item:10m表示声明一个名称为cache_item大小为10m.超出大小后最早的数据被清楚
max_size 缓存区硬盘的最大值。超出闲置数据将被清除
inactive 最长闲置时间,如1d,如果一个数据1天没被请求,则将清除

然后在

    location /  {
            include vhost/proxy.cnf;
            proxy_pass http://backend;
            location ~ ^/(news/articles)/ {
                    add_header x-cache-hit $upstream_cache_status;      #获取是否被缓存命中
                    proxy_cache cache_item;                                             #缓存的区块
                    proxy_cache_key $host$uri$is_args$args;                  #缓存的key已url全路径保存
                    proxy_cache_valid 200 304 12h;                                 #设置状态码为200,304的为12小时
                    proxy_cache_valid   any 10m;                                     #其他设置为10分钟
                    proxy_ignore_headers Cache-Control;                       #注意这里如果没有忽略缓存头部,则可能一直不能命中,而且不会生成缓存目录
                    #expires 12h;                                                              #设置浏览器缓存时间
                    proxy_pass http://backend;
            }

    }

上线之后发现同样是一个URL,本来PC端访问显示的是PC端,移动端显示的就是移动端的样式。但是因为URL是一样的所以移动端和PC端都乱了,PC端部分显示的是移动端,移动端显示的是PC端,咋办呢?
我们可不可以针对移动端加个标识?

    location / {
            include vhost/proxy.cnf;
            proxy_pass http://backend;
            location ~ ^/(news/articles) {
                    if ($http_user_agent ~* "mobile|android|iphone|ios|iOS"){
                            set $device '/m';        #判断是否移动端加一个标记
                    }
                    add_header x-cache-hit $upstream_cache_status;
                    proxy_cache cache_item;
                    proxy_cache_key $host$device$uri$is_args$args;    #注意缓存的key在$host后面加了个$device
                    proxy_cache_valid 200 304 12h;
                    proxy_cache_valid 404 5m;
                    proxy_cache_valid   any 10m;
                    proxy_ignore_headers Cache-Control;
                    #expires 12h;
                    proxy_pass http://backend;
            }
    }

如何清除nginx缓存呢?
这个需要用到nginx的第三方模块ngx_cache_purge(http://labs.frickle.com/nginx_ngx_cache_purge/)

编译nginx的时候

./configure --user=nobody --group=nobody --prefix=/opt/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-openssl=…/openssl-1.1.0k --add-module=…/ngx_cache_purge-2.3
这里是把最新版本的openssl也自动安装进来了,同时外挂ngx_cache_purge模块

    location / {
            include vhost/proxy.cnf;
            proxy_pass http://backend;
            location ~ ^/(news/articles) {
                    if ($http_user_agent ~* "mobile|android|iphone|ios|iOS"){
                            set $device '/m';
                    }
                    add_header x-cache-hit $upstream_cache_status;
                    proxy_cache cache_item;
                    proxy_cache_key $host$device$uri$is_args$args;
                    proxy_cache_valid 200 304 12h;
                    proxy_cache_valid 404 5m;
                    proxy_cache_valid   any 10m;
                    proxy_ignore_headers Cache-Control;
                    #expires 12h;
                    proxy_pass http://backend;
            }
            location ~ ^/purge(/.*) {
                    include trust.conf;
                    proxy_cache_purge cache_item $host$1$is_args$args;
            }

    }

trust.conf文件内容:

    satisfy any;
    allow 127.0.0.1;     #只有127.0.0.1访问不需要密码,其余IP访问均需要密码
    deny all;
    auth_basic "JIA Login";
    auth_basic_user_file passwd;

事例:

清除以下URL的缓存:
http://www.abc.com/news/2019/009.html
如果是PC端: http://www.abc.com/purge/news/2019/009.html
如果是移动端: http://www.abc.com/purge/m/news/2019/009.html

这也是为何我会按照上面来设计缓存的key。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1baDo5tL-1587092326888)(https://s1.51cto.com/images/blog/201907/24/fc0904dd799ad50ae22040e34b47219b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)]
系统上线后如何了解缓存命中率呢?
1.在日志中增加$upstream_cache_status变量

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" $request_time $upstream_cache_status ';

    access_log  logs/access.log  main;

$upstream_cache_status变量有5个值:

MISS 未命中,请求被传送到后台处理
HIT 命中缓存
EXPIRED 缓存已经过期,请求被传送到后台处理
UPDATING 正在更新缓存,将使用旧的应答
STALE 后端得到过期的应答
根据在日志中的记录我们计算命中率

awk ‘{if($NF=="“HIT”") hit++} END {printf “%.2f%”,hit/NR}’ access.log
假如需要记录每天的命中率:

#!/bin/bash
LOG_FILE=’/usr/local/nginx/logs/access.log.1’
LAST_DAY=KaTeX parse error: Expected '}', got 'EOF' at end of input: …day") awk '{if(NF=="“HIT”") hit++} END {printf “’$LAST_DAY’: %d %d %.2f%n”, hit,NR,hit/NR}’ $LOG_FILE
然后在每天的0点1分计算上一天的

crontab -l

1 0 * * * /opt/shell/get_ngx_hit.sh >> /usr/local/nginx/logs/hit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值