一、简介

Nginx版本从0.7.48开始,支持了类似Squid的缓存功能。这个缓存是把URL及相关组合当做Key,用Md5算法对Key进行哈希,得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录内。

Nginx Web 缓存服务只能为指定URL或状态码设置过期时间,不支持类似Squid的PURGE指令手动清除缓存;但是我们可以通过Nginx的模块ngx_cache_purge清除指定URL的缓存。

  • proxy_cache:缓存后端服务器的内容,可能是任何内容,包括静态的和动态,减少了nginx与后端通信的次数,节省了传输时间和后端宽带
  • fastcgi_cache:缓存fastcgi生成的内容,很多情况是php生成的动态的内容,少了nginx与php的通信的次数,更减轻了php和数据库(mysql)的压力,这比用memcached之类的缓存要轻松得多


图片来自网络

二、配置

nginx.conf

1
2
3
4
5
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_temp_path  /tmp/nginx/fcgi/temp;

vhost配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
server {
    server_name example.com www.example.com;
 
    access_log   /var/log/nginx/example.com.access.log;
    error_log    /var/log/nginx/example.com.error.log;
 
    root /var/www/example.com/htdocs;
    index index.php;
 
    set $skip_cache 0;
 
    # POST requests and urls with a query string should always go to PHP
    if ($request_method = POST) {
        set $skip_cache 1;
    }  
    if ($query_string != "") {
        set $skip_cache 1;
    }  
 
    # Don't cache uris containing the following segments
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }  
 
    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }
 
    location / {
        try_files $uri $uri/ /index.php?$args;
    }   
 
    location ~ \.php($|/) {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_split_path_info         ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO         $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
        fastcgi_pass unix:/dev/shm/php-socket;
 
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
 
        fastcgi_cache WORDPRESS;
        include fcgi_cache_params;
 
    }
 
    location ~ /purge(/.*) {
        fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
    }  
 
    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off; log_not_found off; expires max;
    }
 
    location = /robots.txt { access_log off; log_not_found off; }
    location ~ /\. { deny  all; access_log off; log_not_found off; }
}

fcgi_cache_params配置

1
2
3
4
5
6
7
8
9
10
11
12
#include fcgi_cache_params;
#fastcgi_cache_valid 200 302 1s;
### fcgi-cache
fastcgi_cache fcgi;
fastcgi_cache_valid 200 302 1s;
fastcgi_cache_valid 404 500 502 503 504 0s;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500 http_503 updating;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
#add_header X-Cache "$upstream_cache_status - $upstream_response_time";
fastcgi_cache_key "$scheme$request_method$host$request_uri"

大概解释下各个参数的含义:

fastcgi_cache  该指令用于设置哪个缓存区将被使用,zone_name的值为fastcgi_cache_path指令创建的缓存名称

fastcgi_cache_path 作用域:http

