浏览器多进程架构

308 阅读3分钟

在浏览器刚被设计出来的时候,网页占用的资源是非常低的,因此一个进程就能够同时处理多个网页。然而在今天,大量的网页变得日益复杂,把所有网页都放进一个进程的浏览器面临在健壮性,响应速度,安全性方面的挑战。因为如果浏览器中的一个tab网页崩溃的话,将会影响到其他的网页应用。另外在数据安全方面,进程之间的资源和地址空间不共享,相对于线程来说更加安全。Chrome浏览器就是使用多个进程来隔离不同的网页,当打开一个标签页就相当于打开了一个进程。

多线程内核

浏览器的内核是多线程的,在内核控制下各线程相互配合以保持同步,一个浏览器通常由以下常驻线程组成:

  • GUI 渲染线程
  • JavaScript引擎线程
  • 定时触发器线程
  • 事件触发线程
  • 异步http请求线程

GUI渲染线程

GUI渲染线程负责渲染浏览器界面HTML元素,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。在Javascript引擎运行脚本期间,GUI渲染线程都是处于挂起状态的,也就是说被”冻结”了。

JavaScript引擎线程

Javascript引擎,也可以称为JS内核,主要负责处理Javascript脚本程序,例如V8引擎。javascript引擎同时也是单线程的,javascript主要是能够处理页面中用户的交互的,如果javascript是多线程的,在多线程的交互模式下,两个线程操作同一个DOM,一个负责修改另外一个负责删除,那么浏览器如何决定执行哪个线程的命令呢,javascript在最初就选择了单线程执行。

定时触发器线程

浏览器定时计数器并不是由JavaScript引擎计数的, 因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时是更为合理的方案。

事件触发线程

当一个事件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可以是当前执行的代码块如定时任务、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

异步HTTP请求线程

在XMLHttpRequest在连接后是通过浏览器新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript引擎的处理队列中等待处理。