What happens when you type a URL into your browser?

从输入一个 URL、按下回车到显示页面,中间发生了什么?这个问题既有广度,又有深度,很能考验一个人的知识体系

网络上有很多资源,非常详细具体地解释了从底层到高层、从硬件到软件的原理。而本文更侧重于在同一个层次讨论浏览器、操作系统、服务器是如何交互的

整体流程

  1. 用户在某个标签页输入 URL 并回车后,浏览器主进程会新开一个网络线程,发起 HTTP 请求
  2. 浏览器会进行 DNS 查询,将域名解析为 IP 地址
  3. 浏览器获得 IP 地址后,向服务器请求建立 TCP 连接
  4. 浏览器向服务器发起 HTTP 请求
  5. 服务器处理请求,返回 HTTP 响应
  6. 浏览器的渲染进程解析并绘制页面
  7. 如果遇到 JS/CSS/图片 等静态资源的引用链接,重复上述过程,向服务器请求这些资源

  

browser

浏览器是多进程的。

浏览器只有一个主进程,又称 Browser 进程,负责创建/管理其他进程、显示浏览器主窗口、下载网络资源等。

每打开一个标签页,就创建了一个独立的浏览器渲染进程。浏览器渲染进程又称为浏览器内核、Renderer 进程,其内部是多线程的,负责页面渲染、脚本执行等。

浏览器的每一个网络请求,都需要主进程开辟一个单独的网络线程去处理。输入 URL 相当于一个网络请求,解析 HTML 时遇到 JS/CSS/图片等静态资源的引用链接,也需要分别请求。

浏览器的渲染流程:

  1. 解析 HTML 文件,构建 DOM 树,同时下载 CSS 等静态资源
  2. CSS 文件下载完成后,解析 CSS 文件,形成 CSSOM 树
  3. DOM 与 CSSOM 合并得到渲染树 Render Tree
  4. 计算渲染树中各个元素的尺寸、位置,这个过程称为回流 Reflow
  5. 浏览器将各个图层的信息发送给 GPU,GPU 绘制页面

进一步阅读:浏览器运行机制

  • 浏览器的多进程模型
  • 浏览器内核的多线程模型
  • GUI 线程、JS 线程的阻塞关系
  • JS 引擎的解析与执行过程
  • JS 单线程模型、事件循环 Event-Loop

server

负载均衡:大型的项目,往往是由多台服务器组成一个集群,以此应对庞大的并发访问量。这种情况下,用户的请求都会指向调度服务器,由调度服务器将请求分发给集群中的某台服务器 A,然后调度服务器会将 A 服务器的 HTTP 响应发送给用户。

此外,后端还会经过安全认证、参数校验、中间件、执行业务代码、访问数据库等一系列操作,才能向用户返回结果。

网络协议

网络协议栈

OSI 七层模型与 TCP/IP 协议栈各层功能与协议

计算机网络

DNS 原理

域名结构

互联网采用了层次树状结构的命名方法。任何一个连接在互联网上的主机或路由器,都有一个唯一的层次结构的名字,即域名。

域名的结构由标号序列组成,各标号之间用点隔开。类似于这样:“….三级域名.二级域名.顶级域名” 。各级域名由其上一级的域名管理机构管理,而最高级的顶级域名则由ICANN进行管理。

域名服务器

互联网上的DNS域名服务器也是按照层次划分的,每一个域名服务器都只对域名体系中的一部分进行管辖。根据域名服务器所起的作用,可以把域名服务器划分为四种不同的类型:

根域名服务器:根域名服务器是最高层次的域名服务器,也是最重要的域名服务器。根域名服务器知道所有顶级域名服务器的域名和 IP地址。如果本地域名服务器无法对域名进行解析,就首先求助于根域名服务器。

顶级域名服务器:顶级域名服务器负责管理在该服务器注册的所有二级域名。当收到 DNS 查询请求时,就给出相应的回答(可能是最后的结果,也可能是下一步需要查询的域名服务器的 IP 地址)。

权威域名服务器:负责一个区的域名服务器。当一个权限域名服务器还不能给出最后的查询回答时,就会告知发出查询请求的DNS客户,下一步应当找哪一个权威域名服务器。

本地域名服务器:本地域名服务器并不属于下图中的树状结构的DNS域名服务器,但是它对域名系统非常重要。当一个主机发出DNS查询请求时,这个查询请求报文就发送给本地域名服务器。每一个互联网服务提供者ISP都可以拥有一个本地域名服务器。

DNS 查询过程

DNS 是应用层的协议,作用是将域名转化为 IP,以供传输层建立 TCP 连接。

整体流程:

  1. 浏览器搜索自身的 DNS 缓存

  2. 搜索操作系统的 DNS 缓存

  3. 读取本地的 host 文件

  4. 路由器缓存:路由器缓存路由器映射表;

  5. 本地 DNS 服务器进行查询:ISP(Internet Service Provider), 是互联网服务提供商的简称。ISP有专门的DNS服务器对应DNS查询请求。

  6. 域服务器发送请求,没找到的话递归到下一级的域服务器继续查找(域服务器递归寻找)。直到找到返回;

  7. 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个 IP 地址即可访问目标Web服务器。

如果本地DNS服务器无法查询到,则根据本地DNS服务器设置的转发器进行查询。若未用转发模式,则迭代查找过程如下图:

在查找过程中,有以下优化点:

  • DNS存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
  • 在域名和 IP 的映射过程中,给了应用基于域名做负载均衡的机会,可以是简单的负载均衡,也可以根据地址和运营商做全局的负载均衡。

TCP连接

TCP 是传输层协议,HTTP 协议通过 TCP 协议发送数据。之所以选择 TCP,是因为 HTTP 对数据的准确性要求高,TCP 能够提供可靠的交付。

首先,判断是不是https的,如果是,则HTTPS其实是HTTP + SSL / TLS 两部分组成,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。

进行三次握手,建立TCP连接。

  1. 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
  2. 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
  3. 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

完成了之后,客户端和服务器端就可以开始传送数据。

关闭TCP连接

  1. 第一次分手:主机1(可以使客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
  2. 第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我”同意”你的关闭请求;
  3. 第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
  4. 第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

SSL 四次握手

SSL 位于传输层和应用层之间,TCP 和 HTTP 之间。SSL 协议的目的是,为通信双方提供一种在不安全的网络环境中,安全地协商一个密钥的方法。

SSL 实现的核心是非对称式密码学。非对称密码包含两个部分:公钥和私钥,一个用作加密,另一个则用作解密。使用其中一个密钥把明文加密后所得的密文,只能用相对应的另一个密钥才能解密得到原本的明文;甚至连最初用来加密的密钥也不能用作解密。

HTTPS 本质上就是 HTTP + SSL。通过 SSL 四次握手过程,客户端和服务端会商定一个共同的随机密钥,用来对称加密。握手结束后,双方都会使用这个约定的随机密钥来加密、解密会话内容,使用的完全是普通的 HTTP 协议。

SSL握手过程

  1. 第一阶段 建立安全能力 包括协议版本 会话Id 密码构件 压缩方法和初始随机数
  2. 第二阶段 服务器发送证书 密钥交换数据和证书请求,最后发送请求-相应阶段的结束信号
  3. 第三阶段 如果有证书请求客户端发送此证书 之后客户端发送密钥交换数据 也可以发送证书验证消息
  4. 第四阶段 变更密码构件和结束握手协议

HTTP 的长连接与短连接

HTTP/1.0 默认使用的是短连接。也就是说,浏览器每请求一个静态资源,就建立一次连接,任务结束就中断连接。

HTTP/1.1 默认使用的是长连接。长连接是指在一个网页打开期间,所有网络请求都使用同一条已经建立的连接。当没有数据发送时,双方需要发检测包以维持此连接。长连接不会永久保持连接,而是有一个保持时间。实现长连接要客户端和服务端都支持长连接。

长连接的优点:TCP 三次握手时会有 1.5 RTT 的延迟,以及建立连接后慢启动(slow-start)特性,当请求频繁时,建立和关闭 TCP 连接会浪费时间和带宽,而重用一条已有的连接性能更好。

长连接的缺点:长连接会占用服务器的资源。

HTTP 2.0

HTTP 2.0 的三大特性是头部压缩、服务端推送、多路复用

HTTP 1.1 允许通过同一个连接发起多个请求。但是由于 HTTP 1.X 使用文本格式传输数据,服务端必须按照客户端请求到来的顺序,串行返回数据。此外,HTTP 1.1 中浏览器会限制同时发起的最大连接数,超过该数量的连接会被阻塞

HTTP 2 引入了多路复用,允许通过同一个连接发起多个请求,并且可以并行传输数据。HTTP 2 使用二进制数据帧作为传输的最小单位,每个标识了自己属于哪个,每个对应一个请求。服务端可以并行地传输数据,而接收端可以根据帧中的顺序标识,自行合并数据。

在 HTTP 1.1 中,由于浏览器限制每个域名下最多同时有 6 个请求,其余请求会被阻塞,因此我们通常使用多个域名(比如 CDN)来提高浏览器的下载速度。HTTP 2 就不再需要这样优化了。

同理,在 HTTP 1.1 中,我们会将多个 JS 文件、CSS 文件等打包成一个文件,将多个小图片合并为雪碧图,目的是减少 HTTP 请求数。HTTP 2 也不需要这样优化了。

HTTP 缓存

浏览器可以将已经请求过的资源(如图片、JS 文件)缓存下来,下次再次请求相同的资源时,直接从缓存读取。

浏览器采用的缓存策略有两种:强制缓存、协商缓存。浏览器根据第一次请求资源时返回的 HTTP 响应头来选择缓存策略。

强制缓存:为资源设置一个过期时间,只要资源没有过期,就读取浏览器的缓存。强制缓存不需要向服务器发起请求,浏览器直接返回 200(from cache)

协商缓存:浏览器携带缓存资源的元信息,向服务器发起请求,由服务器决定是否使用缓存。如果协商缓存生效,服务器返回 304 和 Not Modified;如果协商缓存失效,服务器返回 200 和请求结果。

协商缓存的原理是:服务端根据资源的元信息,判断浏览器缓存的资源在服务器上是否有改动。元信息有两种,一种是资源的上次修改时间,另一种是资源 Hash 值。前者实现简单,但是精确度低,文件修改时间只能以秒记;后者精确度高,但是性能低,需要计算哈希值。