从浏览器输入url 开始(一) 检查缓存、解析URL、DNS查询

454 阅读7分钟

本文参考链接:

fecommunity.github.io/front-end-i… www.dailichun.com/2018/03/12/… zhuanlan.zhihu.com/p/80551769

小林coding的图解网络

〇、 在浏览器地址栏输入 url

一、浏览器检查缓存

浏览器查看是否有请求资源的强缓存

  • 如果请求资源在缓存中,且没有过期,跳转到解析步骤。
  • 如果资源未缓存,发起新请求

1 HTTP 缓存技术

HTTP 缓存技术是一项提升HTTP性能的方法,对于一些重复性的HTTP请求,每次获得的数据都是一样的,将这些数据缓存到本地,就可以直接读取本地的数据,不必通过网络获取服务器响应。

HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存

1.1 强制缓存

强制缓存: 强缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存。浏览器决定是否使用缓存。

强制缓存的头部字段:

  • Cache-Control: 相对时间(优先级更高)
  • Expires: 绝对时间

强制缓存的实现过程:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control

1.2 协商缓存

协商缓存: 配合强缓存中Cache-Control使用,在未能命中强缓存时,且存在协商缓存头部,那么客户端将于服务端进行协商,通过协商结果判断是否使用本地缓存。

头部字段:

  1. 请求头部中的 If-Modified-Since 响应头部中的 Last-Modified 
  • 响应头部中的 Last-Modified:标示这个响应资源的最后修改时间
  • 请求头部中的 If-Modified-Since:当资源过期了,发现响应头中具有 Last-Modified 声明,则再次发起请求的时候,携带 If-Modified-Since字段,其值为上次响应头部中Last-Modified的值。服务器收到后将If-Modified-Since的值和被请求资源的最后修改时间进行对比,如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。
  1. 请求头部中的 If-None-Match  响应头部中的 ETag 
  • 响应头部中 Etag:唯一标识响应资源;
  • 请求头部中的 If-None-Match:当资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。

Etag的优先级更高: 服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不用在判断 Last-Modified 了,如果 Etag 没有变化,然后再看 Last-Modified。

原因:

  • 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求;
  • 可能有些文件是在秒级以内修改的,If-Modified-Since 能检查到的粒度是秒级的,使用 Etag就能够保证这种需求下客户端在 1 秒内能刷新多次;
  • 有些服务器不能精确获取文件的最后修改时间。

协商缓存和强制缓存的工作流程:

image.png

二、浏览器解析URL

什么是 URL

URL 是英文 Uniform Resource Locator 的简称,中文译为统一资源定位符。

统一资源定位符的标准格式如下:

[协议类型]://[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

统一资源定位符的完整格式如下:

[协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

其中访问凭证信息、端口号、查询、片段ID都属于选填项。

举例:

http://www.example.com:80/path/to/myfile.htmlkey1=value1&key2=value2#SomewhereInTheDocument

http 是协议(protocol),表明浏览器使用何种协议。

www.example.com是域名(Domain Name), 表明正在请求用哪个web服务器。

:80 端口,HTTP 为80, HTTPS 为443,一般可以忽略。

/path/to/myfile.html/ 路径

?key1=value1&key2=value2 参数(parameters),可以执行部分操作。

#SomewhereInTheDocument 锚点(anchor),将到达锚点定义的位置。注意,锚点后面的内容不会发送请求到服务器。

解析 URL

参考链接

  1. 正则表达式解析(太麻烦,暂时先不写)
  2. URL构造函数解析

URL() 构造函数返回一个新创建的 URL 对象,表示由一组参数定义的 URL。如果给定的基本 URL 或生成的 URL 不是有效的 URL 链接,则会抛出一个 TypeError。

语法:new URL(url [, base]);

示例

// 直接使用绝对 URL 地址方式调用
const url = new URL('http://example.com/path/index.html');

// 使用 path 加 base 地址参数的方式调用
const url = new URL('/path/index.html', 'http://example.com');

对URL进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。(组装HTTP请求报文)

image.png

三、DNS 解析

DNS域名解析:将域名网址自动转换为具体的 IP 地址。

参考链接

域名的层级关系

DNS 中的域名都是用句点来分隔的,比如 www.server.com,这里的句点代表了不同层次之间的界限

在域名中,越靠右的位置表示其层级越高

根域是在最顶层,它的下一层就是 com 顶级域,再下面是 server.com。

所以域名的层级关系类似一个树状结构:

  • 根 DNS 服务器
  • 顶级域 DNS 服务器(com)
  • 权威 DNS 服务器(server.com)

image.png

域名解析的工作流程

  1. 浏览器检查自己的缓存-> 查找操作系统的缓存 -> 检查本机域名文件hosts -> DNS查询
  2. 客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器
  3. 本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。
  4. 根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理,我给你 .com 顶级域名服务器地址给你,你去问问它吧。”
  5. 本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server.com 的 IP 地址吗?”
  6. 顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。
  7. 本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
  8. 权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
  9. 本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

image.png

参考来自 zhuanlan.zhihu.com/p/80551769