1
2
3
4
fastcgi_cache_path path
[levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time]
[max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time]
[purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

该指令用于设置缓存文件的存放路径,示例如下:fastcgi_cache_path /data/nginx/cache levels=1:2  keys_zone=cache_one:100M  inactive=1d  max_size=10g;

a、levels:指定了该缓存空间有两层hash目录,设置缓存目录层数,levels=1:2,表示创建两层目录缓存,最多创建三层。第一层目录名取fastcgi_cache_key md5的最后一个字符,第二层目录名取倒数2-3字符,如:fastcgi_cache_key md5为b7f54b2df7773722d382f4809d65029c,则:

1
2
levels=1:2为/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels=1:2:3为/data/nginx/cache/c/29/650/b7f54b2df7773722d382f4809d65029c

b、keys_zone为这个缓存区起名为zone_name,500m指代缓存空间为500MB;

c、inactive=1d 代表如果缓存文件一天内没有被访问,则删除;

d、max_size=30g代表硬盘缓存最大为30G;

设置缓存多个磁盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fastcgi_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g  inactive=60m use_temp_path=off;
fastcgi_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g  inactive=60m use_temp_path=off;
 
split_clients $request_uri $my_cache {
              50%          "my_cache_hdd1";
              50%          "my_cache_hdd2";
}
 
server {
    ...
    location / {
       fastcgi_cache $my_cache;
        
    }
}

将缓存文件放入内存中

编辑/etc/fstab  或者 放入 /dev/shm

1
2
3
tmpfs /etc/nginx/cache tmpfs defaults,size=100M 0 0
mount -a
df -ah | grep tmpfs 

需要注意的是fastcgi_cache缓存是先写在fastcgi_temp_path再移到fastcgi_cache_path,所以这两个目录最好在同一个分区,从0.8.9之后可以在不同的分区,不过还是建议放同一分区

fastcgi_cache_methods 该指令用于设置缓存哪些HTTP方法,默认缓存HTTP GET/HEAD方法。

fastcgi_cache_min_uses  URL经过多少次请求将被缓存

fastcgi_cache_valid  reply_code [reply_code ... ] time

该指令用于对不同返回状态码的URL设置不同的缓存时间,例如: 

1
2
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 404      1m;

设置202 302状态URL缓存10分钟,404状态的URL缓存1分钟。

注意:如果不指定状态码,直接指定缓存时间,则只有200,301,302状态码会进行缓存。

1
fastcgi_cache_valid 5m;

any 可以指定缓存任何响应码    

1
2
3
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301      1h;
fastcgi_cache_valid any      1m;

缓存的参数也可以在响应头直接设置。这些的优先级高于缓存时间设定使用该指令

  • The “X-Accel-Expires” header field sets caching time of a response in seconds. The zero value disables caching for a response. If the value starts with the @ prefix, it sets an absolute time in seconds since Epoch, up to which the response may be cached.
  • If the header does not include the “X-Accel-Expires” field, parameters of caching may be set in the header fields “Expires” or “Cache-Control”.
  • If the header includes the “Set-Cookie” field, such a response will not be cached.
  • If the header includes the “Vary” field with the special value “*”, such a response will not be cached (1.7.7). If the header includes the “Vary” field with another value, such a response will be cached taking into account the corresponding request header fields (1.7.7).

fastcgi_cache_key

该指令用来设置Web缓存的Key值,Nginx根据Key值MD5缓存。一般根据host(域名),host(域名),request_uri(请求的路径)等变量组合成fastcgi_cache_key。

例如:fastcgi_cache_key "schemeschemerequest_methodhosthostrequest_uri";

定义fastcgi_cache的key,示例中就以请求的URI作为缓存的key,Nginx会取这个key的md5作为缓存文件,如果设置了缓存哈希目录,Nginx会从后往前取相应的位数做为目录。

注意一定要加上$request_method作为cache key,否则如果HEAD类型的先请求会导致后面的GET请求返回为空

fastcgi_temp_path  path [level1 [level2 [level3]]];  默认为 fastcgi_temp;

该指令用来设置fastcgi_cache临时文件目录

1
fastcgi_temp_path /spool/nginx/fastcgi_temp 1 2;

a temporary file might look like this:

1
/spool/nginx/fastcgi_temp/7/45/00000123457

fastcgi_cache_use_stale : fastcgi_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_503 | http_403 | http_404 | off ...;

定义哪些情况下用过期缓存

x-cache头,用于调试

$upstream_response_time为过期时间

$upstream_cache_status 变量表示此请求响应来自cache的状态,几种状态分别为:

  • MISS – The response was not found in the cache and so was fetched from an origin server. The response might then have been cached.
  • BYPASS – The response was fetched from the origin server instead of served from the cache because the request matched a proxy_cache_bypass directive (see Can I Punch a Hole Through My Cache? below.) The response might then have been cached.
  • EXPIRED – The entry in the cache has expired. The response contains fresh content from the origin server.
  • STALE – The content is stale because the origin server is not responding correctly, and proxy_cache_use_stale was configured.
  • UPDATING – The content is stale because the entry is currently being updated in response to a previous request, and proxy_cache_use_stale updating is configured.
  • REVALIDATED – The proxy_cache_revalidate directive was enabled and NGINX verified that the current cached content was still valid (If-Modified-Since or If-None-Match).
  • HIT – The response contains valid, fresh content direct from the cache.

有一些情况会影响到cache的命中 这里需要特别注意

  • Nginx fastcgi_cache在缓存后端fastcgi响应时,当响应里包含“set-cookie”时,不缓存;
  • 当响应头包含Expires时,如果过期时间大于当前服务器时间,则nginx_cache会缓存该响应,否则,则不缓存;
  • 当响应头包含Cache-Control时,如果Cache-Control参数值为no-cache、no-store、private中任意一个时,则不缓存,如果Cache-Control参数值为max-age时,会被缓存,且nginx设置的cache的过期时间,就是系统当前时间 + mag-age的值。
1
2
3
4
5
6
7
8
header("Expires: ".gmdate("D, d M Y H:i:s", time()+10000).' GMT');
header("Expires: ".gmdate("D, d M Y H:i:s", time()-99999).' GMT');
header("X-Accel-Expires:5"); // 5s
header("Cache-Control: no-cache"); //no cache
header("Cache-Control: no-store"); //no cache
header("Cache-Control: private"); //no cache
header("Cache-Control: max-age=10"); //cache 10s
setcookie('hello',"testaaaa"); //no cache

注意session使用的时候有坑,可以用下面来设置

1
2
3
session_cache_limiter("none");
session_start();
echo date("Y-m-d H:i:s",time());

可以看一下PHP源代码中的头信息 Expires等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//ext/session/session.c  line:1190 左右
// ...
CACHE_LIMITER_FUNC(private/* {{{ */
{
    ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
    CACHE_LIMITER(private_no_expire)(TSRMLS_C);
}
/* }}} */
//再到这里3 或者上面几个 ##默认是nocache
CACHE_LIMITER_FUNC(nocache) /* {{{ */
{
    ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
  
    /* For HTTP/1.1 conforming clients and the rest (MSIE 5) */
    ADD_HEADER("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
  
    /* For HTTP/1.0 conforming clients */
    ADD_HEADER("Pragma: no-cache");
}
/* }}} */
//这里2
static php_session_cache_limiter_t php_session_cache_limiters[] = {
    CACHE_LIMITER_ENTRY(public)
    CACHE_LIMITER_ENTRY(private)
    CACHE_LIMITER_ENTRY(private_no_expire)
    CACHE_LIMITER_ENTRY(nocache)
    {0}
};
  
static int php_session_cache_limiter(TSRMLS_D) /* {{{ */
{
    php_session_cache_limiter_t *lim;
  
    if (PS(cache_limiter)[0] == '\0'return 0;
  
    if (SG(headers_sent)) {
        const char *output_start_filename = php_output_get_start_filename(TSRMLS_C);
        int output_start_lineno = php_output_get_start_lineno(TSRMLS_C);
  
        if (output_start_filename) {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno);
        else {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent");
        }
        return -2;
    }
  
    for (lim = php_session_cache_limiters; lim->name; lim++) {
        if (!strcasecmp(lim->name, PS(cache_limiter))) {
            lim->func(TSRMLS_C);   //这里1
            return 0;
        }
    }
  
    return -1;
}

三、清除缓存

NGINX只在商业版中支持proxy_cache_purge指令清除缓存,开源的ngx_cache_purge模块只支持单一key的缓存清除。为了实现按目录清除缓存只能自己开发。

NGINX作为Cache服务器时将资源内容以文件形式进行缓存,缓存元信息存储于共享内存中,组织成一棵红黑树。红黑树中的每个节点代表一个Cache元信息。NGINX将Cache Key的HASH值作为红黑树节点的KEY。内容缓存文件以该HASH值作为文件名存储在磁盘上。

NGINX的处理流程简化描述是这样的:当请求到达时,根据Cache Key的HASH值在红黑树中进行查找。如果找到,并查看相关信息,如果Cache可用,返回相应的Cache文件。否则,则回源抓取。

因为元信息是以Cache Key的HASH值作为Key存储的,因而红黑树中并不能保留Cache Key中有层级关系. 如”/uri/foo”和”/uri/bar”在元信息红黑树中完全没有关系。要实现按照目录清除缓存,需要将Cache Key中层次关系存储起来。

可以这样做,在共享内存中建立一棵目录树来存储层级关系。将Cache Key类比于文件系统中的路径, 每级路径存储为树中的一个节点。当需要清除某一目录下的所有缓存时,将该节点子树的中的所有缓存清除即可。

NGINX和NGINX Plus缓存指南

我们都知道,应用程序和网站的性能是成功的关键因素。但是,使您的应用程序或网站表现更好的过程并不总是很清楚。代码质量和基础架构当然至关重要,但在很多情况下,您可以通过关注一些非常基本的应用程序交付技术,对应用程序的最终用户体验进行大幅改进。一个这样的例子是通过在你的应用栈中实现和优化缓存。这篇博客文章介绍的技术可以帮助初学者和高级用户利用NGINX中包含的内容缓存功能获得更好的性能。

概观

内容缓存位于客户端和“原始服务器”之间,并保存其看到的所有内容的副本。如果客户端请求缓存存储的内容,它将直接返回内容而不会联系原始服务器。这可以提高性能,因为内容缓存更接近客户端,并且更高效地使用应用程序服务器,因为他们无需每次都从头开始生成页面。

Web浏览器和应用程序服务器之间可能存在多个高速缓存:客户端的浏览器高速缓存,中间缓存,内容交付网络(CDN)以及位于应用程序服务器前的负载均衡器或反向代理。即使在反向代理/负载平衡器级别,缓存也可以大大提高性能。

举个例子,去年,我接手了一个缓慢加载的网站的性能调整任务。我注意到的第一件事情是,它花了1秒钟以生成主页。经过一些调试之后,我发现由于该页面被标记为不可缓存,因此它是针对每个请求动态生成的。该页面本身没有经常变化,也没有个性化,所以这不是必需的。作为一个实验,我标记了负载平衡器缓存5秒的主页,只是这样做导致了显着的改进。第一个字节的时间缩短到几毫秒,页面加载速度明显加快。

NGINX通常作为应用程序堆栈中的反向代理或负载平衡器部署,并具有一整套高速缓存功能。下一节讨论如何使用NGINX配置基本缓存。

如何设置和配置基本缓存

只需两条指令即可启用基本缓存:proxy_cache_pathproxy_cache。该proxy_cache_path指令设置缓存的路径和配置,并且该proxy_cache指令激活它。

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off; server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://my_upstream;
}
}

proxy_cache_path指令的参数定义了以下设置:

  • 缓存的本地磁盘目录称为/ path / to / cache /
  • levels/ path / to / cache /下建立一个两级目录层次结构。在单个目录中有大量文件会降低文件访问速度,因此我们建议大多数部署使用两级目录层次结构。如果levels参数不包含,NGINX会将所有文件放在同一个目录中。
  • keys_zone设置一个共享内存区域用于存储缓存键和元数据(如使用计时器)。在内存中备份密钥副本使NGINX能够快速确定请求是否是一个HIT或一个MISS不必到磁盘,大大加快检查。1 MB区域可以存储大约8,000个密钥的数据,因此示例中配置的10 MB区域可以存储大约80,000个密钥的数据。
  • max_size设置缓存大小的上限(在本例中为10千兆字节)。它是可选的; 不指定值可以使缓存增长以使用所有可用的磁盘空间。当缓存大小达到限制时,称为缓存管理器的进程会删除最近最少使用的文件,以使缓存大小回到最大限度以下。
  • inactive指定项目在未被访问的情况下可保留在缓存中的时间。在此示例中,缓存管理器进程会自动从缓存中删除60分钟内未请求的文件,而不管其是否已过期。默认值是10分钟(10m)。非活动内容与过期内容不同。NGINX不会自动删除已由缓存控制标头定义的过期内容(Cache-Control:max-age=120例如)。只有在指定的时间内没有访问过期的(陈旧的)内容时,它才会被删除inactive。当访问过期内容时,NGINX从原始服务器刷新它并重置inactive定时器。
  • NGINX首先将写入缓存的文件写入临时存储区,然后该use_temp_path=off指令指示NGINX将它们写入到将被缓存的相同目录中。我们建议您将此参数设置off为避免文件系统之间不必要的数据复制。use_temp_path在NGINX版本1.7.10和NGINX Plus R6中引入。

最后,该proxy_cache指令激活缓存与父location块的URL匹配的所有内容(在示例中为/)。您也可以proxy_cache在一个server块中包含该指令; 它适用于location没有自己的proxy_cache指令的服务器的所有块。

当原点关闭时传送缓存内容

NGINX 内容缓存的一个强大功能是NGINX可以配置为在无法从原始服务器获取新内容时从缓存中提供陈旧内容。如果高速缓存资源的所有源服务器关闭或暂时繁忙,则可能会发生这种情况。NGINX不是将错误传递给客户端,而是从缓存中提供文件的陈旧版本。这为NGINX所代理的服务器提供了额外的容错级别,并确保服务器故障或流量高峰期的正常运行时间。要启用此功能,请包含以下proxy_cache_use_stale指令:

location / {
# ...
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}

通过这个示例配置,如果NGINX 从源服务器收到一个errortimeout或任何指定的5xx错误,并且它的缓存中有一个陈旧版本的请求文件,它将传递陈旧文件,而不是将错误传递给客户端。

微调缓存并提高性能

NGINX具有丰富的可选设置,用于微调缓存的性能。以下是一个激活其中几个例子的例子:

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off; server {
# ...
location / {
proxy_cache my_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 3;
proxy_cache_use_stale error timeout updating http_500 http_502
http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on; proxy_pass http://my_upstream;
}
}

这些指令配置以下行为:

  • proxy_cache_revalidate指示NGINX GET在刷新源服务器的内容时使用条件请求。如果客户端请求缓存控制标头所定义的缓存但过期的项目,NGINX 会将其发送到原始服务器If-Modified-SinceGET请求标头中的字段包含在内。这节省了带宽,因为服务器只有Last-Modified在NGINX最初缓存该文件时附加到该文件的头文件中记录的时间之后才发送整个项目。
  • proxy_cache_min_uses设置客户在NGINX缓存之前必须请求的次数。如果缓存不断填满,这很有用,因为它确保只有最常访问的项目才会添加到缓存中。默认情况下proxy_cache_min_uses设置为1。
  • 指令的updating参数proxy_cache_use_stale与启用指令相结合proxy_cache_background_update,指示NGINX在客户端请求从源服务器过期或正在更新的项目时发送陈旧内容。所有更新将在后台完成。所有请求都会返回失效文件,直到完全下载更新的文件。
  • proxy_cache_lock启用,如果多个客户端请求的文件不在缓存(电流MISS),只有第一个这些请求是通过原始服务器允许的。其余请求等待该请求被满足,然后从缓存中提取文件。如果未proxy_cache_lock启用,导致缓存未命中的所有请求将直接转到原始服务器。

跨多个硬盘分割高速缓存

使用NGINX,无需构建RAID。如果有多个硬盘驱动器,则可以使用NGINX在它们之间分割高速缓存。以下是一个基于请求URI将客户端平均分配到两个硬盘驱动器的示例:

proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m
max_size=10g inactive=60m use_temp_path=off;
proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m
max_size=10g inactive=60m use_temp_path=off; split_clients $request_uri $my_cache {
50% “my_cache_hdd1”;
50% “my_cache_hdd2”;
} server {
# ...
location / {
proxy_cache $my_cache;
proxy_pass http://my_upstream;
}
}

这两个proxy_cache_path指令定义了两个不同硬盘上的两个缓存(my_cache_hdd1my_cache_hdd2)。的split_clients配置块指定从一半的请求(结果50%)被缓存在my_cache_hdd1与另一半中my_cache_hdd2。基于$request_uri变量(请求URI)的散列决定了每个请求使用哪个缓存,结果是对给定URI的请求总是缓存在同一个缓存中。

常见问题(FAQ)

本节回答有关NGINX内容缓存的一些常见问题。

NGINX缓存可以进行检测吗?

是的,与add_header指令:

add_header X-Cache-Status $upstream_cache_status;

本示例X-Cache-Status在响应客户端时添加HTTP标头。以下是可能的值$upstream_cache_status

  • MISS - 在缓存中未找到响应,因此从原始服务器获取响应。该响应可能已被缓存。
  • BYPASS- 响应是从原始服务器获取的,而不是从缓存中提供,因为请求与proxy_cache_bypass指令匹配(请参阅下面的“我可以通过我的缓存打孔”)。然后可能会缓存响应。
  • EXPIRED - 缓存中的条目已过期。该响应包含来自原始服务器的新内容。
  • STALE- 内容陈旧,因为原始服务器没有正确响应,并且proxy_cache_use_stale已配置。
  • UPDATING- 内容陈旧,因为该条目当前正在更新以响应先前的请求并proxy_cache_use_stale updating进行配置。
  • REVALIDATEDproxy_cache_revalidate指令已启用,NGINX验证当前缓存内容仍然有效(If-Modified-SinceIf-None-Match)。
  • HIT - 响应包含直接来自缓存的有效新鲜内容。

NGINX如何确定是否缓存某些内容?

默认情况下,NGINX尊重Cache-Control来自原始服务器的标题。它不缓存响应Cache-Control设置为PrivateNo-CacheNo-StoreSet-Cookie在响应头。NGINX只缓存GETHEAD客户端请求。您可以覆盖这些默认值,如下面的答案中所述。

如果proxy_buffering设置为NGINX不会缓存响应off。这是on默认的。

Cache-Control头能视而不见吗?

是的,与proxy_ignore_headers指令。例如,使用此配置:

location /images/ {
proxy_cache my_cache;
proxy_ignore_headers Cache-Control;
proxy_cache_valid any 30m;
# ...
}

NGINX忽略/ images /Cache-Control下所有内容的标题。该指令强制缓存数据到期,如果忽略标题,则是必需的。NGINX不会缓存没有到期的文件。proxy_cache_validCache-Control

NGINX可以Set-Cookie在标题中使用a缓存内容吗?

是的proxy_ignore_headers,正如前面的回答中所讨论的那样。

NGINX缓存POST请求可以吗?

是的,与proxy_cache_methods指令:

proxy_cache_methods GET HEAD POST;

本示例启用缓存POST请求。

NGINX可以缓存动态内容吗?

是的,只要Cache-Control标题允许。在短时间内缓存动态内容可以减少原始服务器和数据库的负载,这可以缩短第一个字节的时间,因为不必为每个请求重新生成页面。

我可以通过缓存打洞吗?

是的,与proxy_cache_bypass指令:

location / {
proxy_cache_bypass $cookie_nocache $arg_nocache;
# ...
}

该指令定义NGINX立即从源服务器请求内容的请求类型,而不是先尝试在缓存中找到它。这有时被称为通过缓存“打孔”。在这个例子中,例如,NGINX为具有nocachecookie或参数的请求执行此操作http://www.example.com/?nocache=true。NGINX仍然可以为将来未被绕过的请求缓存响应结果。

NGINX使用什么缓存键?

该NGINX生成密钥的缺省形式是类似于以下的MD5哈希NGINX变量$scheme$proxy_host$request_uri; 实际使用的算法稍微复杂一些。

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off; server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://my_upstream;
}
}

