Nginx Pugre返回404

之前一直都是认为purge返回404的原因就是因为所请求的资源并没有被cache,今天在测试过程中无意发现这点认识有错误。

基础环境

  • 确保编译Nginx的时候添加了proxy_cache和purge模块
  • 测试域名: www.cdnhub.org
  • 测试URL: http://www.cdnhub.org/1.txt
  • 资源路径: echo "firefoxbug" > /var/www/cdnhub/1.txt
  • Cache文件安装域名存放,在/home/cache下面
  • 具体查看Nginx配置文件

proxy_temp_path   /home/temp;
proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:200m inactive=10m max_size=10g;

server {
    listen 80;
    server_name www.cdnhub.org cdnhub.org;


    ## Cache For Total
    location / {
        proxy_cache cache_one;
        proxy_cache_valid  200 304 360d; #Cache for 360 days
        proxy_cache_key $host$uri$is_args$args;
        proxy_redirect off;
        proxy_set_header Host   $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Accept-Encoding "";

    ## Ignore Head
        proxy_ignore_headers Cache-Control;
        proxy_hide_header Cache-Control;
        proxy_ignore_headers Expires;
        proxy_hide_header Expires;
        add_header  OpenCDN-Cache "$upstream_cache_status";
        expires 360d;
        proxy_pass http://cdnhub;
    }

    ## Cche For Common Static Files
    location ~ .*\.(ico|jpg|jpeg|bmp|gif|png|js|css|txt)$ {
        proxy_cache cache_one;
        proxy_cache_valid 200 304 360d; #Cache for 360 Days
        proxy_cache_key $host$uri$is_args$args;
        proxy_set_header Host $host;
        add_header  OpenCDN-Cache "$upstream_cache_status";
        expires 360d;
        proxy_pass http://cdnhub;
    }
    
    ##  Purge Cache
    location ~ /purge(/.*) {
        allow all;
        proxy_cache_purge cache_one $host$1$is_args$args;
        error_page 405 =200 /purge$1;
    }
}

模拟请求

请求前

没有任何cache的信息

$ ll www.cdnhub.org/
total 0

发出请求

第一次请求,资源并没有cache,所以OpenCDN-Cache标志位是'MISS'

$ curl --head  http://www.cdnhub.org/1.txt
HTTP/1.1 200 OK
Server: Tengine
Date: Mon, 09 Jun 2014 04:44:46 GMT
Content-Type: text/plain
Content-Length: 11
Connection: keep-alive
Last-Modified: Mon, 09 Jun 2014 04:32:58 GMT
Accept-Ranges: bytes
Expires: Thu, 04 Jun 2015 04:44:46 GMT
Cache-Control: max-age=31104000
OpenCDN-Cache: MISS

请求后

在第一次请求之后,Nginx已经把资源cache住了。

$ cat www.cdnhub.org/5/0c/b1633bf54791f0a1a276e9c824a980c5
...
KEY: www.cdnhub.org/1.txt
HTTP/1.1 200 OK
Server: Tengine
Date: Mon, 09 Jun 2014 04:44:46 GMT
Content-Type: text/plain
Content-Length: 11
Last-Modified: Mon, 09 Jun 2014 04:32:58 GMT
Connection: close
Accept-Ranges: bytes

firefoxbug

再次请求

因为资源已经被cache住了,所以OpenCDN-Cache标志'HIT',代表资源从cache中返回。

$ curl --head  http://www.cdnhub.org/1.txt
HTTP/1.1 200 OK
Server: Tengine
Date: Mon, 09 Jun 2014 05:29:03 GMT
Content-Type: text/plain
Content-Length: 11
Connection: keep-alive
Last-Modified: Mon, 09 Jun 2014 04:32:58 GMT
Expires: Thu, 04 Jun 2015 05:29:03 GMT
Cache-Control: max-age=31104000
OpenCDN-Cache: HIT
Accept-Ranges: bytes

purge

发出purge请求,结果返回404,但是由上面可以知道内容已经被cache住了。

$ curl http://www.cdnhub.org/purge/1.txt
HTTP/1.1 404 Not Found
Server: Tengine
Date: Mon, 09 Jun 2014 05:26:36 GMT
Content-Type: text/html
Content-Length: 580
Connection: keep-alive

查看日志,也可以发现资源都是被cache中的,

问题解决

问题还是出现在Nginx配置Pugre模块上,必须要把Purge的配置内容加到配置静态内容cache之前。

    ...
    ##  Purge Cache
    location ~ /purge(/.*) {
        allow all;
        proxy_cache_purge cache_one $host$1$is_args$args;
        error_page 405 =200 /purge$1;
    }
    
     ## Cche For Common Static Files
    location ~ .*\.(ico|jpg|jpeg|bmp|gif|png|js|css|txt)$ {
        proxy_cache cache_one;
        proxy_cache_valid 200 304 360d; #Cache for 360 Days
        proxy_cache_key $host$uri$is_args$args;
        proxy_set_header Host $host;
        add_header  OpenCDN-Cache "$upstream_cache_status";
        expires 360d;
        proxy_pass http://cdnhub;
    }
    ...

再次Purge

$ curl --head  http://www.cdnhub.org/purge/1.txt
HTTP/1.1 200 OK
Server: Tengine
Date: Mon, 09 Jun 2014 05:32:54 GMT
Content-Type: text/html
Content-Length: 284
Connection: keep-alive

问题原因

还是因为location匹配优先级的问题,回顾下Nginx location匹配优先级(从上到下递减),而且同一层级的根据配置先后顺序

location =
location 完整路径
location ^~ 路径
location ~* 正则
location 相对路径

在 http://www.cdnhub.org/purge/1.txt 首先匹配到的是location (*.txt),所以Nginx会把这个request当做资源做,结果在cache和磁盘上并未找到(可以查看cache日志和源站日志,都存在这个url 404的记录),后面的purge就匹配不到了。

标签:none

评论已关闭