最近使用nginx做缓存,发现当大量客户端访问一个没有cache的文件时,回源的流量非常大,在站源上查看日志也看到确实有并发的请求。这个就是需要改成合并回源,当cache内没有数据的时候,只允许1个请求去站源请求数据,写到本地cache。nginx从1.1.12开始原生支持合并回源了。主要有2个配置项(proxy_cache_lock和proxy_cache_lock_timeout控制).

[proxy_cache_lock和proxy_cache_lock_timeout控制](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_lock)   proxy_cache_lock on;
#一次只允许 cache数据被1个请求更新
proxy_cache_lock_timeout 15s;
    # 设置cache lock的时间
```bash
   proxy_cache_use_stale  error timeout invalid_header http_500 http_502 http_503 http_504 http_404; # 设置几种异常情况下任然使用过期的cache数据
需要注意的是对于缓存数据,是根据自己设置的proxy_cache_key进行识别的,别自己把一些非必要的变量设置在了 proxy_cache_key内,导致对应同一个URL都有不同的cache。附上完整配置文件

user                    app root; worker_processes            auto; worker_cpu_affinity         auto; worker_rlimit_nofile        100000; error_log                   “pipe:/opt//install/cronolog/sbin/cronolog /home/app/webserver/logs/cronolog/%Y/%m/%Y-%m-%d-error_log” warn; pid                         /home/app/webserver/logs/nginx.pid;


events {
    use                     epoll;
    worker_connections      20480;
}

http {
    include                 mime.types;
```bash
default_type            application/octet-stream;
root                    /home/app/webserver/htdocs;

    sendfile                on;     tcp_nopush              on;     server_tokens           off;     keepalive_timeout       0;     client_header_timeout   1m;     send_timeout            1m;     client_max_body_size    3m;

log_format              proxyformat    "$remote_addr $request_time_usec $http_x_readtime [$time_local] \"$request_method http://$host$request_uri\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" $upstream_cache_status $upstream_addr $request_time $upstream_response_time";

    log_not_found           off;

gzip                    on;

    gzip_http_version       1.0;     gzip_comp_level         6;     gzip_min_length         1024;     gzip_proxied            any;     gzip_vary               on;     gzip_disable            msie6;     gzip_buffers            96 8k;

gzip_types              text/xml text/plain text/css application/javascript application/x-javascript application/rss+xml;

    beacon                  off;

proxy_cache_path  /home/app/webserver/data/  levels=1:2   keys_zone=yum_zone:100m inactive=100h max_size=100G;

    # only one request at a time will be allowed to populate a new cache element     proxy_cache_lock on;     # lock time 15s     proxy_cache_lock_timeout 15s;

proxy_cache_use_stale  error timeout invalid_header http_500 http_502 http_503 http_504 http_404;

upstream yum_source {

    server 192.12.251.20:80;     keepalive 2; }     server {         listen              80 default_server;         server_name         mirrors.xxx.net;         index  index.html index.htm;         proxy_set_header Connection “”;         proxy_http_version 1.1;         proxy_intercept_errors on;         proxy_set_header Host      $http_host;

location ~* \.(xml|xm_|gz|sh|conf|tar|repo|html|bz2)$ {

            proxy_pass   http://yum_source;             proxy_cache yum_zone;             proxy_cache_min_uses 1;             proxy_cache_methods GET HEAD;

proxy_cache_key $scheme$proxy_host$request_uri$request_method;

            proxy_cache_valid  404      1m;             proxy_cache_valid 200 302 5m;

add_header  Cache-status $upstream_cache_status;

            add_header  Cache-Time  “5m”;

        }         location / {             proxy_pass   http://yum_source;             proxy_cache yum_zone;             proxy_cache_min_uses 1;             proxy_cache_methods GET HEAD;

proxy_cache_key $scheme$proxy_host$request_uri$request_method;

            proxy_cache_valid  404      1m;             proxy_cache_valid 200 302 48h;

add_header  Cache-status $upstream_cache_status;

            add_header  Cache-Time  48h;         }     }

}