对于此示例配置,缓存密钥for http://www.example.org/my_image.jpg计算为md5(“http://my_upstream:80/my_image.jpg”)

请注意,$proxy_host变量用于哈希值而不是实际的主机名(www.example.com)。$proxy_host被定义为proxy_pass指令中指定的代理服务器的名称和端口。

要更改用作键的基础的变量(或其他词),请使用该 proxy_cache_key指令(另请参阅以下问题)。

我可以使用Cookie作为我的缓存键的一部分吗?

是的,缓存密钥可以配置为任意值,例如:

proxy_cache_key $proxy_host$request_uri$cookie_jessionid;

本示例将JSESSIONIDCookie 的值合并到缓存键中。具有相同URI但具有不同JSESSIONID值的项目将分别缓存为唯一项目。

NGINX是否使用ETag标题?

在NGINX 1.7.3和NGINX Plus R5及更高版本中,ETag头文件完全受支持If-None-Match

NGINX如何处理字节范围请求?

如果该文件在缓存中是最新的,那么NGINX将确认一个字节范围请求,并仅将该项目的指定字节提供给客户端。如果文件没有被缓存,或者文件已经失效,NGINX从原始服务器下载整个文件。如果请求是针对单个字节范围的,NGINX一旦在下载流中遇到该范围,就将该范围发送给客户端。如果请求在同一文件中指定了多个字节范围,则在下载完成时,NGINX会将整个文件传送到客户端。

