前言
最近忙着做面试官,出一期我的面试官思路,面试时长我一般控制在半小时左右,大家时间都很宝贵;
我认为面试别人何尝不是一次难得的学习机会;
对于面试者来说,哪怕不能让他“听君一席话,胜读十年书”;也要让他感叹不虚此行,学到了;
对于面试官来说,每次当我问出一个问题,我也会思考我会怎么答;这也是“学而时习之,温故而知新”的过程,厚积定能薄发,每次对相同的知识亦或者问题都有不一样的心得,不一样的思考,亦有所得。
针对不一样的人出不一样的题,遇强则强,遇弱则降低点难度,多一点引导,少一点对错,多一点反馈,少一点沉默。
遇到基础稍微差点的,答不上来,我会以引导为主,只要愿意思考,我会帮他构建知识基础,由点到线,由线到面。
遇到基础好,有一定沉淀的人,我会以学习交流为主,把这一次面试当成一种多样化知识蓝图的构建点,同时对等输出我的产出
面试遇到过各种各样的面试者,他们各有特色,有不自信的,有自卑的,有自傲的,有爱抬杠的......形形色色,这也正折射着当下所谓的“前端已死”、“环境差”等名词;有趣的是一部分人口口声声把这些东西来作为自己“菜”的借口,遇到不会的的问题,说一句我看过来着,一紧张忘了,记不清了。
环境一直都在变,人也一直在变。但是有个规则是不变的:实力为尊。认清自己,找到定位,思考破局。
最后我都会让面试者进行提问,其中也有实诚人,说:“面试官谢谢你的面试,虽然我发挥的不太好,但是很幸运你,让我获益匪浅,面试官能不能给我一点指点”;我自会道出一二建议。
祭品说,精神反刍和吸引力法则,你信奉什么主义,就会化作什么祭品。你信奉环境差,你何尝不是祭品
下面开始本次的一问到底
在浏览器输入URL后,回车发生了什么
先来个总流程图,然后进入我的知识点一问到底环节
1、解析什么?
浏览器首先对 URL
解析,解析出协议、域名、端口、资源路径、参数等。
2、DNS 域名解析展开讲讲?
DNS
全称 Domain Name System
, 即域名系统。
接触过服务器亦或者你本地启项目IP
地址可以观察下,就会发现服务器地址通常是一串数字,例如192.168.
那么通常我们输入的网址,显然不是IP
地址,所以肯定会有一个解析过程,也就是DNS解析。
一般而言,域名比IP
地址更好记,因而我们更习惯在浏览器输入域名而不是 IP
,而计算机网络通信所识别的计算机标识是 IP
地址,因而首先需要将一个域名转化为相应的IP
地址,这就是 DNS
协议所要做的事。
DNS
就像我们手机中的通讯录一样,通讯录中备注的是对方的姓名(类似于域名),但是打电话的时候实际需要的是电话号码(类似于 IP
地址),利用通讯录将一个姓名转化为对应的电话号码。
2.1 解析完后为什么有些网址打开很快有些很慢?
这就涉及到强缓存和协商缓存,浏览器在加载资源时,会先根据本地缓存资源的 header
中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header
中的部分信息来判断是否命中缓存(协商缓存)。如果命中,则返回 304
,告诉浏览器资源未更新,可使用本地的缓存。
强缓存
浏览器在加载资源时,会先根据本地缓存资源的 header
中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。
- 这里的
header
中的信息指的是expires 和 cahe-control
. Expires
该字段是http1.0
时的规范,它的值为一个绝对时间的GMT
格式的时间字符串,比如Expires:Mon,18 Oct 2066 23:59:59 GMT
。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,就会导致缓存混乱(本地时间也可以随便更改)。Cache-Control(优先级高于 Expires) Cache-Control
是http1.1
时出现的header
信息,主要是利用该字段的max-age
值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600
,代表着资源的有效期是 3600 秒。cache-control
除了该字段外,还有下面几个比较常用的设置值:no-cache
:需要进行协商缓存,发送请求到服务器确认是否使用缓存。no-store
:禁止使用缓存,每一次都要重新请求数据。public
:可以被所有的用户缓存,包括终端用户和CDN
等中间代理服务器。 private:只能被终端用户的浏览器缓存,不允许CDN
等中继缓存服务器对其缓存。Cache-Control
与Expires
可以在服务端配置同时启用,同时启用的时候Cache-Control
优先级高。
协商缓存
当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据 header 中的部分信息来判断是否命中缓存。如果命中,则返回 304 ,告诉浏览器资源未更新,可使用本地的缓存。
- 这里的
header
中的信息指的是Last-Modify/If-Modify-Since 和 ETag/If-None-Match
. Last-Modify/If-Modify-Since
浏览器第一次请求一个资源的时候,服务器返回的header
中会加上Last-Modify,Last-modify
是一个时间标识该资源的最后修改时间(只能精确到秒,所以间隔时间小于 1 秒的请求是检测不到文件更改的。)。- 当浏览器再次请求该资源时,
request
的请求头中会包含If-Modify-Since
,该值为缓存之前返回的Last-Modify
。服务器收到If-Modify-Since
后,根据资源的最后修改时间判断是否命中缓存。 如果命中缓存,则返回 304,并且不会返回资源内容,并且不会返回Last-Modify
。 - 缺点: 短时间内资源发生了改变,
Last-Modified
并不会发生变化。 - 周期性变化。如果这个资源在一个周期内修改回原来的样子了,我们认为是可以使用缓存的,但是
Last-Modified
可不这样认为, 因此便有了ETag
。 ETag/If-None-Match Etag
是基于文件内容进行编码的,可以保证如果服务器有更新,一定会重新请求资源,但是编码需要付出额外的开销。- 与
Last-Modify/If-Modify-Since
不同的是,Etag/If-None-Match
返回的是一个校验码。ETag
可以保证每一个资源是唯一的,资源变化都会导致ETag
变化。服务器根据浏览器上送的If-None-Match
值来判断是否命中缓存。 - 与
Last-Modified
不一样的是,当服务器返回304 Not Modified
的响应时,由于ETag
重新生成过,response header
中还会把这个ETag
返回,即使这个ETag
跟之前的没有变化。 Last-Modified
与ETag
是可以一起使用的,服务器会优先验证ETag
,一致的情况下,才会继续比对Last-Modified
,最后才决定是否返回304
。
3.建立 TCP 连接
一般在浏览器输入 URL
,应用层的协议为 HTTP/HTTPS
,其需要的是可靠的服务,所使用的传输层协议为 TCP
。
通过域名解析后,浏览器获得了服务器的 IP
,则向服务器发起 TCP
连接,这时候就会发生三次握手行为。
3.1 OSI参考模型或七层模型是什么?
七层模型,亦称OSI(Open System Interconnection)
。参考模型是国际标准化组织ISO
)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。
它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括具体的协议。
应用层
网络服务与最终用户的一个接口。
协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
表示层
数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层)
格式有,JPEG、ASCll、EBCDIC、加密格式等 [2]
会话层
建立、管理、终止会话。(在五层模型里面已经合并到了应用层)
对应主机进程,指本地主机与远程主机正在进行的会话
传输层
定义传输数据的协议端口号,以及流控和差错校验。
协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层
网络层
进行逻辑地址寻址,实现不同网络之间的路径选择。
协议有:ICMP IGMP IP(IPV4 IPV6)
数据链路层
建立逻辑连接、进行硬件地址寻址、差错校验 等功能。(由底层网络定义协议)
将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。
物理层
建立、维护、断开物理连接。(由底层网络定义协议)
TCP/IP
层级模型结构,应用层之间的协议通过逐级调用传输层(Transport layer
)、网络层(Network Layer
)和物理数据链路层(Physical Data Link
)而可以实现应用层的应用程序通信互联。
应用层需要关心应用程序的逻辑细节,而不是数据在网络中的传输活动。应用层其下三层则处理真正的通信细节。在 Internet 整个发展过程中的所有思想和着重点都以一种称为 RFC(Request For Comments)
的文档格式存在。针对每一种特定的 TCP/IP
应用,有相应的 RFC
文档。
3.2TCP/IP协议是什么?
TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议) 是指能够在多个不同网络间实现信息传输的协议簇。TCP/IP
协议不仅仅指的是TCP
和IP
两个协议,而是指一个由FTP、SMTP、TCP、UDP、IP
等协议构成的协议簇, 只是因为在TCP/IP
协议中TCP
协议和IP协议最具代表性,所以被称为TCP/IP协议。
它是在网络的使用中的最基本的通信协议。TCP/IP
传输协议对互联网中各部分进行通信的标准和方法进行了规定。并且,TCP/IP
传输协议是保证网络数据信息及时、完整传输的两个重要的协议。TCP/IP
传输协议是严格来说是一个四层的体系结构,应用层、传输层、网络层和数据链路层都包含其中。
3.3 TCP/IP协议有哪些特点?
TCP/IP
协议能够迅速发展起来并成为事实上的标准,是它恰好适应了世界范围内数据通信的需要。它有以下特点:
- 协议标准是完全开放的,可以供用户免费使用,并且独立于特定的计算机硬件与操作系统。
- 独立于网络硬件系统,可以运行在广域网,更适合于互联网。
- 网络地址统一分配,网络中每一设备和终端都具有一个唯一地址。
- 高层协议标准化,可以提供多种多样可靠网络服务。
3.4TCP/IP协议包含哪几层?
- 应用层;
- 传输层;
- 网络层;
- 网络接口层。
- 应用层位于TCP/IP协议的第一层,是直接为应用进程提供服务的;运输层位于协议的第二层,在整个TCP/IP协议中起到了中流砥柱的作用;网络层位于协议的第三层;网络接口层位于协议的第四层。
3.5讲讲三次握手四次挥手?
三次握手
- 第一次握手 客户端向服务端发送连接请求报文段。该报文段的头部中
SYN=1,ACK=0,seq=x。
请求发送后,客户端便进入SYN-SENT
状态。 PS1:SYN=1,ACK=0
表示该报文段为连接请求报文。PS2:x 为本次 TCP
通信的字节流的初始序号。 TCP 规定:SYN=1 的报文段不能有数据部分,但要消耗掉一个序号。 第二次握手 服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。
该应答发送完成后便进入 SYN-RCVD 状态。PS1:SYN=1,ACK=1
表示该报文段为连接同意的应答报文。PS2:seq=y
表示服务端作为发送者时,发送字节流的初始序号。PS3:ack=x+1
表示服务端希望下一个数据报发送序号从x+1
开始的字节。 第三次握手 当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。 该报文段的头部为:ACK=1,seq=x+1,ack=y+1
。 客户端发完这个报文段后便进入ESTABLISHED
状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接的建立完成!
3.5.1为什么连接建立需要三次握手,而不是两次握手
-
在谢希仁著《计算机网络》第四版中讲 “三次握手” 的目的是 “为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手” 的目的是为了解决 “网络中存在延迟的重复分组” 的问题。这两种不用的表述其实阐明的是同一个问题。
-
谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达
server
。本来这是一个早已失效的报文段。但server
收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向client
发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要server
发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待client
发来数据。这样,server
的很多资源就白白浪费掉了。采用“三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client
不会向 server 的确认发出确认。server
由于收不到确认,就知道client
并没有要求建立连接。”
四次挥手 第一次挥手 若 A 认为数据发送完成,则它需要向 B 发送连接释放请求。该请求只有报文头,头中携带的主要参数为: FIN=1,seq=u。此时,A 将进入 FIN-WAIT-1
状态。
PS1:FIN=1
表示该报文段是一个连接释放请求。PS2:seq=u,u-1
是 A 向 B 发送的最后一个字节的序号。 第二次挥手 B 收到连接释放请求后,会通知相应的应用程序,告诉它 A 向 B 这个方向的连接已经释放。此时 B 进入CLOSE-WAIT
状态,并向 A 发送连接释放的应答,其报文头包含:ACK=1,seq=v,ack=u+1。
PS1:ACK=1
:除 TCP 连接请求报文段以外,TCP 通信过程中所有数据报的 ACK 都为 1,表示应答。PS2:seq=v
,v-1 是 B 向 A 发送的最后一个字节的序号。 PS3:ack=u+1 表示希望收到从第 u+1 个字节开始的报文段,并且已经成功接收了前 u 个字节。 A 收到该应答,进入 FIN-WAIT-2 状态,等待 B 发送连接释放请求。- 第二次挥手完成后,A 到 B 方向的连接已经释放,B 不会再接收数据,A 也不会再发送数据。但 B 到 A 方向的连接仍然存在,B 可以继续向 A 发送数据。
- 第三次挥手 当 B 向 A 发完所有数据后,向 A 发送连接释放请求,请求头:
FIN=1,ACK=1,seq=w,ack=u+1。B
便进入LAST-ACK
状态。 - 第四次挥手 A 收到释放请求后,向 B 发送确认应答,此时 A 进入
TIME-WAIT
状态。该状态会持续 2MSL 时间,若该时间段内没有 B 的重发请求的话,就进入CLOSED
状态,撤销TCB
。当 B 收到确认应答后,也便进入CLOSED
状态,撤销 TCB。 - 为什么 A 要先进入 TIME-WAIT 状态,等待
2MSL
时间后才进入CLOSED
状态? 为了保证 B 能收到 A 的确认应答。 若 A 发完确认应答后直接进入CLOSED
状态,那么如果该应答丢失,B 等待超时后就会重新发送连接释放请求,但此时 A 已经关闭了,不会作出任何响应,因此 B 永远无法正常关闭。
4. 浏览器解析渲染页面
浏览器收到服务器的响应报文后,从响应体中得到相应资源,如 HTML 文件、图片、视频等,并进行渲染,然后将结果呈现给用户。
4.1 讲讲页面渲染过程?
- 解析HTML,
- 构建
DOM
树 - 解析
CSS
,生成CSS
规则树 - 合并
DOM
树和CSS
规则, - 生成
render
树 - 布局
render
树(Layout / reflow
), - 负责各元素尺寸、位置的计算 绘制
render
树(paint
),绘制页面像素信息 浏览器会将各层的信息发送给GPU,GPU
会将各层合成(composite
),显示在屏幕上
4.2讲讲重排和重绘?
一、重绘不一定需要重排,重排必然会导致重绘
1、重排:当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
1)添加、删除可见的dom
2)元素的位置改变
3)元素的尺寸改变(外边距、内边距、边框厚度、宽高等几何属性)
4)页面渲染初始化
5)浏览器窗口尺寸改变
2、重绘:是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
二、减少reflow、repaint
1、不要一条一条的修改DOM
的样式,可以先定义好css
的class
,然后修改DOM
的className
。
2、不要把DOM结点的属性值放在一个循环里当成循环里的变量。
3、为动画的HTML
使用fixed
或absolute
的position
,那么修改他们的css
是不会reflow
4.2打开 Chrome 浏览器一个页面,至少会出现几个进程?
最新的 Chrome
浏览器包括至少四个:
1 个浏览器(Browser
)主进程、1 个 GPU
进程、1 个网络(NetWork
)进程、多个渲染进程和多个插件进程, 当然还有复杂的情况;
- 页面中有
iframe
的话,iframe
会单独在进程中 - 有插件的话,插件也会开启进程
- 多个页面属于同一站点,并且从 a 打开 b 页面,会共用一个渲染进程
- 装了扩展的话,扩展也会占用进程
- 这些进程都可以通过
Chrome
任务管理器来查看
4.3即使如今多进程架构,还是会碰到单页面卡死的最终崩溃导致所有页面崩溃的情况,讲一讲你的理解?
提供一种情况,就是同一站点, 围绕这个展开也行。
Chrome
的默认策略是,每个标签对应一个渲染进程。但是如果从一个页面打开了新页面,而新页面和当前页面属于同一站点时,那么新页面会复用父页面的渲染进程。官方把这个默认策略叫 process-per-site-instance。- 更加简单的来说,就是如果多个页面符合同一站点,这几个页面会分配到一个渲染进程中去, 所以有这样子的一种情况, 一个页面崩溃了,会导致同一个站点的其他页面也奔溃,这是因为它们使用的是同一个渲染进程。
- 有人会问为什么会跑到一个进程里面呢?
- 你想一想呀, 属于同一家的站点,比如下面三个:
- time.geekbang.org www.geekbang.org www.geekbang.org:8080 它们在一个渲染进程中的话,它们就会共享 JS 执行环境,也就是 A 页面可以直接在 B 页面中执行脚本了, 有些时候就是有这样子的需求嘛。
写在最后
其实就这一个问题的扩展还有很多,思维发散便可触类旁通,反向推导,由面到线,由线到点,大家有所见解可以留言评论区,比方说TCP和UDP报文的区别、浏览器内核相关知识、等等.....
我是凉城a,一个前端,热爱技术也热爱生活。
希望你读完我的文章,每次都有不一样的收获。
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
- 本文首发于掘金,未经许可禁止转载💌