本期,边肖将给大家带来前端浏览器的工作原理。文章内容丰富,从专业角度进行分析和描述。看完这篇文章,希望你能有所收获。
浏览器架构
在谈浏览器架构之前,先了解两个概念,进程和线程。
进程是程序的执行过程,是一个动态的概念,是程序执行过程中分配和管理资源的基本单位。线程是CPU调度和调度的基本单元,它可以与属于同一进程的其他线程共享该进程拥有的所有资源。
简单地说,进程可以理解为正在执行的应用程序,而线程可以理解为我们应用程序中代码的执行者。他们之间的关系可想而知。线程在进程中运行。一个进程中可能有一个或多个线程,一个线程只能属于一个进程。
众所周知,浏览器属于应用程序,一旦执行了应用程序,就可以理解为计算机启动了一个进程。进程启动后,CPU会给进程分配相应的内存空间。当我们的进程获得内存时,我们可以使用线程来调度资源,然后完成我们的应用程序的功能。
在应用程序中,为了满足功能需求,启动的进程将创建其他新进程来处理其他任务。这些创建的新进程拥有全新的独立内存空间,无法与原来的进程内内存进行通信。如果这些进程需要相互通信,可以通过IPC机制(进程间通信)来实现。
很多应用会以这种多进程的方式工作,因为进程和进程是相互独立的,互不影响,也就是说当其中一个进程挂机时,不会影响其他进程的执行,只需要重启挂机的进程即可恢复运行。
浏览器的多进程架构
如果我们开发一个浏览器,它的架构可以是单进程多线程应用,也可以是使用IPC通信的多进程应用。
不同的浏览器使用不同的架构。下面主要以Chrome为例介绍浏览器的多进程架构。
在Chrome中,有四个主要过程:
浏览器进程:负责浏览器的TAB、地址栏、书签栏的前向和后向,处理浏览器一些不可见的底层操作,如网络请求、文件访问等。
渲染器流程:负责选项卡中与显示相关的工作,也称为渲染引擎。
插件进程:负责控制网页使用的插件。
GPU进程:处理整个应用程序的GPU任务。
这四个过程有什么关系?
首先,当我们想要浏览网页时,我们会在浏览器的地址栏中输入网址。此时,浏览器进程将向该网址发送请求,以获取该网址的HTML内容,然后将该HTML交给渲染器进程,渲染器进程将分析该HTML内容。当需要请求网络的资源被解决后,它们被返回到浏览器进程进行加载。同时通知Browser Process需要Plugin Process加载插件资源,执行插件代码。解析完成后,渲染器进程计算图像帧,并将这些图像帧提供给图形处理器进程,图形处理器进程将其转换为图像显示屏。
多进程架构的好处
为什么Chrome采用多进程架构?
第一,更高的容错性。在当今的网络应用中,HTML、JavaScript和CSS变得越来越复杂。这些运行在渲染引擎中的代码频繁出现bug,有些bug会直接导致渲染引擎崩溃。多进程架构使得每个渲染引擎都在自己的进程中运行,互不影响。也就是说,当一个页面崩溃挂起时,其他页面可以正常运行而不受影响。
第二,更高的安全性和三博兴。渲染引擎经常会在网络上遇到不可信甚至恶意的代码,它们会利用这些漏洞在你的计算机上安装恶意软件。为了解决这个问题,浏览器对不同的进程限制不同的权限,并为它们提供沙盒环境,使它们更加安全可靠。
第三,更高的响应速度。在单进程架构中,各个任务相互竞争抢占CPU资源,使得浏览器的响应速度变慢,而多进程架构恰恰避免了这一缺点。
多进程架构优化
前面我们说过,Renderer Process的作用是负责一个Tab中的显示相关工作,也就是说一个Tab会有一个Renderer Process,而这些进程的内存是不能共享的,不同进程的内存往往需要包含相同的内容。
浏览器的进程模式
为了节省内存,Chrome提供了四个process models,不同的Process Models会以不同的方式处理tab流程。
每个站点实例的进程(默认)-同一站点实例使用一个进程。
每个站点的流程-同一站点使用一个流程。
Process-per-tab - 每个 tab 使用一个进程
Single process - 所有 tab 共用一个进程
这里需要给出 site 和 site-instance 的定义
site 指的是相同的 registered domain name(如: google.com ,bbc.co.uk)和scheme (如:https://)。比如a.baidu.com和b.baidu.com就可以理解为同一个 site(注意这里要和 Same-origin policy 区分开来,同源策略还涉及到子域名和端口)。
site-instance 指的是一组 connected pages from the same site,这里 connected 的定义是 can obtain references to each other in script code 怎么理解这段话呢。满足下面两中情况并且打开的新页面和旧页面属于上面定义的同一个 site,就属于同一个 site-instance
用户通过
这种方式点击打开的新页面
JS代码打开的新页面(比如 window.open)
理解了概念之后,下面解释四个进程模式
首先是Single process,顾名思义,单进程模式,所有tab都会使用同一个进程。接下来是Process-per-tab ,也是顾名思义,每打开一个tab,会新建一个进程。而对于Process-per-site,当你打开 a.baidu.com 页面,在打开 b.baidu.com 的页面,这两个页面的tab使用的是共一个进程,因为这两个页面的site相同,而如此一来,如果其中一个tab崩溃了,而另一个tab也会崩溃。
Process-per-site-instance 是最重要的,因为这个是 Chrome 默认使用的模式,也就是几乎所有的用户都在用的模式。当你打开一个 tab 访问 a.baidu.com ,然后再打开一个 tab 访问 b.baidu.com,这两个 tab 会使用两个进程。而如果你在 a.baidu.com 中,通过JS代码打开了 b.baidu.com 页面,这两个 tab 会使用同一个进程。
默认模式选择
那么为什么浏览器使用Process-per-site-instance作为默认的进程模式呢?
Process-per-site-instance兼容了性能与易用性,是一个比较中庸通用的模式。
相较于 Process-per-tab,能够少开很多进程,就意味着更少的内存占用
相较于 Process-per-site,能够更好的隔离相同域名下毫无关联的 tab,更加安全
导航过程都发生了什么
前面我们讲了浏览器的多进程架构,讲了多进程架构的各种好处,和Chrome是怎么优化多进程架构的,下面从用户浏览网页这一简单的场景,来深入了解进程和线程是如何呈现我们的网站页面的。
网页加载过程
之前我们我们提到,tab以外的大部分工作由浏览器进程Browser Process负责,针对工作的不同,Browser Process 划分出不同的工作线程:
UI thread:控制浏览器上的按钮及输入框;
network thread:处理网络请求,从网上获取数据;
storage thread: 控制文件等的访问;
第一步:处理输入
当我们在浏览器的地址栏输入内容按下回车时,UI thread会判断输入的内容是搜索关键词(search query)还是URL,如果是搜索关键词,跳转至默认搜索引擎对应都搜索URL,如果输入的内容是URL,则开始请求URL。
第二步:开始导航
回车按下后,UI thread将关键词搜索对应的URL或输入的URL交给网络线程Network thread,此时UI线程使Tab前的图标展示为加载中状态,然后网络进程进行一系列诸如DNS寻址,建立TLS连接等操作进行资源请求,如果收到服务器的301重定向响应,它就会告知UI线程进行重定向然后它会再次发起一个新的网络请求。
第三步:读取响应
network thread接收到服务器的响应后,开始解析HTTP响应报文,然后根据响应头中的Content-Type字段来确定响应主体的媒体类型(MIME Type),如果媒体类型是一个HTML文件,则将响应数据交给渲染进程(renderer process)来进行下一步的工作,如果是 zip 文件或者其它文件,会把相关数据传输给下载管理器。
与此同时,浏览器会进行 Safe Browsing 安全检查,如果域名或者请求内容匹配到已知的恶意站点,network thread 会展示一个警告页。除此之外,网络线程还会做 CORB(Cross Origin Read Blocking)检查来确定那些敏感的跨站数据不会被发送至渲染进程。
第四步:查找渲染进程
各种检查完毕以后,network thread 确信浏览器可以导航到请求网页,network thread 会通知 UI thread 数据已经准备好,UI thread 会查找到一个 renderer process 进行网页的渲染。
浏览器为了对查找渲染进程这一步骤进行优化,考虑到网络请求获取响应需要时间,所以在第二步开始,浏览器已经预先查找和启动了一个渲染进程,如果中间步骤一切顺利,当 network thread 接收到数据时,渲染进程已经准备好了,但是如果遇到重定向,这个准备好的渲染进程也许就不可用了,这个时候会重新启动一个渲染进程。
第五步:提交导航
到了这一步,数据和渲染进程都准备好了,Browser Process 会向 Renderer Process 发送IPC消息来确认导航,此时,浏览器进程将准备好的数据发送给渲染进程,渲染进程接收到数据之后,又发送IPC消息给浏览器进程,告诉浏览器进程导航已经提交了,页面开始加载。
这个时候导航栏会更新,安全指示符更新(地址前面的小锁),访问历史列表(history tab)更新,即可以通过前进后退来切换该页面。
第六步:初始化加载完成
当导航提交完成后,渲染进程开始加载资源及渲染页面(详细内容下文介绍),当页面渲染完成后(页面及内部的iframe都触发了onload事件),会向浏览器进程发送IPC消息,告知浏览器进程,这个时候UI thread会停止展示tab中的加载中图标。
网页渲染原理
导航过程完成之后,浏览器进程把数据交给了渲染进程,渲染进程负责tab内的所有事情,核心目的就是将HTML/CSS/JS代码,转化为用户可进行交互的web页面。那么渲染进程是如何工作的呢?
渲染进程中,包含线程分别是:
一个主线程(main thread)
多个工作线程(work thread)
一个合成器线程(compositor thread)
多个光栅化线程(raster thread)
不同的线程,有着不同的工作职责。
构建DOM
当渲染进程接受到导航的确认信息后,开始接受来自浏览器进程的数据,这个时候,主线程会解析数据转化为DOM(Document Object Model)对象。
DOM为WEB开发人员通过JavaScript与网页进行交互的数据结构及API。
资源子加载
在构建DOM的过程中,会解析到图片、CSS、JavaScript
脚本等资源,这些资源是需要从网络或者缓存中获取的,主线程在构建DOM过程中如果遇到了这些资源,逐一发起请求去获取,而为了提升效率,浏览器也会运行预加载扫描(preload scanner)程序,如果如果HTML中存在img、link等标签,预加载扫描程序会把这些请求传递给Browser Process的network thread进行资源下载。
JavaScript的下载与执行
构建DOM过程中,如果遇到
上述就是小编为大家分享的前端浏览器的工作原理是什么了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/132529.html