#1,ETag和Last-Modified
nginx的proxy_cache可以通过缓存首部Cache-Control和Expires进行代理缓存,但是有个参数可以有效减少报文的传输
proxy_cache_revalidate on;
proxy_cache_revalidate on;
##1.1 缓存原理
在HTTP协议中If-Modified-Since和If-None-Match分别对应Last-Modified和ETag。结合Expires为缓存的方式实现减少传输报文的场景。按照RFC2616对HTTP协议的规定,在客户端第二次向服务器发出请求时,对于第一次访问请求的资源如果响应状态为200的资源,那么在这次请求中将会添加一个新的请求头:If-Modified-Since,故名思议,就是询问服务器从这个时间起,或者说是以这个时间为分割点,在这时间点之前有没有修改过这个文档,如果没有修改,那么返回的http状态代码是304.并且同时再次发回响应头Last-Modified,而且这两个头的时间完全相同的。
在计算Etag的时候,会产生CPU的耗费,所以也可以用时间戳,但这样直接使用Last-Modified即可。
在同时使用Expires和Etag时,没有优先级,在满足两者时才会做出决定。
在http的Response的首部中,有transfer-coding域值为chunked。则无法使用304的原理。在tomcat中禁用的方法就是设置返回的缓存,只要返回数据小于这个缓存,则不会开启。 response.setBufferSize(1024 * 1024);
如果expires 和 add_header 同时开启的情况下,则add_header优于expires生效;
- 查看图
启用proxy_cache_min_uses最后一次缓存出发的时候,nginx服务器不会把304透传给应用服务器,而是直接获取最新的数据进行缓存,应用服务器返回200状态码
- proxy_cache_min_uses
proxy_cache_min_uses
proxy_cache_min_uses
##1.2 缓存规则
所有的缓存,都遵循源策略,就像CDN一样。Cache-Control以下4个属性,出现任意一个,则不缓存。 no-cache, no-store, max-age=0, s-maxage=0 其中max-age和s-maxage大于0的时候,则根据源站策略进行缓存,proxy_cache_valid的缓存设置时间失效。
当 max-age=3, s-maxage=5,同时配置的时候,nginx缓存时间以s-maxage时间为主。 遵循源和proxy_cache_path里面的时间有冲突的时候,策略如下:
当proxy_cache_path时间大于遵循源的时候,遵循源时间到期,请求时候,重新设置并覆盖磁盘上的文件;
当proxy_cache_path时间小于遵循源的时候,则proxy_cache_path到期的时候,重新到源站获取数据,遵循源策略失效。
#2,参数配置
proxy_cache_valid 200 304 301 302 1h; #哪些状态缓存多长时间
proxy_cache_methods GET; # 默认是get和head
proxy_cache_valid any 3s; #其他的缓存多长时间
proxy_cache_key $host:$server_port$uri$is_args$args;
#通过key来hash,定义KEY的值
#缓存的具体key值是: [host]192.168.56.2 [server_port]8080 [uri]/cache_ehcache-2.10.0_web/expire [is_args] [args]-
proxy_cache_min_uses 3; #只要统一个url,在磁盘文件删除之前,总次数访问到达3次,就开始缓存
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment; # 如果任何一个参数值不为空,或者不等于0,nginx就不会查找缓存,直接进行代理转发
proxy_cache_valid 200 304 301 302 1h; #哪些状态缓存多长时间
proxy_cache_methods GET; # 默认是get和head
proxy_cache_valid any 3s; #其他的缓存多长时间
proxy_cache_key $host:$server_port$uri$is_args$args;
#通过key来hash,定义KEY的值
#缓存的具体key值是: [host]192.168.56.2 [server_port]8080 [uri]/cache_ehcache-2.10.0_web/expire [is_args] [args]-
proxy_cache_min_uses 3; #只要统一个url,在磁盘文件删除之前,总次数访问到达3次,就开始缓存
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment; # 如果任何一个参数值不为空,或者不等于0,nginx就不会查找缓存,直接进行代理转发
#3,例子
##3.1 favicon缓存
location = /favicon.ico {
root html;
index index.html index.htm;
expires 30d; #会同时设置Expires 和 Cache-Control:max-age
add_header Pragma Pragma;
}
location = /favicon.ico {
root html;
index index.html index.htm;
expires 30d; #会同时设置Expires 和 Cache-Control:max-age
add_header Pragma Pragma;
}
4. 避免 Nginx 缓存 0 字节文件的方法
- 通过使用 Content-Length 响应头信息来判断并禁止缓存
只缓存大小大于0的内容
map $upstream_http_content_length $flag_cache_empty {
default 0;
0 1;
}
server {
....
location / {
...
proxy_no_cache $flag_cache_empty;
proxy_cache_bypass $flag_cache_empty;
...
}
}
如果 Content-Length 值为 0 时 map 将设置 flag_cache_empty 变量值为 1,当这个值为 1 时不启用缓存
只缓存大小大于0的内容
map $upstream_http_content_length $flag_cache_empty {
default 0;
0 1;
}
server {
....
location / {
...
proxy_no_cache $flag_cache_empty;
proxy_cache_bypass $flag_cache_empty;
...
}
}
如果 Content-Length 值为 0 时 map 将设置 flag_cache_empty 变量值为 1,当这个值为 1 时不启用缓存
proxy_cache
proxy_cache_path /home/nginx/proxy_cache/cache levels=1:2 keys_zone=proxycache:60m max_size=120m inactive=2h use_temp_path=off;
proxy_cache_key $host$request_uri;
proxy_cache proxycache;
proxy_cache_valid 304 2h;
proxy_cache_valid 403 444 24h;
proxy_cache_valid 404 2h;
proxy_cache_valid 500 502 2h;
proxy_cache_use_stale invalid_header http_403 http_404 http_500 http_502;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_no_cache $proxynocache_atomxml $proxynocache_sitemapxml;
proxy_cache_path /home/nginx/proxy_cache/cache levels=1:2 keys_zone=proxycache:60m max_size=120m inactive=2h use_temp_path=off;
proxy_cache_key $host$request_uri;
proxy_cache proxycache;
proxy_cache_valid 304 2h;
proxy_cache_valid 403 444 24h;
proxy_cache_valid 404 2h;
proxy_cache_valid 500 502 2h;
proxy_cache_use_stale invalid_header http_403 http_404 http_500 http_502;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_no_cache $proxynocache_atomxml $proxynocache_sitemapxml;
- proxy_cache:对应 http 段的 key_zone,是你定义的 proxy_cache 所使用的共享空间的名称。我在上面示例中使用的名称是“proxycache”
- proxy_cache_valid:对指定的 HTTP 状态进行缓存,并指定缓存时间。可以自定义写入多个配置项
- proxy_cache_stale:这个可以大大减少回源次数。因此可以将 inactive 适当延长
- proxy_cache_lock:同样是减少回源次数。和上面的差别在于缓存是否存在
- proxy_no_cache:值为若干个变量($string),这个变量的值只有俩类,0 和 非0,这若干个变量中只要有一个值不为 0,就不会触发缓存
5.案例
[root@pcweb conf]# cat proxy.conf
proxy_cache_path /data/cache_dir/cdn levels=1:2 keys_zone=Rats:600m inactive=6h max_size=10g use_temp_path=off;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_buffer_size 32k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
[root@pcweb conf]# cat proxy.conf
proxy_cache_path /data/cache_dir/cdn levels=1:2 keys_zone=Rats:600m inactive=6h max_size=10g use_temp_path=off;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_buffer_size 32k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
upstream NORTH1_SERVER_PROXY {
server 172.x.x.x:10000 max_fails=2 fail_timeout=30s;
}
server {
listen 80 fastopen=3 reuseport;
server_name xxx.com;
return 301 https://xxx.com$request_uri;
}
server {
listen 443 ssl http2;
server_name web.xxx.io www.xxx.io xxx.io;
ssl_certificate /data/apps/nginx/ssl/xx.crt;
ssl_certificate_key /data/apps/nginx/ssl/xx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5';
ssl_async on;
ssl_prefer_server_ciphers on;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:20m;
ssl_early_data on;
#ssl_stapling on;
#ssl_stapling_verify on;
#ssl_trusted_certificate /data/apps/nginx/ssl/chain.pem;
include /data/apps/nginx/conf/roles/*.conf;
if ($server_port !~ 443) {
rewrite ^(.*)$ https://$host$1 permanent;
}
if ($request_uri ~ ^/static/js/login.*\.(js|css)) {
set $nocache 1;
}
if ($request_uri ~ ^/static/js/register.*\.js) {
set $nocache 1;
}
location ~* /downloadImgs/*\.(png)$ {
add_header Content-Disposition: "attachment; filename=$1";
}
location / {
try_files $uri $uri/ /index.html;
proxy_set_header Accept-Encoding "";
proxy_next_upstream http_500 http_503 http_504 error timeout invalid_header;
proxy_pass http://NORTH1_SERVER_PROXY;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache Rats;
proxy_cache_valid 304 2h;
proxy_cache_valid 301 24h;
proxy_cache_valid 500 502 503 504 0s;
proxy_cache_valid any 2h;
proxy_cache_min_uses 1;
expires 4h;
proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie";
#add
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_no_cache $nocache $arg_nocache $arg_comment;
}
location ~ .*\.(htm|html|js|css|gif|webp|jpg|jpeg|png|bmp|woff)$ {
try_files $uri $uri/ /index.html;
proxy_ignore_headers Cache-Control;
proxy_next_upstream http_500 http_503 http_504 error timeout invalid_header;
proxy_cache Rats;
proxy_cache_valid 200 304 1d;
proxy_cache_valid 301 302 2h;
proxy_cache_valid 404 10m;
proxy_cache_valid any 2h;
proxy_cache_key $host$uri$is_args$args;
proxy_no_cache $nocache $arg_nocache $arg_comment;
#proxy_no_cache $http_pargma $http_authorization;
add_header x-cache '$upstream_cache_status from TCP-MEM_CACHEB';
proxy_pass http://NORTH1_SERVER_PROXY;
expires 4d;
}
access_log /var/log/nginx/web_access.log es;
}
upstream NORTH1_SERVER_PROXY {
server 172.x.x.x:10000 max_fails=2 fail_timeout=30s;
}
server {
listen 80 fastopen=3 reuseport;
server_name xxx.com;
return 301 https://xxx.com$request_uri;
}
server {
listen 443 ssl http2;
server_name web.xxx.io www.xxx.io xxx.io;
ssl_certificate /data/apps/nginx/ssl/xx.crt;
ssl_certificate_key /data/apps/nginx/ssl/xx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5';
ssl_async on;
ssl_prefer_server_ciphers on;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:20m;
ssl_early_data on;
#ssl_stapling on;
#ssl_stapling_verify on;
#ssl_trusted_certificate /data/apps/nginx/ssl/chain.pem;
include /data/apps/nginx/conf/roles/*.conf;
if ($server_port !~ 443) {
rewrite ^(.*)$ https://$host$1 permanent;
}
if ($request_uri ~ ^/static/js/login.*\.(js|css)) {
set $nocache 1;
}
if ($request_uri ~ ^/static/js/register.*\.js) {
set $nocache 1;
}
location ~* /downloadImgs/*\.(png)$ {
add_header Content-Disposition: "attachment; filename=$1";
}
location / {
try_files $uri $uri/ /index.html;
proxy_set_header Accept-Encoding "";
proxy_next_upstream http_500 http_503 http_504 error timeout invalid_header;
proxy_pass http://NORTH1_SERVER_PROXY;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache Rats;
proxy_cache_valid 304 2h;
proxy_cache_valid 301 24h;
proxy_cache_valid 500 502 503 504 0s;
proxy_cache_valid any 2h;
proxy_cache_min_uses 1;
expires 4h;
proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie";
#add
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
proxy_no_cache $nocache $arg_nocache $arg_comment;
}
location ~ .*\.(htm|html|js|css|gif|webp|jpg|jpeg|png|bmp|woff)$ {
try_files $uri $uri/ /index.html;
proxy_ignore_headers Cache-Control;
proxy_next_upstream http_500 http_503 http_504 error timeout invalid_header;
proxy_cache Rats;
proxy_cache_valid 200 304 1d;
proxy_cache_valid 301 302 2h;
proxy_cache_valid 404 10m;
proxy_cache_valid any 2h;
proxy_cache_key $host$uri$is_args$args;
proxy_no_cache $nocache $arg_nocache $arg_comment;
#proxy_no_cache $http_pargma $http_authorization;
add_header x-cache '$upstream_cache_status from TCP-MEM_CACHEB';
proxy_pass http://NORTH1_SERVER_PROXY;
expires 4d;
}
access_log /var/log/nginx/web_access.log es;
}
香港服务器反向代理我这台国内的服务器.来加速境外缓存.
境内->CDN->源站
境外->香港服务器->CDN->源站
境内->CDN->源站
境外->香港服务器->CDN->源站
#PROXY-START/
location ~* \.(php|jsp|cgi|asp|aspx)$
{
proxy_pass https://blog.kieng.cn.**.***;
proxy_set_header Host blog.kieng.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
}
location /
{
proxy_pass https://blog.kieng.cn.**.***;
proxy_set_header Host blog.kieng.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
#Set <a href="https://blog.kieng.cn/tag/nginx" title="查看更多关于 Nginx 的文章" target="_blank">Nginx</a> Cache
proxy_ignore_headers Set-Cookie Cache-Control expires;
proxy_cache cache_one;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 304 301 302 1h;
expires 12h;
}
#我们需要缓存的文件后缀,可以自己按照自己的情况配置
location ~*\.(png|jpg|gif|svg|jpeg|js|css|ttf|woff|eot)$ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
#所有链接,浏览器缓存过期时间为 365 天
expires 365d;
#此目录为服务器的根目录,下面的 if 语句就是判断此目录下是否有响应的文件
root /www/wwwroot/blog.kieng.cn;
#表示开启缓存
proxy_store on;
#表示用户读写权限
proxy_store_access user:rw group:rw all:rw;
#此处为文件的缓存路径,这个路径是和 url 中的文件路径一致的
proxy_temp_path /www/wwwroot/blog.kieng.cn;
#发送的 host 就是博客域名
proxy_set_header Host blog.kieng.cn;
#这句话的意思是请求时让源服务器不压缩数据,如果你开启了 gzip 的话必须加这个.要不然 CSS 和 JS 文件会乱码
proxy_set_header Accept-Encoding identity;
if ( !-e $request_filename) {
#此处为要被代理的服务器的地址 CDN 的 cname 地址
proxy_pass https://blog.kieng.cn.**.***;
}
}
#PROXY-END/
#PROXY-START/
location ~* \.(php|jsp|cgi|asp|aspx)$
{
proxy_pass https://blog.kieng.cn.**.***;
proxy_set_header Host blog.kieng.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
}
location /
{
proxy_pass https://blog.kieng.cn.**.***;
proxy_set_header Host blog.kieng.cn;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
#Set <a href="https://blog.kieng.cn/tag/nginx" title="查看更多关于 Nginx 的文章" target="_blank">Nginx</a> Cache
proxy_ignore_headers Set-Cookie Cache-Control expires;
proxy_cache cache_one;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 304 301 302 1h;
expires 12h;
}
#我们需要缓存的文件后缀,可以自己按照自己的情况配置
location ~*\.(png|jpg|gif|svg|jpeg|js|css|ttf|woff|eot)$ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
#所有链接,浏览器缓存过期时间为 365 天
expires 365d;
#此目录为服务器的根目录,下面的 if 语句就是判断此目录下是否有响应的文件
root /www/wwwroot/blog.kieng.cn;
#表示开启缓存
proxy_store on;
#表示用户读写权限
proxy_store_access user:rw group:rw all:rw;
#此处为文件的缓存路径,这个路径是和 url 中的文件路径一致的
proxy_temp_path /www/wwwroot/blog.kieng.cn;
#发送的 host 就是博客域名
proxy_set_header Host blog.kieng.cn;
#这句话的意思是请求时让源服务器不压缩数据,如果你开启了 gzip 的话必须加这个.要不然 CSS 和 JS 文件会乱码
proxy_set_header Accept-Encoding identity;
if ( !-e $request_filename) {
#此处为要被代理的服务器的地址 CDN 的 cname 地址
proxy_pass https://blog.kieng.cn.**.***;
}
}
#PROXY-END/
6.跳过缓存配置
第一个是url包含preview和cauth不缓存,第二个是url包含type =4的缓存,其他都不走缓存
location ~* /apadlibrary/.*GetJpgUrl.aspx.* {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://usp_sub;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_cache cache_one;
proxy_cache_valid 301 302 1d;
proxy_cache_bypass $arg_preview $arg_cauth;
add_header Nginx-Cache "$upstream_cache_status";
expires 1d;
}
location ~* /.*/Detail.mvc.* {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://usp_iis;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_cache cache_one;
proxy_cache_valid 301 302 1d;
set $nocache 1;
if ($arg_type = "4") {
set $nocache 0;
}
proxy_cache_bypass $nocache;
add_header Nginx-Cache "$upstream_cache_status";
expires 1d;
}
location ~* /apadlibrary/.*GetJpgUrl.aspx.* {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://usp_sub;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_cache cache_one;
proxy_cache_valid 301 302 1d;
proxy_cache_bypass $arg_preview $arg_cauth;
add_header Nginx-Cache "$upstream_cache_status";
expires 1d;
}
location ~* /.*/Detail.mvc.* {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://usp_iis;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
proxy_cache cache_one;
proxy_cache_valid 301 302 1d;
set $nocache 1;
if ($arg_type = "4") {
set $nocache 0;
}
proxy_cache_bypass $nocache;
add_header Nginx-Cache "$upstream_cache_status";
expires 1d;
}