美文网首页浏览器专栏学习记录
浏览器专栏学习-宏观视角下的浏览器

浏览器专栏学习-宏观视角下的浏览器

作者: Mstian | 来源:发表于2020-08-21 00:31 被阅读0次

    此学习记录来自于极客时间专栏浏览器工作原理与实践,由于个人对这块内容比较感兴趣,所以花钱买了专栏,但看完总觉得什么都没记住,所以将一些重要内容记录下来。文中有老师课程中的原文和配图,已在课程留言区告知老师,如侵删。
    如果对这块内容感兴趣,强烈建议去读一遍老师的课程,很有收获。

    宏观视角下的浏览器

    Chrome架构

    目前浏览器采用多进程架构
    最新的Chrome浏览器包括1个浏览器主进程,1个GPU进程,1个网络进程,多个渲染进程和多个插件进程
    如何查看打开一个页面需要启动多少个进程?
    点击Chrome浏览器右上角“选项”菜单,选择“更多工具”子菜单,点击“任务管理器”
    如下图:

    image.png
    假如打开一个百度页面就会有浏览器主进程,GPU进程,网络进程,渲染进程,还有插件进程,如果你再打开一个tab页面,那么就会有新的进程生成。

    进程VS线程
    一个进程就是一个程序的运行实例。启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程

    线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单位,是处理器调度和分派的基本单位。

    线程与进程

    进程与线程关系:

    1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位。
    2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线。
    3. 进程之间相互独立,同一进程下的各个线程之间共享程序的内存空间。
    4. 进程之间的内容相互隔离。(防止某个进程挂掉影响其他进程,但进程之间有通信机制(IPC))。
    5. 进程中的任意线程执行出错,都会导致整个进程的崩溃。

    浏览器多进程功能分析
    浏览器进程:主要负责界面显示、用户交互、子进程管理、同时提供存储等功能。
    渲染进程:核心任务是将HTML、CSS和JavaScript转换为用户可以与之交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该进程中的,默认情况下,Chrome会为每个Tab标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
    GPU进程:GPU进程使用初衷是为了实现3D CSS的效果,只是随后网页、Chrome的UI界面都选择GPU来绘制,最终Chrome在其多进程架构中引入了GPU进程。
    网络进程:主要负责页面的网络资源加载。
    插件进程:主要负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。

    仅仅打开一个页面为什么有4个进程?因为打开一个页面至少需要1个网络进程、一个浏览器进程、一个GPU进程、以及一个渲染进程。共4个,如果打开的页面有运行插件的话,还需要再加上一个插件进程。

    TCP协议

    如何保证页面文件能被完整地送达浏览器呢?

    1. IP:把数据包送达目的主机
      IP(Internet Protocol)网际协议,计算机的地址就成为IP地址,访问任何网站实际上只是你的计算机向另外一台计算机请求信息。

    2. UDP:把数据包送达应用程序
      IP是非常底层的协议,只负责把数据包传送到对方电脑,但电脑并不知道具体需要把数据包交给哪个程序,是给浏览器还是网易云音乐?因此需要基于IP之上开发能和应用打交道的协议,最常见的是用户数据包协议(User Datagram Protocol),简称UDP
      UDP在发送数据时,有各种因素会导致数据包出错,虽然UDP可以校验数据是否正确,但是对于错误的数据包,UDP并不提供重发机制,只是丢弃当前的包,而且UDP在发送之后也无法知道是否能到达目的地。
      虽说UDP不能保证数据可靠性,但是传输速度却非常快,所以UDP会应用在一些关注速度,但不要求数据完整性的领域,如在线视频、互动游戏等。

    3. TCP:把数据完整地送达应用程序
      对于浏览器请求或者邮件类要求数据传输可靠性的应用,使用UDP会存在两个问题:

    • 数据包在传输过程中容易丢失。
    • 大文件被拆分传输,而UDP协议不知道如何组装还原。

    基于这两个问题引入TCP,TCP(Transmission Control Protocol)传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。相对于UDP,TCP有以下两个特点:

    • 对于数据包丢失的情况,TCP提供重传机制。
    • TCP引入数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。

    一个完整的TCP连接的生命周期包括了建立连接 传输数据断开连接三个阶段。

    TCP连接生命周期
    • 首先,建立连接阶段,需要通过“三次握手”来建立客户端和服务端之间的连接。
    • 其次,传输数据阶段,接收端需要对每个数据包进行确认操作,如果当发送端发送一个数据包在规定时间内没有接收到接收端反馈的确认消息,则判断为数据包丢失,触发重传机制。大文件在传输过程中会被拆分成很多小数据包,这些数据包到达接收端后,接收端会按照TCP头中的序号为其排序,保证组成完整数据。
    • 最后,断开连接阶段,数据传输完毕之后经过“四次挥手”保证双方都能断开连接。

    TCP为了保证数据传输的可靠性,牺牲了数据包的传输速度,因为“三次握手”和“数据包校验机制”等把传输过程中数据包的数量提高了。

    HTTP请求流程

    HTTP是一种允许浏览器向服务器获取资源的协议,是Web的基础,通常由浏览器发起请求,用来获取不同不同类型的文件,例如HTML CSS JavaScript文件,图片,视频等。
    下面看看HTTP请求流程

    浏览端发起HTTP请求流程

    如果在浏览器中输入一个url,那么接下来浏览器会发生什么呢?
    1. 构建请求:
    首先,浏览器构建请求行信息,构建好后,浏览器准备发起网络请求。

    请求行信息

    GET /index.html HTTP1.1
    

    2. 查找缓存:
    在真正发起网络请求之前,浏览器会在浏览器缓存中查询是否有要请求的文件。其中浏览器缓存时一种在本地保存资源副本,以供下次请求时直接使用的技术。
    当浏览器发现请求的资源在浏览器缓存中有副本,它会拦截请求,返回该资源副本,并直接结束请求,不会去服务器重新下载。
    这样做的好处有:

    • 缓解服务器端压力,提升性能(获取资源耗时短了)
    • 对于网站来说,缓存是实现快速资源加载的重要组成部分。
      如果查找缓存失败了,就会进入网络请求过程。

    3. 准备IP地址和端口
    因为浏览器使用HTTP协议作为应用层协议,用来封装请求的文本信息,并使用TCP/IP作传输层协议将它发到网络上,所以在HTTP工作开始之前,浏览器需要通过TCP与服务器建立连接。也就是说HTTP的内容是通过TCP的传输数据阶段来实现的

    域名系统,简称DNS(Domain Nane System),负责把域名和IP地址做一一映射关系。
    第一步浏览器会请求DNS返回域名对应IP,如果某个域名已经解析过了,那么浏览器会缓存解析的结果,以供下次查询使用,这样会减少一次网络请求,称为DNS数据缓存服务
    拿到IP后需要获取端口号,如果URL没有指明端口号,那么HTTP协议默认是80端口。

    4. 等待TCP队列

    准备好端口号和IP地址后,理论上是可以进行TCP连接了,但是Chrome有个机制,同一域名同时最多只能建立6个TCP连接,如果有超过6个的请求,那么其余请求就会进入排队等待状态,直至进行中的请求完成。

    如果有超过6个请求那么需要等待,没有超过6个请求的话,直接进入建立TCP连接阶段。

    5. 建立TCP连接
    在HTTP工作开始之前,浏览器通过TCP与服务器建立连接,连接步骤在上面有提到可以参考一下。

    6. 发送HTTP请求
    一旦建立了TCP连接,浏览器就可以和服务器进行通信了。而HTTP中的数据就是在通信过程中传输的。

    可以根据下图理解:


    HTTP请求数据格式

    首先浏览器会向服务器发送请求行,它包括了请求方法,请求URI(Uniform Resource Identifier)和HTTP版本协议
    发送请求行,告诉服务器浏览器需要什么资源,常见请求方法有GET,POST,如果使用POST方法,浏览器还要通过请求体发送数据给服务器。

    在浏览器发送请求行命令之后,还要以请求头发送一些其他信息,把浏览器的一些基础信息告诉服务器。比如浏览器所使用的操作系统、浏览器内核等信息,以及当前请求的域名信息,浏览器端的Cookie信息等。

    服务器处理HTTP请求流程

    1. 返回请求
    一旦服务器处理请求结束,便可以返回数据给浏览器了,可以通过curl -i 查看返回请求数据。

    curl -i  https://time.geekbang.org/
    

    结果大概如下:


    服务器响应数据格式

    首先服务器会返回响应行,包括协议版本和状态码

    服务器也会向浏览器发送响应头。响应头包含了服务器自身的一些信息,比如服务器返回数据的时间,返回数据类型(JSON HTML 流媒体等类型),以及服务器要在客户端保存的Cookie等信息。

    发送完响应头后,服务器就可以继续发送响应体的数据,通常,响应体就包含了HTML的实际内容。

    2. 断开连接
    通常情况下,一旦服务器向客户端返回了请求数据,它就要关闭TCP连接。如果浏览器或者服务器在其头部信息中加入了:

    Connection:Keep-Alive
    

    那么TCP连接在发送后将仍然保持打开状态,这样浏览器就可以继续通过同一个TCP连接发送请求。保持TCP连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。比如,一个Web页面内嵌的图片都来自于同一个Web站点,如果初始化了一个持久连接,你就可以复用该连接,以请求其他资源,而不需要重新再建立新的TCP连接

    3. 重定向
    比如在地址栏输入geekbang.org,最终打开的是https://www.geekbang.org
    这两个URL之所以不一样,是因为涉及到了一个重定向操作。
    可以使用curl查看请求geekbang.org的返回内容。

    在控制台输入如下命令:

    curl -I geekbang.org
    

    这里输入的参数大写I和i不一样,-I表示只需要获取响应头和响应行数据,不需要获取响应体数据,最终返回数据如下。


    服务器返回响应行和响应头

    响应行返回的状态码是301,表示需要重定向,需要重定向的地址就是包含在响应头中的Location字段。接下来浏览器会获取Location字段中的地址,并使用该地址重新导航,这就是一个完整重定向的执行流程。

    问题1:为什么很多站点第二次打开速度会很快?
    主要原因是第一次加载页面过程总,缓存课一些耗时的数据。
    DNS缓存页面资源缓存这两块数据是会被浏览器缓存起来的。
    关于缓存内容可以参阅其他资料:
    放个自己画的丑图:

    缓存使用流程图

    问题2:登录状态是如何保持的?

    • 用户使用用户名密码登录,调用POST方法提交信息给服务器。
    • 服务器接受信息验证登录,通过之后生成一段表示用户身份的字符串,并把该字符串写到响应头的Set-Cookie字段里
    response header
    Set-Cookie: UID=2020uuap
    
    • 浏览器接收到服务器响应后遇到响应头中含有Set-Cookie字段的情况,浏览器会把这个字段信息保存到本地。
    • 当用户再次访问时,浏览器会发起HTTP请求,在发起请求之前浏览器会读取之前保存的Cookie数据,并写进请求头Cookie字段,然后浏览器再将请求头发送给服务器。
    // request header
    Cookie:UID=2020uuap
    
    • 服务器收到HTTP请求头数据之后,就会找到请求头里面的Cookie字段信息,当查找到包含UID=2020uuap信息时,服务器查询后台判断得知该用户已是登陆状态,然后生成含有该用户信息的页面数据,并把生成的数据发送给浏览器。
    • 浏览器在接收到该含有当前用户的页面数据后,就可以正确展示用户登录的状态信息了。

    导航流程

    问题:在浏览器里,从输入URL到页面显示,这中间发生了什么?

    从输入URL到页面展示流程图

    从图中可以看出,整个过程需要各个进程之间的配合

    过程大致如下:

    1. 首先,浏览器进程接收到用户输入的URL请求,浏览器进程便将该URL转发给网络进程。
    2. 然后,在网络进程中发起真正的URL请求。
    3. 接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。
    4. 浏览器进程接收到网络进程的响应头数据之后,发送“提交文档(CommitNavigation)”消息到渲染进程。
    5. 渲染进程接收到“提交文档”的消息之后,便开始准备接收HTML数据,接收数据的方式是直接和网络进程建立数据管道。
    6. 等文档传输完成之后,最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接收和解析页面数据了”。
    7. 浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态,包括安全状态,地址栏URL,前进后退的历史状态,并更新Web页面。

    其中用户发出URL请求到页面开始解析的这个过程,就叫做导航

    tips:

    • 服务器可以根据响应头来控制浏览器的行为,如跳转,网络数据类型判断。
    • Chrome默认采用每个标签对应一个渲染进程,但是如果两个页面属于同一站点,那这两个标签会使用同一个渲染进程。
    • 浏览器的导航过程涵盖了从用户发起请求到提交文档给渲染进程的中间所有阶段。

    相关知识可以查阅资料了解。

    渲染流程

    整个渲染流程包括,从HTML到DOM,样式计算,布局,图层,绘制,光栅化,合成和显示。


    完整的渲染流水线示意图

    完整的流程大致总结:

    1. 渲染进程将HTML内容转换为能够读懂的DOM树结构
    2. 渲染引擎将CSS样式表转化为浏览器可以理解的styleSheets,计算出DOM节点的样式。
    3. 创建布局树,并计算元素的布局信息。
    4. 在渲染进程主线程中对布局树进行分层,并生成分层树
    5. 为每个图层生成绘制列表也就是一条条绘制指令,并将其提交到合成线程。
    6. 合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图(此操作运行在GPU进程中)。
    7. 合成线程发送绘制图块命令DrawQuad给浏览器进程。
    8. 浏览器进程根据DrawQuad消息生成页面,并显示到显示器上。

    到这里,经过一些列的阶段,编写好的HTML,CSS,JavaScript等文件,经过浏览器就会显示出漂亮的页面了。

    这部分内容其实相对来说是比较复杂的内容也很多,比如DOM树的生成使用到Chrome中的HTMLparser解析,还有布局树与分层树的关系,以及为什么要有图块等等,这些内容有兴趣可以自己查阅或者在留言区留言,我也可以将这些内容在留言区中分享出来,

    相关文章

      网友评论

        本文标题:浏览器专栏学习-宏观视角下的浏览器

        本文链接:https://www.haomeiwen.com/subject/njyyjktx.html