面试官一上来就问我 Chrome 底层原理和 HTTP 协议(万字长文)
哪吒人生信条:如果你所学的东西 处于喜欢 才会有强大的动力支撑。
每天学习编程,让你离梦想更新一步,感谢不负每一份热爱编程的程序员,不论知识点多么奇葩,和我一起,让那一颗四处流荡的心定下来,一直走下去,加油,2021
加油!欢迎关注加我vx:xiaoda0423
,欢迎点赞、收藏和评论
不要害怕做梦,但是呢,也不要光做梦,要做一个实干家,而不是空谈家,求真力行。
前言
有人说,如果你懂得浏览器的工作原理,你就能解决 80%的前端难题。
是的,了解浏览器的工作原理,有助于你的工作;而了解 TCP/IP 、HTTP 等网络协议,更是对你未来的职业发展大有裨益。
下面,我总结了 4 个面试常考的关于浏览器和网络通信的问题,为你重新梳理浏览器,网络通信、页面渲染、JavaScript、浏览器安全等知识,从而让你对整个前端后端体系有全新的认识。
第一问:Chrome 为什么打开一个页面,会有 4 个进程?
学习掌握:浏览器中的网络流程,页面渲染过程,JavaScript 执行流程,以及 Web 安全理论。下面展开问题了解多进程架构:
多进程架构的学习
进程和线程的概念混淆
如计算来说,单线程就是一个接一个的计算,多线程就是同时处理多个计算。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,就是说允许单个程序创建多个并行执行。
单线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程也是程序,所以线程需要占用内存,线程越多占用内存也越多,多线程需要协调和管理,所以需要 CPU 时间跟踪线程;线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;线程太多会导致控制太复杂。
单线程在程序执行时,所走的程序都是按照连续顺序下来的,前面的必须处理好,才会执行后面的。多线程运行就是一个进程内有多个相对独立的并且实现特定的任务以竞争 CPU 的方式执行,宏观上是并发,实际上是分时执行,只是执行的时间片较短。
每个正在运行的程序即是进程,至少包含一个线程,这个线程叫主线程,它在程序启动时被创建,用于执行 main 函数。只有一个主线程的程序,称为单线程程序。拥有多个线程的程序,称为多线程程序。
进程是当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源(一个进程又是由多个线程所组成的)
多线程的好处就是可以提高 CPU 的利用率,在多线程程序中,如果一个线程必须等待的时候,CPU 可以运行其它的线程而不是等待,这样可以大大地提高程序的效率。
所以,线程是不能单独存在的,它是由进程来启动和管理的,一个进程就是一个程序的运行实例。线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。线程之间共享进程中的数据。当一个进程关闭后,操作系统会回收进程所占用的内存。
目前的多进程架构浏览器 Chrome 包括,1 个浏览器主进程,1 个 GPU 进程,1 个网络进程,多个渲染进程和多个插件进程。
so,打开一个页面,为啥有 4 个进程?因为打开 1 个页面:至少需要 1 个网络进程,*1 个浏览器进程*,1 个 GPU 进程以及*1 个渲染进程*。
虽然多进程模型提升了浏览器的稳定性、流畅性和安全性,但是带来了更高的资源占用,更复杂的体系架构。so,Chrome
官方要构建一个更内聚,松耦合,易于维护和扩展的系统。
第二问:TCP 协议是如何保证页面文件能被完整送达浏览器的?
对于在网络中,我们知道一个文件通常会被拆分为很多数据包来进行传输,而数据包在传输过程中又有很大的可能会丢失或者出错,保证页面文件完整地送达浏览器是有必要的。
下面就这三方面展开描述:
数据包如何送达到主机
主机如何将数据包转交给应用
数据是如何被完整地送达到应用程序
数据包从主机 A 送到主机 B,数据包上会附加上主机 B 的 IP 地址信息,主机 A 本身的 IP 地址,这些附加的信息会被装进一个 IP 头的数据结构里(包含 IP 版本,源 IP 地址,目标 IP 地址,生存时间等)
这些一般我们都了解,下面主要说明 TCP(Transmission Control Protocol
),传输控制协议是一种面向连接的,*可靠的*,基于字节流的传输层通信协议,在简化的计算机网络 OSI 模型中,它完成第四层传输层所指定的功能。
用户数据报协议(UDP
)是同一层内另一个重要的传输协议。
在因特网协议族中,TCP
层是位于 IP 层之上的,TCP->IP,应用层之下的中间层,应用层->中间层。不同主机的应用层之间经常需要可靠的,像管道一样的连接,但是 IP 层不提供这样的流机制,而是提供不可靠的包进行交换。
TCP
为了保证不发生丢包的情况,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。接收端实体对已成功收到的包发回一个相应的确认信息(ACK
),如果发送端实体在合理的往返时延(RTT
)内未收到确认,那么对应的数据包就被假设为已丢失并进行重传。
数据在
TCP
层称为流数据分组称为分段
TCP 协议的运作:连接创建,数据传送,连接终止。
那你了解什么是TCP
吗?这一点大部分人应该只会说它是一种协议。
TCP
传输控制协议是TCP/IP
,传输控制协议 Internet 协议中的主要协议之一,TCP/IP
是一套通信协议,用于连接 Internet 以及大多数其他计算机网络上的主机。
协议是一种共同商定的用于执行某件事的格式。对于计算机,最常用于指一组规则,使计算机能够相互连接并传输数据,称为通信协议。
TCP 是一种面向连接的协议,它在主机之间建立并维护虚拟连接,直到交换了一条消息或要在其上运行的应用程序交换的消息为止。数据包是 TCP/IP 网络上数据传输的最基本单位。
TCP 在传输层上运行,负责维护整个网络上可靠的端到端通信,IP 是网络层协议,它是传输层正下方的层,在传输层运行的有:UDP(用户数据报协议),RTP(实时传输协议),SCTP(流控制传输协议)。
连接创建
TCP 用三次握手过程创建一个连接
三次握手协议的过程:
a.客户端 向 服务器端 发送一个 SYN 包,请求一个主动打开。该包携带客户端为这个连接请求设定的随机数 A 作为消息列号。
b.服务器端接收到一个 SYN 包后,把该包放入 SYN 队列中;回送一个 SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身携带一个随机产生的序号 B。
c.客户端收到 SYN/ACK 包后,发送一个 ACK 的包,该包的序号被设定为 A+1,而 ACK 的确认码为 B+1。 当服务器端收到这个 ACK 包的时候,把请求帧从 SYN 队列中移出,放置 ACCEPT 队列中。
场景:当服务器端接收到客户端发送过来的 SYN 后, 回了 SYN-ACK 后,客户端掉线了,服务器端没有收到客户端回来的 ACK,那这个连接 就 处于 一个中间状态,没成功也没失败。
但是,服务器端如果在一定时间内没有收到 TCP 会重新发 SYN-ACK。
主机收到一个 TCP 包时,用两端的 IP 地址与端口号来标识这个 TCP 包属于哪个 session。
使用一张表来存储所有的 session,表中的每条称作 TCB。
tcb 结构的定义含: 连接使用的源端口, 目的端口,目的 ip, 序号, 应答序号, 对方窗口大小, 已方窗口大小, tcp 状态, tcp 输入/输出队列, 应用层输出队列, tcp 的重传有关变量等。
服务器端的连接数量是无限的,只受内存的限制。
数据传送
在每个 TCP 报文段中都有一对序号和确认号。
TCP 报文发送者称自己的字节流的编号为序号,称接收到对方的字节流编号为确认号。通过使用序号和确认号,TCP 层可以把收到的报文段中的字节按正确的顺序交付给应用层。
TCP 协议使用序号标识每端发出的字节顺序,从另一端接收数据可以重建顺序,无惧传输的包的乱序交付或丢包。
发送确认包 acks,携带接收对方发来的字节流的编号(确认号),告诉对方已经成功接收的数据流的字节位置。
上图描述数据传输的过程图
数据包结构
下面让我们来看看数据包结构图:
包含:偏移字节,来源连接端口,目的连接端口,序列号码,确认号码,校验和,紧急指针等。
来源连接端口,16 位长,识别发送连接端口
目的连接端口,16 位长,识别接收连接端口
序列号(
seq
,32 位长)确认号(
ack
,32 位长),期望收到的数据的开始序列号,也即已经收到的数据的字节长度加 1资料偏移(4 位长),以 4 字节为单位计算出的数据段开始地址的偏移值。
保留,须置 0
ACK
—为 1 表示确认号字段有效SYN
—为 1 表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步FIN
—为 1 表示发送方没有数据要传输了,要求释放连接RST
—为 1 表示出现严重差错。可能需要重新创建 TCP 连接。还可以用于拒绝非法的报文段和拒绝连接请求紧急指针(16 位长)—本报文段中的紧急数据的最后一个字节的序号
窗口(
WIN
,16 位长)—表示从确认号开始,本报文的发送方可以接收的字节数,即接收窗口大小。用于流量控制校验和(
Checksum
,16 位长)—对整个的TCP
报文段,包括TCP
头部和 TCP 数据,以 16 位字进行计算所得。这是一个强制性的字段
记住其中 IP 是把数据包送达目的主机的,数据包送达到主机。那么如何将数据包转交给应用的呢?
UDP 是把数据包送达应用程序的。
UDP 是基于 IP 之上开发能和应用打交道的协议,用户数据包协议,是决定把数据包交给哪个程序的,IP 只负责把数据包传送到对方电脑。
下面看一下 UDP 协议和 TCP 协议在 TCP/IP 体系中的位置:
看完位置,那么下面我们来简单对比一下 UDP 和 TCP:
UDP
: 无连接;支持一对一,一对多,多对一和多对多交互通信;对应用层交付的报文直接打包;尽最大努力交付,也就是不可靠;不使用流量控制和拥塞控制;首部开销小,仅 8 字节。
TCP
:面向连接;每一条 TCP 连接只能有两个端点 EP,只能是一对一通信;面向字节流;可靠传输,使用流量控制和拥塞控制;首部最小 20 字节,最大 60 字节。
让我们看看 UDP 和 TCP 首部对比开销:
UDP 最重要的一点就是端口号,因为 UDP 是通过端口号把数据包分发给正确的程序,UDP 不能保证数据的可靠性,但传输速度快。
重要的讲解是:数据是如何被完整地送达到应用程序?
TCP 就是把数据完整地送达应用程序。
TCP 是一种面向连接的,可靠的,基于字节流的传输层通信协议,提供重传机制,引入了数据包排序机制(TCP 头,提供了排序的序列号,用来通过序号重排数据包)。
说到 TCP 连接,就要说说常面试的 TCP/IP 的三次握手,建立连接;四次挥手,断开连接。
三次握手图:
完成了三次 TCP 握手:
女朋友发给男朋友:“在吗?”
男朋友回复女朋友:“我在!”
女朋友回复男朋友:“我知道了!”
此时男朋友知道了。
四次挥手图:
完成四次挥手:
女朋友发给男朋友:“分手吧!”
男朋友回复女朋友:“额?”
男朋友回复女朋友:“认真的吗?”
女朋友回复男朋友:“认真的!”
此时女朋友删除了男朋友的微信。
按照我描述的三次握手和四次挥手,我相信你懂了,哈哈!
第三问:HTTP 请求流程,为什么很多站点第二次打开速度会很快呢?
说到 HTTP 协议,它是建立在 TCP 连接基础之上的,超文本传输协议,HTTP 是一种用于分布式,协作式和超媒体信息系统的应用层协议,HTTP 是万维网的数据通信的基础。
某人说:要想学好浏览器,就要深入了解 HTTP。
浏览器是使用 HTTP 协议作为应用层协议,用来封装请求的文本信息,使用TCP/IP
作传输层协议将它发到网络上(http 的内容是通过 TCP 的传输数据阶段来实现的)。
域名和 IP 地址-映射关系,域名映射为 IP 的系统叫作“域名系统”,简称
DNS
。
域名系统 DNS 是互联网的一项服务。它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。
域名如:dadaqianduan.cn
(URL 地址)
IP 地址为:xx.233.xxs.12
(访问)
首先,第一步浏览器会请求 DNS 返回域名对应的 IP,浏览器还提供了 DNS 数据缓存服务,如果某个域名已经被解析过了,浏览器就会缓存解析的结构,下次查询时直接使用,减少一次网络请求。拿到 IP 后,就需要获取端口号,如果 url 没有明确指出端口号,HTTP 协议默认是 80 端口。
到这一步明白的清清楚楚了,IP 和端口号。那么让我说说 HTTP 协议的描述,这里补充是为了更好的了解:
HTTP 是一个客户端和服务器端之间请求和应答的标准,通常使用 TCP 协议,通过使用网页浏览器,网咯爬虫或者其它的工具,客户端发起一个 HTTP 请求到服务器上指定端口,默认端口为 80。
应答的服务器上存储着一些资源,如 HTML 文件和图像等,源服务器;(客户端称为用户代理程序),用户代理和源服务器中间可能存在多个"中间层",比如代理服务器,网关,隧道等。
so,HTTP 服务器在端口监听客户端的请求,一旦收到请求,服务器会向客户端返回一个状态,如:"HTTP/1.1 200 OK
",以及返回的内容,如请求的文件,错误消息,或者其它消息。
到这里我先回答一下:浏览器发起 HTTP 请求流程:1.构建请求(构建请求行信息);2.查找缓存(浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术);3.准备 IP 地址和端口;4.等待 TCP 队列;5.建立 TCP 连接;6.发送 HTTP 请求。
然后服务器处理请求,服务器返回请求,断开连接。
其实端口和 IP 地址准备好后,不一定直接建立 TCP 连接的,因为在 Chrome 中有个机制,就是同一个域名同时最多只能建立 6 个 TCP 连接,如果在同一个域名下同时有 10 个请求发生,那么其中就有 4 个请求进入排队等待状态。
如果请求数量少于 6 个,就直接进入建立 TCP 连接。
发送 HTTP 请求
上面都讲好了初步,那么浏览器是如何发送请求信息给服务器的呢?
来一张 post 请求抓包图:
来张浏览器发送请求到服务器端接收返回的过程:
描述:用户在浏览器输入请求的 url 地址,浏览器内部的核心代码会将这个 url 进行拆分解析,最终将 domain 发送到 DNS 服务器上,DNS 服务器会根据 domain 去查询相关的对应的 ip 地址,从而将 IP 地址返回给浏览器。
浏览器有了 ip 地址后就会知道这个请求是发送到哪里的。经过(局域网,交换机,路由器,主干网咯)到达服务器。
对于经常了解 HTTP 的朋友应该了解上述表达,那接下来看看 HTTP 请求数据格式(可看上图->来一张 post 请求抓包图):
HTTP 请求数据格式:
浏览器首先向服务器发送请求行(请求方法;请求 URI;HTTP 协议版本)-来告诉服务器浏览器需要什么资源,常用请求方法为 GET,请求头(用来告诉一些浏览器的基础信息-浏览器所使用的操作系统、浏览器内核等信息,以及当前请求的域名信息、浏览器端的 Cookie 信息等),请求体(如常用的 POST,用于发送一些数据给服务器,准备的数据是通过请求体来发送的)。
服务器处理 HTTP 请求流程:
返回请求;
断开连接;
重定向。
查看返回请求数据,-i,获取返回响应行(包含协议版本和状态码),响应头,响应体数据。
一般情况下,服务器向客户端返回了请求数据,就要关闭 TCP 连接。但其头信息中加入了该字段: Connection: Keep-Alive
,让 TCP 连接仍然保持连接,可以继续同一个 TCP 连接发送请求,可以省下次请求时需要建立连接的时间。
其实一般返回请求,断开连接就没了,但有一种就是你在浏览器中打开的 url,发现最终的页面地址不一样,那是因为有一个重定向操作。
如图:-I 表示只需要获取响应头和响应行数据
location 字段时重定向的地址;
状态码 301 和 302 的区别
301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。
302 Found 请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在 Cache-Control 或 Expires 中进行了指定的情况下,这个响应才是可缓存的。
字面上的区别:301 是永久重定向,而 302 是临时重定向
302 重定向是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址,因为服务器返回 302,所以搜索搜索引擎认为新的网址是暂时的。
301 重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址。
接下来,让我们梳理一下 HTTP 版本号,这一点,我相信在学习的过程中,大家也是想知道的。
HTTP/0.9:
已过时。仅支持请求方式 GET,并且仅能请求访问 HTML 格式的资源,没有在通讯中指定版本号,且不支持请求头。
HTTP/1.0:
这是第一个在通讯中指定版本号的 HTTP 协议版本,增加了请求方式 POST 和 HEAD;不再局限于 0.9 版本的 HTML 格式,根据 Content-Type 可以支持多种数据格式;包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
1.0 版本:每次 TCP 连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立 TCP 连接.
HTTP/1.1:
默认采用持续连接(TCP 连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive
),能很好地配合代理服务器工作。
一个 TCP 连接可以允许多个 HTTP 请求
增加了管道机制,在同一个 TCP 连接里,允许多个请求同时发送,增加了并发性,进一步改善了 HTTP 协议的效率
1.1 版规定可以不使用Content-Length
字段,而使用"分块传输编码"-只要请求或回应的头信息有Transfer-Encoding
字段,就表明回应将由数量未定的数据块组成。Transfer-Encoding: chunked
新增了请求方式PUT、PATCH、OPTIONS、DELETE
等
分块传输编码:是超文本传输协议中的一种数据传输机制,允许 HTTP 由网页服务器发送给客户端应用的数据可以分成多个部分,分块传输编码只在
HTTP
协议 1.1 版本(HTTP/1.1
)中提供。
同一个 TCP 连接里,所有的数据通信是按次序进行的。回应慢,会有许多请求排队,造成"队头堵塞"。
HTTP/2:
于 2015 年 5 月作为互联网标准正式发布。加了双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题。
使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比 HTTP1.1 大了好几个数量级。
增加服务器推送的功能,不经请求服务端主动向客户端发送数据。
HTTP1.1 相较于 HTTP1.0 协议区别:
缓存处理
带宽优化及网络连接的使用
错误通知的管理
消息在网络中的发送
互联网地址的维护
安全性及完整性
最后的最后,说第二次站点的打开为啥速度快?
原因是第一次加载页面过程中,缓存了一些耗时的数据,主要缓存有 DNS 缓存 和 页面资源缓存 两个方面。
浏览器缓存
当第一次发送请求,服务器返回 HTTP 响应头给浏览器时,浏览器会通过响应头中CacheControl
字段来设置是否缓存资源。通常还需设置一个缓存时间,Cache-Control:Max-age=2000
,在缓存没有过期的情况下,在发送请求请求该资源,会直接返回缓存中的资源给浏览器。如果缓存过期,浏览器则会继续发起网络请求。
盲点:
第四问:输入 URL 到页面展示发生了什么?
简单地说一下就是:
浏览器主进程提交
url
给网络进程网络进程请求服务器,返回响应头行体,判断是否需要重定向
网络进程将页面类型的响应资源提交给渲染进程
渲染进程渲染结束,加载完毕
分步骤简单说一下就是:
首先是域名解析
建立 TCP 链接
建立 Http 请求
服务器处理 Http 请求
关闭 TCP 连接
浏览器解析资源
浏览器渲染页面
在我的 GitHub 上也讲过:
https://github.com/webVueBlog/interview-answe/issues/27
本篇文章的最后,留给你一个面试题,就是上面说到的:“从输入 URL 到页面展示,这中间发送了什么?”这个问题,如果面试你,你又如何回答呢?
如果你作为面试官,又该考哪些点呢?
阅读资料
浏览器工作原理与实践
https://time.geekbang.org/column/intro/100033601
总结
以上就是今天要讲的内容,本文简单介绍了 Chrome 流程,梳理了 TCP 与 HTTP 协议,了解三次握手,四次挥手流程,感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。
喜欢本文的朋友,欢迎关注,收看更多精彩内容
❤️关注+点赞+收藏+评论+转发❤️,原创不易,鼓励笔者创作更好的文章
点赞、收藏和评论
我是Jeskson
(达达前端),感谢各位人才的:点赞、收藏和评论,我们下期见!(如本文内容有地方讲解有误,欢迎指出☞谢谢,一起学习了)
我们下期见!
文章持续更新,可以微信搜一搜「 程序员哆啦 A 梦 」第一时间阅读,回复【资料】有我准备的一线大厂资料,本文 http://www.dadaqianduan.cn/#/ 已经收录
github
收录,欢迎Star
:https://github.com/webVueBlog/WebFamily
版权声明: 本文为 InfoQ 作者【魔王哪吒】的原创文章。
原文链接:【http://xie.infoq.cn/article/1389674ed08fce24e3e83dc8f】。未经作者许可,禁止转载。
评论