nginx 简单实践:Web 缓存【nginx 实践系列之三】
〇、前言
本文为 nginx 简单实践系列文章之二,主要简单实践了两个内容:正向代理、反向代理,仅供参考。
关于 Nginx 基础,以及安装和配置详解,可以参考博主过往文章:
https://www.cnblogs.com/hnzhengfy/p/Nginx.html
一、强制缓存、协商缓存
1.1 强制缓存(强缓存)
强制缓存指的是当用户请求一个资源时,浏览器直接从本地缓存中读取数据而不向服务器发送任何请求。
这种缓存机制主要依赖于 HTTP 响应头中的 Cache-Control 和 Expires 字段。
Expires:这是 HTTP/1.0 引入的一个头部字段,它指定了资源在该时间之前被认为是有效的。例如,Expires: Wed, 21 Oct 2025 07:28:00 GMT。但是,由于 Expires 依赖于客户端的时间设置,可能出现非预期的状况。
Cache-Control:HTTP/1.1 引入了更为强大的 Cache-Control 头部,提供了更多控制缓存行为的指令,如下表:
| 值 | 含义 |
| no-store | 禁止缓存(强缓存和协商缓存),客户端不存储任何值 |
| no-cache | 禁止强缓存,需要重写验证(可以理解为禁止强缓存,启用协商缓存) |
| private | 私有缓存,禁止中间人(比如 CDN 等代理缓存) |
| public | 共享缓存,允许中间人缓存 |
| max-age | 资源可以被缓存的最大时间,单位:秒,是一个相对时间,优先级高于 Expires,示例(缓存两分钟):max-age=120 |
| s-maxage | 用于共享缓存,单位:秒,如果在其有效期内,不去访问 CDN 等。s-maxage 会覆盖 max-age 和 Expires |
| must-revalidate | 缓存使用陈旧资源时,必需先验证状态 |
强缓存的优势:
- 减少网络请求:浏览器可以直接使用本地缓存中的资源,无需再次向服务器发起请求,从而减少了网络往返次数,提升了页面加载速度。
- 降低服务器负载:由于减少了对服务器的请求,服务器的压力也随之减小,有助于提高服务器的整体性能和稳定性。
- 节省带宽:避免了重复下载相同的数据,节省了用户的网络带宽,尤其对于移动设备或在带宽有限的情况下尤为重要。
- 提升用户体验:加速页面加载时间,尤其是对于静态资源如图片、CSS 和 JavaScript 文件等,能够显著改善用户体验。
强缓存的劣势:
- 可能展示过期内容:如果缓存策略设置不当,可能会导致用户看到过期的内容。例如,如果资源更新了但缓存尚未过期,用户将继续看到旧版本的资源,直到缓存失效。
- 缺乏灵活性:强制缓存的时间是预先设定好的,无法根据实际情况动态调整。这意味着即使服务器上的资源已经更新,只要客户端缓存未过期,用户就看不到最新的内容。
- 需要精确配置:正确配置缓存策略需要一定的专业知识,尤其是在处理不同类型的资源时(如静态资源与动态生成的内容),错误的配置可能导致缓存命中率低或频繁的缓存失效问题。
- 难以应对紧急更新:在某些情况下,比如发现安全漏洞或需要立即推送的重要更新,强制缓存可能会成为障碍,因为用户可能长时间看不到最新的修复或更新。
在实际应用中,通常会结合使用强制缓存和协商缓存,以达到既快速又可靠的缓存效果。例如,对于不经常变化的静态资源可以使用较长的缓存时间,而对于可能频繁更新的内容则采用较短的缓存时间或者使用协商缓存机制。
1.2 协商缓存
协商缓存(也称为验证缓存)是一种 HTTP 缓存机制,它在强制缓存失效后使用。
在这种情况下,浏览器会携带特定的缓存标识(如 ETag 或 Last-Modified)向服务器发送请求,询问资源是否有更新。如果资源没有变化,服务器将返回一个 304 Not Modified 状态码,指示客户端可以继续使用本地缓存;如果资源有变化,则服务器返回新的资源。