下载完成后,NGINX将整个资源移入缓存中,以便所有将来的字节范围请求(无论是单个范围还是多个范围)都立即从缓存中满足。

请注意,upstream服务器必须支持NGINX的字节范围请求,以响应到该upstream服务器的字节范围请求。

NGINX是否支持缓存清除?

NGINX Plus支持选择性清除缓存文件。如果文件已在源服务器上更新但在NGINX Plus缓存Cache-Control:max-age中仍然有效(该文件仍然有效,并且指令inactive参数设置的超时proxy_cache_path未过期),此功能很有用。借助NGINX Plus的缓存清除功能,该文件可以轻松删除。有关更多详细信息,请参阅清除缓存中的内容

NGINX如何处理Pragma标题?

Pragma:no-cache报头由客户加入到绕过所有中间缓存,直接进入到源服务器的请求的内容。NGINX在Pragma默认情况下不支持标题,但您可以使用以下proxy_cache_bypass指令配置该功能:

location /images/ {
proxy_cache my_cache;
proxy_cache_bypass $http_pragma;
# ...
}

NGINX是否支持头文件stale-while-revalidatestale-if-error扩展Cache-Control

是的,在NGINX Plus R12和NGINX 1.11.10及更高版本中。这些扩展可以做什么:

    • HTTP头的stale-while-revalidate扩展Cache-Control允许使用陈旧的缓存响应,如果它正在更新。

