从输入URL到页面加载完成期间经历了什么?

作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等。

本文将更深入的研究当你输入一个网址的时候,后台到底发生了一件件什么样的事~

整个过程大致的的流程是:

  1. 在浏览器地址栏输入某个网站的URL
  2. 浏览器通过DNS服务,查询域名的IP地址(浏览器缓存-->操作系统hosts缓存--->路由缓存—>本地域名服务器—>根域名服务器—>顶级域名服务器—>一级域名服务器...,注意图中箭头的含义是上一步查询失败后才会继续下一步,如果上一步直接查询到了,那就直接返回了)
  3. 发起TCP三次握手,建立连接
  4. TCP建立成功后浏览器向服务器发送HTTP请求
  5. 服务器响应HTTP请求,返回HTML页面
  6. 断开TCP连接(四次挥手)
  7. 浏览器解析HTML代码,请求js,css等资源,最后进行页面渲染,呈现给用户

1、在浏览器地址栏输入某个网站的URL

在一个网络中,不同计算机拥有的 ip 地址都是唯一的。提供网页的服务器也是一台计算机,所以同样拥有唯一的一个 ip。

比如百度的某一台服务器 ip 为 111.13.101.208,你完全可以通过 111.13.101.208:80 去访问百度的首页。但如果你还想访问腾讯、淘宝等其他网站呢?

显然以 ip 方式去访问一个网站是很费劲的。就像我们说天安门在哪的时候不会说天安门在经纬多少多少度一样,而是以人话说在北京哪哪哪。

所以,我们同样以别名的方式去记住每一个网站。而这就是 DNS 服务器干的活。

我们在浏览器输入的是一个,人能够轻松记住的域名网址。当我们回车的时候 DNS 服务器就会去找该域名网址在网络中对应的 ip 地址,称之为解析域名。

2、浏览器通过DNS服务,查询域名的IP地址

导航的第一步是通过访问的域名找出其IP地址。DNS查找过程如下:

  • 浏览器缓存 – 浏览器会缓存DNS记录一段时间。 有趣的是,操作系统没有告诉浏览器储存DNS记录的时间,这样不同浏览器会储存个自固定的一个时间(2分钟到30分钟不等)。
  • 系统缓存 – 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname),主要去查找了系统中的hosts文件。这样便可获得系统缓存中的记录。
  • 路由器缓存 – 接着,前面的查询请求发向路由器,查看路由器映射表,它一般会有自己的DNS缓存。
  • 本地DNS服务器(提供本地连接的服务商) – 接下来要检查的就是ISP缓存DNS的服务器。在这一般都能找到相应的缓存记录。
  • 递归查询或迭代查询 – DNS 在解析域名的时候有两种方式:递归查询和迭代查询。 本地DNS服务器找不到会将域名发送给其他服务器,进行递归过程迭代过程,首先会发送到根域名服务器去找,返回顶级域名服务器的IP地址,再请求顶级域名服务器IP返回二级域名服务器IP,再请求二级域名服务器IP返回三级域名服务器IP......直到找到对应的IP地址,返回给浏览器。
    • 递归查询是以本地DNS服务器为中心的,是DNS客户端和服务器之间的查询活动,递归查询的过程中“查询的递交者” 一直在更替,其结果是直接告诉DNS客户端需要查询的网站目标IP地址;
    • 迭代查询则是DNS客户端自己为中心的,是各个服务器和服务器之间的查询活动,迭代查询的过程中“查询的递交者”一直没变化,其结果是间接告诉DNS客户端另一个DNS服务器的地址。

DNS递归查询或迭代查询如下图所示:

扩展阅读

什么是DNS劫持? 什么是301重定向?301重定向设置教程 电脑上不了网将DNS改为114.114.114.114或8.8.8.8可以解决或加快网速的原理是什么? 局域网 IP 和公网 IP 有何差别? 根域名服务器的作用是什么?全球 13 组根域名服务器中有 10 组在美国,意味着什么? 递归和迭代的区别?

3、浏览器发起TCP三次握手,建立TCP连接

