由于之前找工作,刚来上海挺多事,些久没写博客;至此打算新开一个 “学习录” 系列(以读书笔记和实战心得为主),记录自己 Java 学习路上的收获,共勉。
以 《深入分析 Java Web 技术内幕》 第一章 深入 Web 请求过程的内容为参考,此篇讲解游览器缓存、DNS 域名解析的过程和 CDN 工作机制。
游览器缓存
缓存可以减少游览器向服务器请求资源的次数,减少网络延时,加快页面响应速度,减少服务器压力。下图中 size 不为 0 的请求就是没有使用缓存。
Memory Cache
会将资源暂时缓存到内存中,在关闭游览器后会释放掉这部分内存空间。受限于计算机内存的大小,当内存使用率高的时候,资源大概率会被缓存到 Disk Cache
,它可以长时效的在硬盘中缓存资源。
Cache-Control / Pragma
我们在游览一个页面时发现有异常,通常考虑的就是是不是游览器做的缓存,这个时候可以按 Ctrl + F5 来重新请求到没有缓存的页面。这个组合键会直接向目标 URL 发送请求,而不会使用游览器缓存的数据;它会在 HTTP 的请求头中增加一些请求头,告诉服务器我们要获取最新的数据而不是缓存(以此也可以跳过前端部署的缓存服务器)。
对 HTTP 请求头不太熟悉的同学可以先参考下我的计网学习笔记:Net:计算机网络读书笔记。
使用 Ctrl + F5 组合键后在 HTTP 请求头中增加了两项 Pragma:no-cache
和 Cache-Control:no-cache
,其字段可选值如下表所示:
可选值 | 说明 |
---|---|
Private | 所有内容都将被缓存,在响应头中设置 |
Private | 内容只缓存到私有缓存中,在响应头中设置 |
no-cache | 所有内容都不会被缓存,在请求头和响应头中设置 |
no-store | 所有内容都不会被缓存到缓存或 Internet 临时文件中,在响应头中设置 |
must-revalidation/proxy-revalidation | 如果设置的内容失效,请求必须发送到服务器 / 代理以进行重新验证,在请求头中设置 |
max-age=xxx | 缓存的内容将在 xxx 秒后失效,这个选项只在 HTTP 1.1 中可用,和 Last-Modified 一起使用时优先级较高,在响应头中设置 |
Cache-Control 请求字段被各个游览器支持得较好,而且它的优先级比较高,和其他的一些请求字段(如 Expires)同时出现时,Cache-Control 会覆盖其他字段。
Expires
Expires:Sat,25 Feb 2012 12:22:17 GMT,超过这个时间值后,缓存的内容将失效,也就是游览器在发出请求之前会检查这个页面的这个字段,看该页面是否已经过期了,过期了就重新向服务器发起请求。
Last-Modified / Etag
Last-Modified 一般用于表示一个服务器上的资源的最后修改时间,通过这个最后修改时间可以判断当前请求的资源是否是最新的。
一般服务端在响应头返回一个 Last-Modified:Sat,25 Feb 2012 12:55:04 GMT,游览器再次请求时就增加一个 If-Modified-Since:Sat,25 Feb 2012 12:55:04 GMT
字段,询问当前请求的资源是否是最新的,如果是最新的就返回 304 Not Modified 状态码,告诉游览器是最新的,服务器也不会传输新的数据。
Etag 字段让服务器给每个页面分配一个唯一的编号,通过编号区分当前页面是否是最新的,比 Last-Modified 更加灵活,但是在后端的 Web 服务器有多台时难以处理,因为每个 Web 服务器都要记住网站的所有资源,否则游览器返回这个编号就没有意义了。
强缓存与协商缓存
Cache-Control 与 Expires 都属于强缓存,在缓存时间内不会向服务器发送请求,直接从缓存中读取资源,一旦在服务器的资源文件发送变化,就会导致服务器和游览器文件不一致的问题。
而 Last-Modified 和 Etag 则属于协商缓存,可以很好的解决这个问题。游览器会携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。
DNS 域名解析
我们通常使用 URL 域名来请求网络资源,它需要被解析成 IP 地址才能与远程主机建立连接,如何将域名解析成 IP 地址就属于 DNS 解析的工作范畴了。
对 URL 域名仍不了解的同学可以先阅读下:Web:浅析 URL
域名缓存
当用户在游览器中输入域名并按下回车键后,游览器会先检查缓存中有没有这个域名对应的解析过的 IP 地址,如果没有命中,则会去操作系统的缓存中查找是否有这个域名对应的 DNS 解析结果。用户也可以修改系统文件来修改域名对应的 IP,Windows 下为 C:\\Windows\System32\drivers\etc\hosts
,Linux 下为 /etc/hosts
,域名劫持 就是黑客修改把特定的域名解析到它指定的 IP 地址上,所以 Windows 7 中将 hosts 设置成了只读,防止这个文件被轻易修改。
本机的域名缓存 Windows 下可通过 ipconfig /flushdns
Linux 下 /etc/init.d/nscd restart
来清除缓存,JVM 也会在 InetAddress
类中缓存 DNS 解析结果。
域名解析
如果在本机中仍然无法完成域名的解析,就会真正请求域名服务器。
- 首先会去请求本地区的域名服务器 LDNS,即本地区的互联网应用服务商电信或者联通,它们的域名解析服务器性能都很好,会缓存域名解析结果,80% 的域名解析请求到 LDNS 就结束了,所以 LDNS 承担了主要的域名解析工作。
- 如果 LDNS 没有命中,则会依次去请求 Root Server、gTLD Server,顶级域名服务器会查找并将此域名对应的 Name Server 地址返回给 LDNS。Name Server 就是域名注册时的某个域名服务提供商。
- LDNS 再向 Name Server 发起请求,Name Server 会查询存储的域名和 IP 的映射关系表,连同一个 TTL 值一起返回给 LDNS,LDNS 会缓存这个域名和 IP 的对应关系,缓存时间由 TTL 值控制。
- 最后,LDNS 将解析结果返回给用户,用户根据 TTL 值缓存在本地系统缓存中,域名解析过程结束。
跟踪域名解析过程
Windows 和 Linux 下都可以使用 nslookup
来查询域名的解析结果,Linux 下可用 dig
查询 DNS 的解析过程。
CNAME
为 Canonical Name(别名解析),可以为一个域名设置一个或者多个别名(方便 CDN 配置)。A 为 Address 为域名对应的 IP 地址。
CDN 工作机制
CDN 全称 Content Delivery Network,它将网站的内容发布到最接近用户的网络“边缘”,使用户可以 就近 取得所需的内容,提高用户访问网站的响应速度。
CDN 主要缓存网站中的静态数据,如 CSS、JS、图片和静态页面等数据,
CDN 架构下,当用户发起请求,经迭代解析后 LDNS 将收到域名的注册服务器地址,而公司的 DNS 解析服务器会把它重新 CNAME 到 CDN 全局中的 DNS 负载均衡服务器,再由 GTM 根据是哪个地方的访问用户来分配离这个用户最近的 CDN 节点。
如果 CDN 节点中的请求数据不存在,则会回到源站去获取这个文件,然后再返回给用户。