HTTP头的stale-if-error扩展Cache-Control允许在发生错误时使用陈旧的缓存响应。

这些头具有比低优先级proxy_cache_use_stale指令如上所述

NGINX是否支持Vary标题?

是的,在NGINX Plus R5和NGINX 1.7.7及更高版本中。这是一个很好的Vary头部概览

安装Purge模块

Purge模块被用来清除缓存

1
2
wget http://labs.frickle.com/files/ngx_cache_purge-1.2.tar.gz
tar -zxvf ngx_cache_purge-1.2.tar.gz

编译

1
2
3
4
./configure \
…… \
--with-http_geoip_module \
--add-module=/usr/local/ngx_cache_purge-1.2

四、需要注意的一些问题

设置了之后重启nginx就可以生效了,这个时候再访问php的页面的话,就会被缓存了,可以查看/var/logs/nginx/fastcgi_cache_dir这个目录下面是有缓存文件的。最后再说明一点,如果更改了缓存目录的路径,一定要把缓存的名称也改掉,后端调用的名称也同步改掉,如果只改掉了缓存目录,不改缓存名称的话,缓存的时候还是会缓存到之前的路径下面去,但是调用的时候调用的是新的路径,这个时候就会出现找不到的情况

参考文章

http://www.nginxtips.com/configure-nginx-fastcgi-cache/