拿到IP地址后的浏览器很开心,终于可以有目的的去联系远方的“朋友”了,此时作用于传输层的TCP协议向远端服务器发起连接请求,此举称为三次握手

(1)客户端->服务器:你好,我想跟你连接可以吗?(SYN=1,seq=x)

(2)服务器->客户端:可以,你确定要连接是吧?(SYN=1,ACK=1,ack=x+1,seq=y)

(3)客户端->服务器:确定,我们连接吧!(ACK=1,ack=y+1,seq=x+1)

4、TCP建立成功后浏览器向服务器发送HTTP请求

OK,连接上了,传输吧,这时就需要将用户输入的地址封装成HTTP Request请求报文,发送到服务器,服务器收到请求后会发出应答,即响应数据。

HTTP请求报文格式:请求行+请求头+空行+消息体,请求行包括请求方式(GET/POST/DELETE/PUT)、请求资源路径(URL)、HTTP版本号;

使用Wireshark抓包分析:

5、服务器响应HTTP请求,返回HTML页面

HTTP响应报文格式:状态行+响应头+空行+消息体,状态行包括HTTP版本号、状态码、状态说明

使用Wireshark抓包分析:

6、断开TCP连接(四次挥手)

传也传完了,那咱们断开连接吧!

(1)客户端->服务器:好了,咱们断开吧(FIN=1,seq=u)

(2)服务器->客户端:行,等我稍微检查一下还有没有要发你的数据(ACK=1,ack=u+1,seq=v)

(3)服务器->客户端:可以了,咱们断开吧,拜拜(FIN=1,ACK=1,ack=u+1,seq=w)

(4)客户端->服务器:好的,再会,拜拜(ACK=1,ack=w+1,seq=u+1)

7、浏览器解析HTML代码,请求js,css等资源,最后进行页面渲染,呈现给用户

浏览器获取文件后开始利用内核解析了,解析过程中也会出现一些HTTP请求请求一些资源,如js,css等文件,将这些文件下载到本地。浏览器解析HTML文件时会自上而下,起初产生一个DOM树,解析CSS之后产生CSS规树,后将两树进行融合,合成为渲染层,最后调用操作系统的Native GUI的API绘制。

浏览器是多进程的,浏览器能够运行是因为系统给它的进程分配了资源,每打开一个Tab页就相当于创建了一个独立的浏览器进程。浏览器主要包含以下进程:

(1)浏览器主进程,负责协调主控,只有一个
  • 负责浏览器页面显示,用户交互,如前进后退等
  • 负责各个页面的管理、创建和销毁进程
  • 网络资源的管理下载等
(2)第三方插件进程,每种类型插件对应一个进程,使用时才创建
(3)GPU进程,最多一个,用于3D绘制等
(4)浏览器渲染进程(浏览器内核),内部是多线程的,主要用于页面渲染、脚本执行、事件处理等

重点介绍浏览器内核即渲染进程,页面的渲染、JS的执行、事件的循环都在这个进程内进行。浏览器内核是多线程的,主要包含以下线程:

1、GUI渲染线程
  • 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
  • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
  • GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结),GUI更新会被保存到一个队列中等JS引擎空闲时立即被执行。
2、JS引擎线程(JS内核)
  • 负责处理JavaScript脚本程序
  • JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页上只有一个JS线程在运行JS程序
  • JS引擎线程与GUI渲染线程是互斥的,因此如果JS执行时间过长会造成页面渲染不连贯,导致页面渲染加载阻塞。
3、事件触发线程
  • 用来控制事件循环
  • 当JS引擎执行代码块如setTimeOut时(也可能来自浏览器内核的其它线程,如鼠标点击、ajax异步请求等),会将对应任务添加到事件线程中
  • 符合条件的事件出发时,该线程会把事件添加到待处理的队列队尾,等待JS引擎处理
4、定时触发器线程
5、异步http请求线程

JS运行机制分析

  • JS分为同步任务和异步任务
  • 同步任务都在主线程上执行,形成一个执行栈
  • 主线程外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果就在任务队列中放置一个事件
  • 执行栈中的所有同步任务执行完毕,系统会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。

参考

留言区

还能输入500个字符