在浏览器输入域名看到完整页面背后都发生了什么
  qbian 2020年11月21日 371 3

一 完整流程概览

1.1 概述

本文讲述浏览器域名解析获取IP、请求静态资源时cdn工作原理、获取IP后请求服务端页面时IP是怎么寻址的、请求到达服务器后应用从都有哪些方式获取请求数据、应用层和系统内核之间的数据copy方式、以及浏览器获取到响应页面后,是怎么将html+css+js内容渲染为一个缤纷多彩的页面的。

1.2 DNS/CDN

image.png

1.3 TCP/IP

image.png

二 DNS 工作过程

2.1 解析过程

image.png

  1. 访问www.google.com时,先查询本地机器缓存,没查到后再向本地域名服务器(一般为网络服务商)发起dns请求该域名背后ip是。
  2. 本地域名服务器维护了一张域名与ip地址的映射关系,如果映射关系未查到,本地域名服务器会去根DNS服务器问该域名背后ip是啥,根DNS服务器不解析域名,但是会指明一条道路(顶级域名服务器)告诉你去哪里可以找到解析结果(根据域名后缀)。
  3. 本地域名服务器转而问顶级域名服务器,www.google.com背后的ip是啥?顶级域名服务器收到请求后,会返回负责www.google.com区域的权威域名服务器,说“这个域名他负责的,你去问他吧”。
  4. 本地域名服务器再去问权威域名服务器,权威域名服务器找到www.google.com背后映射的ips后返回给本地域名服务器。
  5. 本地域名服务器解析到www.google.com背后的ips后先进行本地缓存,再将ip地址返回给客户端。
  6. 客户端可以通过ips做简单的全局负载均衡(轮询),权威域名服务器也可以返回cname后的域名,该域名解析服务可以做更复杂的负载均衡(根据请求ip做地域就近机房访问,返回就近的机房ip等)。

2.2 DNS 存在的问题及解决方案

2.2.1 存在的问题

  1. 域名缓存问题:本地域名服务器缓存更新不及时;
  2. 域名转发问题:有些机房的网关配置了网络地址转换,改变了源请求IP地址;
  3. 域名更新问题:双机房容灾的时候,某个机房挂掉,因为域名缓存更新不及时导致请求未及时转发到备用机房;
  4. 解析延迟问题:域名解析过程比较复杂,需要层层递归解析,存在一定的延时;

2.2.2 解决方案

  1. HttpDNS;

三 CDN 工作过程

3.1 工作过程

image.png

  1. CDN可以类比我们在电商网站上购物,买的家电一般由距离你最近的仓库发货,也就是边缘节点,边缘节点数目较多,集群规模较小,一般不会缓存太多东西,所以可能无法命中
  2. 边缘节点未命中的资源请求,会向上到区域节点查找,区域节点存储的数据会更大,缓存的数据也更多,命中的概率也更大一些;
  3. 区域节点如果还是没查询到,就会到数据中心查找,数据中心存储了所有的资源,到数据中心的查询叫回源;
  4. 电商网站物流系统的设计思路也是这样,杭州区的仓库找不到,就去找华中区的仓库,华中区的仓库找不到,就去找南方区域的仓库,最后如果还是没找到,就走总仓库发货;

3.2 CDN 临近节点判断规则

基于DNS的全局负载均衡器,会选择合适的服务节点提供服务,具体选择依据如下:

  1. 根据用户 IP 地址,判断哪一台服务器距用户最近;
  2. 用户所处的运营商;
  3. 根据用户所请求的 URL 中携带的内容名称,判断哪一台服务器上有用户所需的内容;
  4. 查询各个服务器当前的负载情况,判断哪一台服务器尚有服务能力;

四 TCP 滑动窗口

4.1 TCP 报文

image.png

  1. 端口号:用于主机分发给哪个应用;
  2. 序号:用于数据包的排序;
  3. 确认序号:保证不丢包的前提是收到回复;
  4. 状态维护:有始有终,握手挥手;
  5. 窗口大小:流量控制、拥塞控制;

4.2 TCP 滑动窗口

4.2.1 发送方

image.png

右图是发送方的数据结构,为什么要有第三部分和第四部分?这就是我们上面说的流量控制,接收方响应的数据包中有可接收窗口大小(发送未确认+未发送可发送),如果一下把第四部分也发出去,超过了接收方可接收范围,就会触发丢包重传,导致网络拥堵;

4.2.2 接收方

