web 缓存
一、什么是 web 缓存
Web 缓存是指一个 Web 资源(如 html 页面,图片,js,数据等)存在于 Web 服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的 URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个 URL 地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。
二、web 缓存的作用
- 减少网络带宽消耗
- 降低服务器压力
- 减少服务器压力
- 减少网络延迟,加快页面打开速度
三、web 缓存的类型
web 缓存可以分为
3.1 数据库缓存
Web 应用,特别是 SNS 类型的应用,往往关系比较复杂,数据库表繁多,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。比如常用的缓存方案有 memcached redist 等。
3.2 CDN 缓存
CDN 缓存,也叫网关缓存、反向代理缓存。CDN 缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。浏览器先向 CDN 网关发起 web 请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存没法共享,但却拥有更好的处扩展性。
3.3 代理服务器缓存
代理服务器缓存是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起 web 请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。
3.4 浏览器缓存
每个浏览器都实现了 HTTP 缓存,我们通过浏览器使用 HTTP 协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作
3.5 应用层缓存
应用层缓存是指我们在代码层面上做的缓存。通过代码逻辑,把曾经请求过的数据或资源等,缓存起来,再次需要数据时通过逻辑上的处理选择可用的缓存的数据。
今天我们主要讨论和前端密切想着的浏览器 HTTP 缓存机制。浏览器 HTTP 缓存可以分为强缓存和协商缓存。强缓存和协商缓存最大区别是:强缓存命中的话不会发请求到服务器(比如 chrome 中的 200 from memory cache),协商缓存一定会发请求到服务器,通过资源的请求首部字段难资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的实体,而是通知客户端可以从缓存中加载这个资源(304 not modifend)。流程图如下:
四、http 缓存相关参数
4.1 http 报文中与缓存相关的首部字段
- 通用首部字段(就是请求报文和响应都能用上的字段)
字段名称 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Pragma | http1.0 的旧社会遗留物,值为“no-cache”时禁用缓存 |
- Cache-Control 和浏览器相关的命令
指令 | 参数 | 说明 |
---|---|---|
private | 无 | 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它) |
public | 可省略 | 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存 |
no-cache | 可省略 | 缓存前必需确认其有效性 |
no-store | 无 | 不缓存请求或响应的任何内容 |
max-age=[s] | 必需 | 响应的最大值 |
max-age
(单位为 s)设置缓存的存在时间,相对于发送请求的时间。只有响应报文首部设置 Cache-Control 为非 0 的 max-age 或者设置了大于请求日期的 Expires(下文会讲)才有可能命中强缓存。当满足这个条件,同时响应报文首部中 Cache-Control 不存在 no-cache、no-store 且请求报文首部不存在 Pragma 字段,才会真正命中强缓存。以下所有图片均为刷新(command+R)的截图。no-cache
表示请求必须先与服务器确认缓存的有效性,如果有效才能使用缓存(协商缓存),无论是响应报文首部还是请求报文首部出现这个字段均一定不会命中强缓存。Chrome 硬性重新加载(Command+shift+R)会在请求的首部加上 Pragma:no-cache 和 Cache-Control:no-cache。no-store
表示禁止浏览器以及所有中间缓存存储任何版本的返回响应,一定不会出现强缓存和协商缓存,适合个人隐私数据或者经济类数据。public
表明响应可以被浏览器、CDN 等等缓存。private
响应只作为私有的缓存,不能被 CDN 等缓存。如果要求 HTTP 认证,响应会自动设置为 private。
- 请求首部字段
字段名称 | 说明 |
---|---|
if-Match | 比较 ETag 是否一致 |
if-None-Match | 比较 ETag 是否不一致 |
if-Modified-Since | 比较资源最后更新的时间是否一致 |
if-UnModified-Since | 比较资源最后更新的时间是否不一致 |
- 响应首部字段
字段名称 | 说明 |
---|---|
ETag | 资源的匹配信息 |
Expires | http1.0 的遗留物,实体主体过期时间 |
Last-Modifid | 资源的最后一次修改的时间 |
4.2 强制缓存
与强缓存主要是 Pragma、Cache-Control 、Expires
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
注意上面两条指令的作用是不允许浏览器缓存当前页面以及页面上引用的资源,强制浏览器每次请求当前页面时都需要从服务器端获取最新版本。这种方式仅对部分浏览器有效,而且不影响代理服务器对该页面的缓存控制,原因是因为代理服务器并不会去解析页面上的内容。
控制协商缓存
Last-Modified/If-Modified-Since
If-Modified-Since 是一个请求首部字段,并且只能用在 GET 或者 HEAD 请求中。Last-Modified 是一个响应首部字段,包含服务器认定的资源作出修改的日期及时间。当带着 If-Modified-Since 头访问服务器请求资源时,服务器会检查 Last-Modified,如果 Last-Modified 的时间早于或等于 If-Modified-Since 则会返回一个不带主体的 304 响应,否则将重新返回资源。
If-Modified-Since: , :: GMT Last-Modified: , :: GMT
- ETag/If-None-Match
ETag 是一个响应首部字段,它是根据实体内容生成的一段 hash 字符串,标识资源的状态,由服务端产生。If-None-Match 是一个条件式的请求首部。如果请求资源时在请求首部加上这个字段,值为之前服务器端返回的资源上的 ETag,则当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的时候,服务器才会返回带有所请求资源实体的 200 响应,否则服务器会返回不带实体的 304 响应。ETag 优先级比 Last-Modified 高,同时存在时会以 ETag 为准。
If-None-Match: <etag_value>
If-None-Match: <etag_value>, <etag_value>,
If-None-Match: \*
ETag 属性之间的比较采用的是弱比较算法,即两个文件除了每个比特都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。
因为 ETag 的特性,所以相较于 Last-Modified 有一些优势:
- 某些情况下服务器无法获取资源的最后修改时间
- 资源的最后修改时间变了但是内容没变,使用 ETag 可以正确缓存
- 如果资源修改非常频繁,在秒以下的时间进行修改,Last-Modified 只能精确到秒
五、整体流程
用户行为对浏览器的影响
参考资料
- 透过浏览器看 HTTP 缓存
- 浅谈浏览器 http 的缓存机制
- 浏览器 HTTP 缓存机制
- 浏览器缓存知识小结及应用
- 响应速度不给力?解锁正确缓存姿势
- 前端面试之浏览器缓存机制
- 一文搞懂浏览器缓存策略
- 彻底理解浏览器的缓存机制
Web性能优化-DNS缓存
title: Web 性能优化-缓存-DNS 缓存
date: 2018-05-16 13:32:17
categories: 性能
tags:
- DNS
- HttpDNS
- LDNS
缓存梗概
缓存技术几乎存在于网络技术发展的各个角落,从数据库到服务器,从服务器到网络,再从网络到客户端,缓存随处可见。跟前端有关的缓存技术主要有:DNS 缓存,HTTP 缓存,浏览器缓存,HTML5 缓存(localhost/manifest)和 service worker 中的 cache api。
DNS 缓存
当用户在浏览器中输入网址的地址后,浏览器要做的第一件事就是解析 DNS:
(1) 浏览器检查缓存中是否有域名对应的 IP,如果有就结束 DNS 解析过程。浏览器中的 DNS 缓存有时间和大小双重限制,时间一般为几分钟到几个小时不等。DNS 缓存时间过长会导致如果 IP 地址发生变化,无法解析到正确的 IP 地址;时间过短会导致浏览器重复解析域名。
(2) 如果浏览器缓存中没有对应的 IP 地址,浏览器会继续查找操作系统缓存中是否有域名对应的 DNS 解析结果。我们可以通过在操作系统中设置 hosts 文件来设置 IP 与域名的关系。
(3) 如果还没有拿到解析结果,操作系统就会把域名发送给本地区的域名服务器(LDNS),LDNS 通常由互联网服务提供商(ISP)提供,比如电信或者联通。这个域名服务器一般在城市某个角落,并且性能较好,当拿到域名后,首先也是从缓存中查找,看是否有匹配的结果。一般来说,大多数的 DNS 解析到这里就结束了,所以 LDNS/ISP DNS 承担了大部分的域名解析工作。如果缓存中有 IP 地址,就直接返回,并且会被标记为非权威服务器应答。
第三步有一点需要注意的是,如果用户在自己电脑里设置了 DNS,比如 Google 的
8.8.8.8
或者 CloudFlare 新出的1.1.1.1
,将不会通过 ISP DNS 服务器解析。
(4) 如果前面三步还没有命中 DNS 缓存,那只能到 Root Server 域名服务器中请求解析了。根域名服务器拿到请求后,首先判断域名是哪个顶级域名下的,比如 .com
, .cn
, .org
等,全球一共 13 台顶级域名服务器。根域名服务器返回对应的顶级域名服务器(gTLD Server)地址。
(5) 本地域名服务器(LDNS)拿到地址后,向 gTLD Server 发送请求,gTLD 服务器查找并且返回此域名对应的 Name Server 域名服务器地址。这个 Name Server 通常就是用户注册的域名服务器,例如用户在某个域名服务提供商申请的域名,那么这个域名解析任务就由这个域名提供商的服务器来完成。
这个过程的解析方式为递归搜索。比如:
https://movie.lz5z.com
,本地域名服务器首先向顶级域名服务器(com 域)发送请求,com 域名服务器将域名中的二级域lz5z
的 IP 地址返回给 LDNS,LDNS 再向二级域名服务器发送请求进行查询,之后不断重复直到 LDNS 得到最终的查询结果。
(6) Name Server 域名服务器会查询存储的域名和 IP 的映射关系表,在正常情况下都根据域名得到目标 IP 地址,连同一个 TTL 值返回给 LDNS。LDNS 会缓存这个域名和 IP 的对应关系,缓存时间由 TTL 值控制。LDNS 会把解析结果返回给用户,DNS 解析结束。
清除 DNS 缓存
(1) chrome: chrome://net-internals/#dns
(2) 本地 DNS :Windows: ipconfig /flushdns
; Linux 和 mac 根据不同的版本有不同的方式
减少 DNS 解析我们能做什么?
(1) 减少 DNS 查询,避免重定向。
(2) DNS 预解析:
- 可以通过 meta 信息告诉浏览器,页面需要做 DNS 预解析。
<meta http-equiv="x-dns-prefetch-control" content="on" />
- 通过 link 标签强制 DNS 预解析
<link rel="dns-prefetch" href="https://lz5z.com" />
(3) 域名发散/域名收敛
- 域名发散
PC 端因为浏览器有域名并发请求限制(chrome 为 6 个),也就是同一时间,浏览器最多向同一个域名发送 6 个请求,因此 PC 端使用域名发散策略,将 http 静态资源放入多个域名/子域名中,以保证资源更快加载。常见的办法为使用 cdn。
- 域名收敛
将静态资源放在同一个域名下,减少 DNS 解析的开销。域名收敛是移动互联网时代的产物,在 LDNS 没有缓存的情况下,DNS 解析占据一个请求的大多数时间,因此,采用尽可能少的域名对整个页面加载速度有显著的提高。
(4) HttpDNS
DNS 请求使用的是 UDP 协议,虽然没有 TCP 三次握手的开销,但是可能导致弱网环境下(2G,3G)数据丢失的问题。还记得之前Web 性能优化-页面重绘和回流(重排)中提到的 Google 1s 终端首屏渲染标准,假如 DNS 解析出现问题,那可能几秒甚至几十秒都首屏不了了。而且国内牛 X 的运营商的品质你也是知道的,随便劫持一下 DNS 就让你的 web 应用不见天日。
为了应对以上两个问题,HttpDNS 应运而生,原理也非常简单,将 DNS 这种容易被劫持的协议,转而使用 HTTP 协议请求 Domain 与 IP 地址之间的映射。获得正确的 IP 地址后,就不用担心 ISP 篡改数据了。
国内腾讯云和阿里云都有相应的解决方案
Google 的方案则更近一步,使用 https 协议。