http://www.haidx.com/fastcgi-cache-details.html

http://www.just4coding.com/blog/2014/11/01/nginx-purge-directory/

http://weizhifeng.net/nginx-proxy-cache.html

https://www.nginx.com/blog/nginx-caching-guide/#gs.6PdbraI

http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache

https://www.cnxct.com/several-reminder-in-nginx-fastcgi_cache-and-php-session_cache_limiter/

https://rtcamp.com/wordpress-nginx/tutorials/single-site/fastcgi-cache-with-purging/

http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache

 

nginx cache的玩法的更多相关文章

  1. 全面解密QQ红包技术方案:架构、技术实现、移动端优化、创新玩法等

    本文来自腾讯QQ技术团队工程师许灵锋.周海发的技术分享. 一.引言 自 2015 年春节以来,QQ 春节红包经历了企业红包(2015 年).刷一刷红包(2016 年)和 AR 红包(2017 年)几个 ...

  2. 朱晔的互联网架构实践心得S2E4:小议微服务的各种玩法(古典、SOA、传统、K8S、ServiceMesh)

    十几年前就有一些公司开始践行服务拆分以及SOA,六年前有了微服务的概念,于是大家开始思考SOA和微服务的关系和区别.最近三年Spring Cloud的大火把微服务的实践推到了高潮,而近两年K8S在容器 ...

  3. 【腾讯云的1001种玩法】几种在腾讯云建立WordPress的方法(Linux)(二)

    版权声明:本文由张宁原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/126547001488207964 来源:腾云阁 ht ...

  4. openresty+lua在反向代理服务中的玩法

    openresty+lua在反向代理服务中的玩法 phith0n · 2015/06/02 10:35 0x01 起因 几天前学弟给我介绍他用nginx搭建的反代,代理了谷歌和维基百科. 由此我想到了 ...

  5. kubernetes之coredns玩法

    一.概述 新版本的kubernetes默认使用了coredns,这里就不赘述了.直达车:https://coredns.io/.https://kubernetes.io/docs/tasks/adm ...

  6. [C#] 软硬结合第二篇——酷我音乐盒的逆天玩法

    1.灵感来源: LZ是纯宅男,一天从早上8:00起一直要呆在电脑旁到晚上12:00左右吧~平时也没人来闲聊几句,刷空间暑假也没啥动态,听音乐吧...~有些确实不好听,于是就不得不打断手头的工作去点击下 ...

  7. git分布式版本控制玩法

    git分布式版本控制玩法 Git distributed version control play github的配置安装步骤:1.下载git bash(从http://www.git-scm.com ...

  8. 自定义 checkbox 新玩法 ?

    自定义 checkbox 新玩法 ? 第一步:selector 编写 drawable/selector_checkbox_voice.xml <?xml version="1.0&q ...

  9. 【第1期】腾讯云的1001种玩法征集,Ipad mini和Kindle 等你拿!(文章评审中)

    版权声明:本文由阁主的小跟班原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/695994001482226944 来源:腾云 ...

随机推荐

  1. Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper

    RecyclerView这个被誉为ListView和GirdView的替代品,它的用法在之前的一篇博文中就已经讲过了,今天我们就来实现RecyclerView的侧滑删除和长按拖拽功能,实现这两个功能我 ...

  2. 为macbook双系统的windows装驱动

    网上有很多装双系统教程,这里就不再累赘,但是自己发现装完后驱动怎么装并没有交代清楚. 研究后发现,在作为驱动盘的U盘里,BootCamp文件夹下有个setup.exe 运行此程序便进行驱动的安装.

  3. How Tomcat Works 读书笔记 八 载入器 上

    Java的类载入器 详细资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...

  4. 43个优秀的Swift开源项目推荐

    "轮子" 工具类 项目 开发者 备注 SwiftyJSON tangplin, lingoer GitHub 上最为开发者认可的 JSON 解析类 Dollar.swift Ank ...

  5. Linux Framebuffer驱动剖析之一—软件需求

    嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT两方面的原创技术分享,稍后会发布嵌入式企鹅圈的2 ...

  6. MR PAGERANK思路

    map( key: [url, pagerank], value: outlink_list ) for each outlink in outlink_list emit( key: outlink ...

  7. SharePoint2010 -- ECMAScript客户端模型简单示例

    ECMAScript客户端模型,是SharePoint2010推出的三种客户端模型".NET托管"."ECMAScript"."Sliverlight ...

  8. Unity脚本编程之——协程(Coroutine)

    本文翻译自Unity官方文档:https://docs.unity3d.com/Manual/Coroutines.html 专有名词: Coroutine 协程 Alpha 不透明度 当你调用一个函 ...

  9. mysql性能优化之-innodb_flush_log_at_trx_commit

    innodb_flush_log_at_trx_commit是配置MySql日志何时写入硬盘的参数: 一.参数值说明 0:log buffer将每秒一次地写入log file中,并且log file的 ...

  10. 深入理解springMVC思想

     转载:http://elf8848.iteye.com/blog/875830 深入理解Spring MVC 思想   目录  一.前言二.spring mvc 核心类与接口三.spring mvc ...