https://segmentfault.com/a/1190000013522717
1.DNS解析
2.tcp连接
3.http请求
4.http返回
5.浏览器解析渲染
6.tcp关闭连接
https://juejin.im/post/5b148a2ce51d4506965908d2
image.png

1.DNS解析

1.1 DNS介绍

 DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。
DNS名称空间的组织方式:5个类别 根、顶级域、二级域、子域、主机名
image.png

1.2 DNS解析过程

就是寻找哪台机器上有你需要的资源。每台机器有固定的IP地址,但是IP地址不方便记忆,网址 => IP地址
DNS查找的顺序:浏览器缓存=>操作系统缓存=>本地host文件=>路由器缓存=>ISP缓存=>顶级DNS服务器/根DNS服务器
主要说下后面两个缓存:
ISP DNS缓存:互联网服务提供商(如中国电信)也会提供DNS服务,比如比较著名的 114.114.114.114,在本地查找不到的情况下,就会向ISP进行查询,ISP会在当前服务器的缓存内查找是否有记录,如果有,则返回这个IP,若没有,则会开始向根域名服务器请求查询。
顶级DNS服务器/根DNS服务器:根域名收到请求后,会判别这个域名(.com)是授权给哪台服务器管理,并返回这个顶级DNS服务器的IP。请求者收到这台顶级DNS的服务器IP后,会向该服务器发起查询,如果该服务器无法解析,该服务器就会返回下一级的DNS服务器IP(google.com),本机继续查找,直到服务器找到(www.google.com)的主机。
下面这张图很完美的解释了这一过程:
image.png
首先在本机域名服务器查找IP地址—>根域名(.)服务器查找—>顶级域名(.com)服务器查找—>域名服务器地址 —>返回本机并缓存,以备下次使用。上述过程是 com—>google.com—>www.google.com,但好像少了根域名服务器查找的过程,其实DNS在实际查找过程中,会自动在域名后面加 . ,真正的过程是 com.—>google.com.—>www.google.com. ,为了方便通常都会省略,浏览器在请求DNS的时候会自动加上 . 。
查询方式:
(1)递归解析
image.png
(2)迭代解析
image.png

1.3 DNS优化

(1)多级缓存:浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存
(2)DNS负载均衡:一个主机名对应多个IP地址,请求域名时,引导到不同机器上进行请求。

2.TCP连接

https://github.com/jawil/blog/issues/14
  拿到域名对应的IP地址之后,浏览器会向服务器的80端口发起TCP的连接请求。这个连接请求到达服务器端后( 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层),建立了TCP/IP的连接。
第一次握手:客户端发送 SYN=1,seq=x,到服务端请求建立连接,此时客户端进入 SYN_SEND 状态
第二次握手:服务端接收到请求,回传 SYN=1,ack=x+1,seq=y,服务端进入SYN_RECV状态
第三次握手:客户端收到回传信息,再次向服务端发送确认包SYN=1,ack=y+1,seq=z, 服务端收到请求后,握手完毕,客户端服务端都进入 established 状态。
image.png
补充:《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”

3.http请求

建立TCP连接之后,会开始下一个阶段 http请求。客户端向服务端发起http请求,一般包括 4个部分:

  • 请求行 方法 / URL / http协议和版本
  • 请求头 协助客户端及服务端交易的一些附属信息 Accept、Cookie、Referer、**Cache-Control** 、UA等
  • 空行 回车+换行
  • 请求体 参数

image.png

4.http响应

image.png
客户端发送http请求后,服务端解析 http request 对象,处理后要向客户端返回一个http响应,与http请求相似,也包括:

  • 状态行 http协议和版本/状态码/状态描述文本
  • 响应头 Allow、Content-Type、Set-Cookie、Date等
  • 空行 表示响应头结束(回车+换行)
  • 响应体 包含着我们需要的一些具体信息,比如cookie,html,image,后端返回的请求数据等等

补充1:
反向代理?
客户端本来可以直接通过HTTP协议访问某网站应用服务器,网站管理员可以在中间加上一个Nginx,客户端请求Nginx,Nginx请求应用服务器,然后将结果返回给客户端,此时Nginx就是反向代理服务器。
image.png
一些大一点的网站会将你的请求到反向代理服务器中,因为当网站访问量非常大,网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。此时,客户端不是直接通过HTTP协议访问某网站应用服务器,而是先请求到Nginx,Nginx再请求应用服务器,然后将结果返回给客户端,这里Nginx的作用是反向代理服务器。同时也带来了一个好处,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。如下图所示:
image.png
补充2:
HTTP状态码
下面是常见的HTTP状态码:

  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
image.png

5.浏览器解析渲染

通过http响应接收到html css js后,浏览器就开始进行WebKit渲染。解析渲染过程如下图所示 :
image.png
浏览器是一个边解析边渲染的过程,首先使用HTML构建DomTree,解析CSS构建CSSOM,domtree和cssom结合成渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。
浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS等。浏览器将重复1-6过程下载该资源。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。原因是因为JS有可能修改DOM结构,这就意味着JS执行完成前,后续所有资源的下载是没有必要的,这就是JS阻塞后续资源下载的根本原因。CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。
image.png
关于JS执行做一个简短的介绍:
image.png
JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

6.tcp关闭连接


现在的页面为了优化请求的耗时,默认都会开启持久连接(keep-alive),就是在一次TCP连接后,保持连接。那么一个TCP连接确切关闭的时机,是这个tab标签页关闭的时候。这个关闭的过程就是著名的四次挥手。关闭是一个全双工的过程,发包的顺序的不一定的。一般来说是客户端主动发起的关闭,过程如下:
image.png
第一次挥手:客户端发送 FIN seq=x ack=y+1报文头到服务端,客户端进入FIN_WAIT_1阶段,(我要关闭连接)
第二次挥手:服务端收到报文,进入CLOSE_WAIT状态,并不立即用FIN报文段回复,而是先返回 ack=x+1,客户端进入FIN_WAIT_2状态(“同意”我的关闭请求)
第三次挥手:服务端向客户端发送FIN报文段,请求关闭连接,同时服务端进入LAST_ACK状态
第四次挥手:C收到S发送的FIN报文段,然后C进入TIME_WAIT状态,然后C向S发送ACK报文段;S收到C的ACK报文段以后,就关闭连接;此时,C等待2MSL后依然没有收到回复,则证明S端已正常关闭,那好,C也可以关闭连接了。