image.png

右图是接收方的数据结构,接收方最大可接收的数据量=接收已确认+等待接收未确认,接收方当前可接收的量=等待接收未确认的量,随着接收已确认的不断变大,可接收的量会不断变小,对应到发送发就是可接收窗口会随着发送已确认的数据变大,可发送的窗口再不断减小;

五 IP 寻址

当一个路由器启动的时候,首先是发现邻居,向邻居 say hello,邻居都回复。然后计算和邻居的距离,发送一个 echo,要求马上返回,除以二就是距离。然后将自己和邻居之间的链路状态包广播出去,发送到整个网络的每个路由器。这样每个路由器都能够收到它和邻居之间的关系的信息。因而,每个路由器都能在自己本地构建一个完整的图,然后针对这个图使用 Dijkstra 算法,找到两点之间的最短路径。

Dijkstra 算法就是找到最短的路径。在一个组织内部,路径最短往往最优。当然有时候可以发现多个最短的路径,可以在这多个路径中进行负载均衡,这常常被称为等价路由,有了等价路由,到一个地方去可以有相同的两个路线,可以分摊流量,也可以结合应用层 LVS 做负载均衡。

六 BIO/NIO/AIO

6.1 BIO

image.png

BIO: 一个socket对应一个thread,阻塞读写。因操作系统不能无限创建线程,所以存在C10K问题。

6.2 NIO

image.png

NIO: 一个selector对应所以socket,通过轮询集合状态改变,去循环判断哪个socket状态改变,触发具体业务事件去处理该socket。因需要selector每次都轮询循环判断具体socket事件变化,存在并发性能问题。

6.3 AIO

image.png

AIO: 操作系统调用epoll_create发放创建epoll对象,epoll对象内部维护了一个红黑树数据结构,每个节点指向一个数据结构,这个结构挂在被监听的socket事件列表中,当一个socket来了一个事件时,可以从这个列表得到epoll对象,并调用callback通知它。这种方式使得监听socket数量增加的时候,效率不会大幅度降低,能够监听socket的数量也非常多,通常为系统设置的进程最大打开文件描述符上限。

七 零拷贝

7.1 四次拷贝

image.png

7.2 三次拷贝

image.png

7.3 两次拷贝(操作系统层面:零拷贝)

image.png

八 浏览器(webkit)页面渲染

image.png

  1. html文档解析:webkit 接收到各种网页或者资源的数据,网页被交给 html 解析器转变成一系列的词语(token),解析器根据词语构建节点(node),形成 dom 树。如果节点是 javascript 代码的话,调用 javascript 引擎解释并执行,javascript 代码可能会修改 dom 树的结构。如果节点需要依赖其他资源,例如图片、css、视频等,调用资源加载器来加载它们,但是它们是异步的,不会阻碍当前 dom 树的继续创建;如果是 javascript 资源 url (没有标记异步),则需要停止当前 dom 树的创建,直到 javascript 的资源加载并被 javascript 引擎执行后才继续 dom 树的创建。
  2. css 文件的解析:css 文件被 css 解释器解释成内部表示结构,css 解释器工作完成之后,在 dom 树上附加解释后的样式信息,这就是 RenderObjcet 树。RenderObjcet 节点在创建的同时,webkit 会根据网页的层次结构创建 RenderLayer 树,同时构建一个虚拟的绘图上下文。
  3. 生成最终绘制的图像:绘制上下文将每个绘图操作桥接到不同的具体实现类,绘图实现类将 2D 图形库或者 3D 图形库绘制的结果保存下来,交给浏览器来同浏览器界面一起显示。

从以上内容可以得出为什么页面在引入 js 的时候最好是放在 body 的最后,而引入 css 的时候却无任何要求。因为 css 在解析时不会修改 dom 树的结构,所以完全可以和 html 的解析同时执行,但是 js 的解释执行却会修改 dom 树的结构,所以 js 的解释执行和 html 的解释执行是阻塞进行的。为了加快 html 页面的显示,最好将 js 的引入放在 body 的最后。

以上就是在浏览器输入域名看到完整页面背后发送的所有事情。

最后一次编辑于 2021年03月10日 3

帅气的大叔

asdfasdfsadfasdfasd

2020-11-27 02:03:45      回复

帅气的大叔

嗯·?

2020-12-02 02:56:54 回复

帅气的大叔 回复:帅气的大叔

嗯?

2020-12-02 02:57:02 回复