协商缓存主要依赖于 值标记法(ETag、If-None-Match)和比较最后修改时间法(Last-Modified、If-Modified-Since)两种头部字段来实现。
值标记法(ETag、If-None-Match):
- ETag:由服务器生成并返回给客户端的一个唯一标识符,通常基于文件内容的哈希值。每当资源发生变化时,ETag 也会随之改变。
- If-None-Match:当客户端再次请求资源时,会在请求头中带上之前获取的 ETag 值。服务器收到请求后,会比较当前资源的 ETag 与请求中的 If-None-Match 值。如果两者相同,说明资源未变,服务器返回 304 Not Modified(未更改,缓存可用);否则,服务器返回新的资源及其新的 ETag。
比较最后修改时间法(Last-Modified、If-Modified-Since):
- Last-Modified:服务器告诉客户端资源最后修改的时间。例如,Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT。
- If-Modified-Since:客户端在后续请求中会带上这个时间戳。服务器接收到请求后,检查资源的最后修改时间 Last-Modified 是否晚于 If-Modified-Since 指定的时间。如果是,服务器返回新资源;如果不是,服务器返回 304 Not Modified(未更改,缓存可用)。
协商缓存的优势:
- 确保数据新鲜度:通过与服务器进行验证,确保用户始终能够获取到最新的资源,避免了因缓存过期而看不到最新内容的问题。
- 节省带宽:如果资源没有变化,服务器只需返回一个小的 304 Not Modified 响应,而不需要重新传输整个资源,从而节省了带宽。
- 灵活性:相比强制缓存,协商缓存提供了更高的灵活性,允许根据实际资源的变化情况动态调整缓存策略。
协商缓存的劣势:
- 增加网络开销:即使资源没有变化,每次请求都需要与服务器进行一次验证,这增加了少量的网络开销。
- 复杂性较高:需要正确设置和管理 ETag、Last-Modified 等头部字段,增加了配置和维护的复杂性。
- 性能略逊于强缓存:虽然节省了带宽,但相比直接从缓存中读取资源,协商缓存仍需要一次网络往返,因此性能稍逊一筹。
通过合理地结合使用强制缓存和协商缓存,可以根据不同的需求优化网站的性能和用户体验。
对于不常变化的静态资源,可以优先考虑使用强制缓存;而对于那些需要保持最新状态的资源,则应采用协商缓存。
二、通过 nginx 配置实现 Web 缓存
2.1 强缓存的实现:Cache-Control
Expires 可能造成误差,因此不再进行示例测试。由于 Expires 配置是后端返回给客户端的一个时间戳,取自服务器时间,当客户端发送请求时,采用客户端的当前时间进行比较,如果两边时间有误差就会造成数据不一致的异常情况。
Cache-Control 的优先级高于 Expires,Expires 是 http1.0 的产物,而 Cache-Control 是 http1.1 的产物,两者同时存在的时候 Expire 会被 Cache-Control 的 max-age 覆盖,在不支持 http1.1 的情况下可能就需要 Expires 来保持兼容。
nginx 配置示例:
server {
listen 8888;
server_name www.testczzj.com;
#charset utf-8;
#charset koi8-r;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
add_header Cache-Control max-age=500; # 缓存有效期配置为 500 秒
proxy_pass http://www.testczzj.com:5000;
}
}
如下图请求结果:(响应头中包含了强缓存配置项 Cache-Control)

如下图针对文件 bootstrap.min.css 的二次请求详情:

2.2 协商缓存实现:Cache-Control:no-cache
客户端每次请求都会向服务端发起,若没更新则返回 304,若有更新就正常返回 200。
nginx 配置,其实就是修改了 Cache-Control 这个配置项:
server {
listen 8888;
server_name www.testczzj.com;
#charset utf-8;
#charset koi8-r;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
add_header Cache-Control no-cache; # 配置为协商缓存
proxy_pass http://www.testczzj.com:5000;
}
}
如下图,首次加载是从服务器拉取全部数据,待第二次刷新时,在服务端数据未发生变更的情况下,返回 304,效率大大提高:

如下图针对文件 bootstrap.min.css 的二次请求详情:

2.3 无缓存:Cache-Control:no-store
nginx 配置如下:
server {
listen 8888;
server_name www.testczzj.com;
#charset utf-8;
#charset koi8-r;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
add_header Cache-Control no-store; # 配置无缓存
proxy_pass http://www.testczzj.com:5000;
}
}
每次请求都是从服务端取数据,如下图:

参考:https://blog.csdn.net/JarryNeverGiveup/article/details/131060939
https://segmentfault.com/a/1190000040748678
nginx 简单实践:Web 缓存【nginx 实践系列之三】的更多相关文章
- 用代码来实践Web缓存
Web缓存是可以自动保存常见文档副本的HTTP设备.当Web请求抵达缓存时,如果本地有"已缓存的副本",就可以从本地存储设备而不是原始服务器中提取这个文档. 上面是<HTTP ...
- nginx的web缓存服务环境部署记录
web缓存位于内容源Web服务器和客户端之间,当用户访问一个URL时,Web缓存服务器会去后端Web源服务器取回要输出的内容,然后,当下一个请求到来时,如果访问的是相同的URL,Web缓存服务器直接输 ...
- Nginx简单总结
NGINX简单总结 特点总结 nginx有一个master进程和多个worker进程,master进程是主要用来管理worker进程,管理的内容包括以下内容:接收来自外界的信号,向各个woker进程发 ...
- Nginx部署及Web基础
目录 Nginx部署及Web基础 Nginx简介 Nginx特点 Web服务 Web服务器软件 Nginx和Apache对比图 部署Nginx yum安装 编译安装 平滑增加Nginx模块 Nginx ...
- Nginx之(一)Nginx是什么
Nginx("engine x")是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大 ...
- 基于nginx+lua+redis高性能api应用实践
基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...
- Nginx配置支持https协议-应用实践
Nginx配置支持https协议-应用实践 https简介 HTTPS 是运行在 TLS/SSL 之上的 HTTP,与普通的 HTTP 相比,在数据传输的安全性上有很大的提升. TLS是传输层安全协议 ...
- Nginx+Memcached+Tomcat集群配置实践(Sticky Session)
准备工作 创建一个简单的web应用,名为session.其中有两个页面,分别如下所示: 页面login.jsp <%@ page language="java" conten ...
- nginx高性能WEB服务器系列之三版本升级
nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...
- Nginx反代服务器基础配置实践案例
转载自:https://www.bilibili.com/read/cv16149433?spm_id_from=333.999.0.0 方式1: 轮询 RR(默认轮询)每个请求按时间顺序逐一分配到不 ...
随机推荐
- php调试工具之firePHP
让PHP可以像js一样利用浏览器的控制台调试代码 ------- FirePHP(http://www.firephp.org/) 1. 安装FirePHP插件 在Chrome浏览器的应用商店中,搜 ...
- android emulator 设置代理
android emulator 设置代理 由于开发的 app 需要访问 google 服务,那么跑虚拟机的时候就需要设置网络代理,试了几种方法都没成功,记录一下 因为已知我开发电脑的代理地址和端口, ...
- IOS多线程之NSOperation(3)
IOS多线程之NSOperation(3) 操作优先级和服务质量 可以通过QueuePriority属性来设置operation在队列中的执行优先级 public enum QueuePriority ...
- OpenType 字体文件组织结构
OpenType 字体文件结构 OpenType 字体的组织 https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organi ...
- 【MyBatis】学习笔记10:添加功能获取自增的主键
[Mybatis]学习笔记01:连接数据库,实现增删改 [Mybatis]学习笔记02:实现简单的查 [MyBatis]学习笔记03:配置文件进一步解读(非常重要) [MyBatis]学习笔记04:配 ...
- docker-安装Oracle11g
获取镜像 在线 docker pull oracleinanutshell/oracle-xe-11g 离线 tar包下载:链接: https://pan.baidu.com/s/1bRp6mSq ...
- Spirng Data JPA 之Specification中and、or的使用
项目中,有的地方存值以逗号分隔的方式来存储,但查询的时候是需要满足单个值或者多个值条件查询,因此用到Specification中and.or组合使用,此文用来记录,以防后用. 描述:parentCod ...
- Qt音视频开发39-海康sdk回调拿到数据GPU绘制的实现
一.前言 采用海康的sdk做开发,最简单最容易的方式就是传入句柄(windows和linux都支持/很多人以为只有windows才支持)即可,这种方式不用自己处理绘制,全部交给了sdk去处理,所以cp ...
- 鸿蒙OS创新实践:动态声控话筒开发指南
前言 在鸿蒙OS的生态中,开发者们不断探索和创新,以期为用户带来更丰富的交互体验.最近,我萌生了一个想法:制作一个能够随着声音动态变化的话筒组件.尽管网络上缺乏现成的参考案例,但我决定亲自动手,将这一 ...
- Visual Studio Code启动时总是提示“Code安装似乎损坏。请重新安装。”、标题栏显示“不受支持”等信息的解决办法
我的VSCode一直提示"Code安装似乎损坏.请重新安装."同时标题栏显示"不受支持"就像这样: 反思了一下,应该是我安装的background插件,把vsc ...