AIOps 一场颠覆传统运维的盛筵
968
2022-10-13
Nginx下关于缓存控制字段cache-control的配置说明 - 运维小结
HTTP协议的Cache -Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置 Cache-Control并不会影响另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括: no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached等。响应消息中的指令包括: public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。
下面做一详细总结, 方便在以后的运维工作中理解和运用.
一. 浏览器中关于Cache的3属性:1. Cache-Control:设置相对过期时间, max-age指明以秒为单位的缓存时间. 若对静态资源只缓存一次, 可以设置max-age的值为315360000000 (一万年). 比如对于提交的订单,为了防止浏览器回退重新提交,可以使用Cache-Control之no-store绝对禁止缓存,即便浏览器回退依然请求的是服务器,进而判断订单的状态给出相应的提示信息!
Http协议的cache-control的常见取值及其组合释义:no-cache: 数据内容不能被缓存, 每次请求都重新访问服务器, 若有max-age, 则缓存期间不访问服务器.no-store: 不仅不能缓存, 连暂存也不可以(即: 临时文件夹中不能暂存该资源).private(默认): 只能在浏览器中缓存, 只有在第一次请求的时候才访问服务器, 若有max-age, 则缓存期间不访问服务器.public: 可以被任何缓存区缓存, 如: 浏览器、服务器、代理服务器等.max-age: 相对过期时间, 即以秒为单位的缓存时间.no-cache, private: 打开新窗口时候重新访问服务器, 若设置max-age, 则缓存期间不访问服务器.- private, 正数的max-age: 后退时候不会访问服务器.- no-cache, 正数的max-age: 后退时会访问服务器.
2. Expires:设置以分钟为单位的绝对过期时间, 优先级比Cache-Control低, 同时设置Expires和Cache-Control则后者生效. 也就是说要注意一点: Cache-Control的优先级高于Expires
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ { root /var/www/img/; expires 30d; }
再比如:
location ~ \.(wma|wmv|asf|mp3|mmf|zip|rar|swf|flv)$ { root /var/www/upload/; expires max; }
3. Last-Modified:该资源的最后修改时间, 在浏览器下一次请求资源时, 浏览器将先发送一个请求到服务器上, 并附上If-Unmodified-Since头来说明浏览器所缓存资源的最后修改时间, 如果服务器发现没有修改, 则直接返回304(Not Modified)回应信息给浏览器(内容很少), 如果服务器对比时间发现修改了, 则照常返回所请求的资源.
2) ETag将返回给浏览器一个资源ID, 如果有了新版本则正常发送并附上新ID, 否则返回304, 但是在服务器集群情况下, 每个服务器将返回不同的ID, 因此不建议使用ETag.
下面是相关页面设置Cache-Control头信息的几个简单配置:例一:
if ($request_uri ~* "^/$|^/search/.+/|^/company/.+/") { add_header Cache-Control max-age=3600; }
个人理解的max-age意思是:客户端本地的缓存,在配置的生存时间内的,客户端可以直接使用,超出生存时间的,到服务器上取新数据。当然这些还要看客户端浏览器的设置。
例二:
location ~ .*\.(css|js|swf|php|htm|html )$ { add_header Cache-Control no-store;}
例三:
location ~ .*\.(js|css)$ { expires 10d;}
例四: 将html结尾的请求加上no-cache
location / { access_log /data/nginx/log/xxx.log api; root /home/www/html; if ($request_filename ~ .*\.(htm|html)$) { add_header Cache-Control no-cache; }}
expires 24h;expires 0;expires -1;expires epoch;add_header Cache-Control private;
指令add_header add_headerexpires expires
可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的 time 值来获得。
epoch
指定“Expires”的值为 1 January, 1970, 00:00:01 GMT。
max
指定“Expires”的值为 31 December 2037 23:59:59 GMT,“Cache-Control”的值为10年。
-1
指定“Expires”的值为 服务器当前时间 -1s,即永远过期.
"Cache-Control"头标的值由您指定的时间来决定: - 负数
Cache-Control: no-cache
- 正数或零
Cache-Control: max-age = #
# 为您指定时间的秒数。
"off" 表示不修改“Expires”和“Cache-Control”的值;
响应头:Cache-Control:no-cache,强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据 的应用(不惜牺牲使用缓存的所有好处). 通俗解释:浏览器通知服务器,本地没有缓存数据.
通俗解释:响应头中的 Cache-Control:max-age=315360000 是通知浏览器: 315360000 秒之内不要烦我, 就自己从缓冲区中刷新。
语法指令不区分大小写,并且具有可选参数,可以用令牌或者带引号的字符串语法。多个指令以逗号分隔。
指令- 可缓存性public 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。表示相应会被缓存,并且在多用户间共享。默认是public。private 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它),可以缓存响应内容。响应只作为私有的缓存,不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。no-cache 在释放缓存副本之前,强制高速缓存将请求提交给原始服务器进行验证。指定不缓存响应,表明资源不进行缓存。但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。only-if-cached 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝.
- 到期max-age=
- 其他no-store 缓存不应存储有关客户端请求或服务器响应的任何内容。表示绝对禁止缓存!no-transform 不得对资源进行转换或转变。Content-Encoding, Content-Range, Content-Type等HTTP头不能由代理修改。例如,非透明代理可以对图像格式进行转换,以便节省缓存空间或者减少缓慢链路上的流量。 no-transform指令不允许这样做。
两个小示例- 禁止缓存发送如下指令可以关闭缓存。此外,可以参考Expires 和 Pragma 标题。
Cache-Control: no-cache, no-store, must-revalidate
- 缓存静态资源节对于应用程序中不会改变的文件,通常可以在发送响应头前添加积极缓存。这包括例如由应用程序提供的静态文件,例如图像,CSS文件和JavaScript文件。另请参阅Expires标题。
Cache-Control:public, max-age=31536000
这里扩展一下:HTTP1.0HTTP1.0中通过Pragma 控制页面缓存,通常设置的值为no- cache,不过这个值不这么保险,通常还加上Expires置为0来达到目的。但是如我们刻意需要浏览器或缓存服务器缓存住我们的页面这个值则要设置为 Pragma。
目前Cache-Control请求字段被各个浏览器支持的较好,其优先级也比较高,当和别的字段(如Expires)一起用时,会覆盖其他字段。
四. nginx配置管理浏览器静态缓存策略浏览器缓存: expires, cache-control, last-modified, etag. 先来看一张图:
每个状态的详细说明如下:1、Last-Modified在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记(HttpReponse Header)此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified:Tue, 24 Feb 2019 08:01:04 GMT
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头(HttpRequest Header),询问该时间之后文件是否有被修改过:
If-Modified-Since:Tue, 24 Feb 2019 08:01:04 GMT
如果服务器端的资源没有变化,则自动返回HTTP304(NotChanged.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
注意: 如果If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求
2、Etag工作原理HTTP协议规格说明定义ETag为“被请求变量的实体标记”(参见14.19)。简单点即服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式:
Etag:“5d8c72a5edda8d6a:3239″
客户端的查询更新格式是这样的:
If-None-Match:“5d8c72a5edda8d6a:3239″
如果ETag没改变,则返回状态304。即: 在客户端发出请求后,HttpReponse Header中包含Etag:“5d8c72a5edda8d6a:3239″标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次需要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问得到的Etag:“5d8c72a5edda8d6a:3239″标识。
If-None-Match:“5d8c72a5edda8d6a:3239“
这样,Client端等于Cache了两份,服务器端就会比对2者的etag。如果If-None-Match为False,不返回200,返回304(Not Modified) Response。
3、Expires给出的日期/时间后,被响应认为是过时。如 Expires:Thu, 02 Apr 2009 05:14:08 GMT需和Last-Modified结合使用。用于控制请求文件的有效时间,当请求数据在有效期内时客户端浏览器从缓存请求数据而不是服务器端.当缓存中数据失效或过期,才决定从服务器更新数据。
5、Etag和Expires如果服务器端同时设置了Etag和Expires时,Etag原理同样,即与 Last-Modified/Etag 对应的 HttpRequestHeader:If-Modified-Since 和 If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.
6、Last-Modified和Etag分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败. 分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样)
过程如下:1) 客户端请求一个页面(A)。2) 服务器返回页面A,并在给A加上一个Last-Modified/ETag。3) 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。4) 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。5) 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
需要注意:1) Last-Modified和Etag头都是由WebServer发出的HttpReponse Header,WebServer应该同时支持这两种头。2) WebServer发送完Last-Modified/Etag头给客户端后,客户端会缓存这些头;3) 客户端再次发起相同页面的请求时,将分别发送与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;4) 通过上述值到服务器端检查,判断文件是否继续缓存;
7、关于 Cache-Control: max-age=秒 和 ExpiresExpires = 时间,HTTP 1.0 版本,缓存的载止时间,允许客户端在这个时间之前不去检查(发请求)max-age = 秒,HTTP 1.1版本,资源在本地缓存多少秒。如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。
Expires 的一个缺点: 就是返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。
Expires =max-age + “每次下载时的当前的request时间”
所以一旦重新下载的页面后,expires就重新计算一次,但last-modified不会变化.
8、基于nginx配置使用总结分布式系统(有ng-ha 和 应用的负载均衡),最好使用Last-Modified和Expires,把Etag关闭掉。1) 关闭etag
关闭etag, 使用Last-Modified和Expires
2) 配置last-modified(默认开启)和expires
location ~.*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; }location ~.*\.(js|css)?$ { expires 12h; }
对于配置了多个location(upstream)的,可以:
location /filebase/ { root /hskj/file/; autoindex on; if ($request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx)$){ add_header Content-Disposition: 'attachment;'; } if ($request_filename ~* ^.*?\.(gif|jpg|jpeg|png|bmp|swf)$){ expires 30d; } if ($request_filename ~* ^.*?\.(js|css)$){ expires 12h; }}
效果如下:
这里顺便看一个配置实例: nginx设置不使用缓存 add_header Cache-Control no-cache
运维案例分享: Nginx增加缓存控制字段cache-control 下面是开发部门同事发过来的配置需求: 1) 禁用html文件缓存,即cache control设置为no-cache; 2) 对于js,图片,css,字体等,设置max-age=2592000. 也就是30天;
针对上面的案例需求, 操作记录如下:1) 本案中在实际场景中, 有LB层. LB层的nginx配置不需要配置, 这里只是粘贴下负载配置:
2) 缓存控制字段cache-control的配置要放在后端两台真实服务器172.16.50.73和172.16.50.74上.a) 172.16.60.73 (即fvtkevin-dmz01.kevin.com)服务器上缓存控制字段cache-control的配置如下:
[root@fvtkevin-dmz01 ~]# cat /data/nginx/conf/vhosts/fvtkevin-web01.kevin.com.conf server { listen 80; server_name fvtkevin-dmz01.kevin.com; access_log /data/nginx/logs/fvtkevin-dmz01.kevin.com-access.log main; error_log /data/nginx/logs/fvtkevin-dmz01.kevin.com-error.log; location / { root /data/web/kevin; index index.php index.html index.htm; } location ~ \.(css|js|gif|jpg|jpeg|png|bmp|swf|ttf|woff|otf|ttc|pfa)$ { root /data/web/kevin; expires 30d; } location ~ \.(html|htm)$ { root /data/web/kevin; add_header Cache-Control no-cache; } location /document/ { alias /data/web/document/; } location ~ \.(css|js|gif|jpg|jpeg|png|bmp|swf|ttf|woff|otf|ttc|pfa)$ { root /data/web/document; expires 30d; } location ~ \.(html|htm)$ { root /data/web/document; add_header Cache-Control no-cache; } }
b) 172.16.60.74 (即fvtkevin-dmz02.kevin.com)服务器上缓存控制字段cache-control的配置如下:
[root@fvtkevin-dmz02 ~]# cat /data/nginx/conf/vhosts/fvtkevin-web02.kevin.com.conf server { listen 80; server_name fvtkevin-web02.kevin.com; access_log /data/nginx/logs/fvtkevin-web02.kevin.com-access.log main; error_log /data/nginx/logs/fvtkevin-web02.kevin.com-error.log; location / { root /data/web/kevin; index index.php index.html index.htm; } location ~ \.(css|js|gif|jpg|jpeg|png|bmp|swf|ttf|woff|otf|ttc|pfa)$ { root /data/web/kevin; expires 30d; } location ~ \.(html|htm)$ { root /data/web/kevin; add_header Cache-Control no-cache; } location /document/ { alias /data/web/document/; } location ~ \.(css|js|gif|jpg|jpeg|png|bmp|swf|ttf|woff|otf|ttc|pfa)$ { root /data/web/document; expires 30d; } location ~ \.(html|htm)$ { root /data/web/document; add_header Cache-Control no-cache; } }
发表评论
暂时没有评论,来抢沙发吧~