{"componentChunkName":"component---src-templates-blog-post-js","path":"/learn-browser/","result":{"data":{"markdownRemark":{"html":"<h2>浏览器架构</h2>\n<blockquote>\n<p>通过对浏览器多进程架构的学习，可以把网络流程、页面渲染过程、JavaScript执行流程以及Web安全理论这些知识点串起来组成一张网。</p>\n</blockquote>\n<h3>单进程浏览器</h3>\n<p><img src=\"https://static001.geekbang.org/resource/image/6d/ca/6ddad2419b049b0eb2a8036f3dfff1ca.png?wh=1142*469\" alt=\"Image text\"></p>\n<ul>\n<li>单进程架构浏览器的缺点\n<ul>\n<li>不稳定\n<ul>\n<li>一个插件线程或者渲染线程出错了，会导致整个浏览器进程崩溃</li>\n</ul>\n</li>\n<li>不流畅\n<ul>\n<li>所有页面的渲染模块、JavaScript 执行环境以及插件都是运行在同一个线程中的，这就意味着同一时刻只能有一个模块可以执行。</li>\n</ul>\n</li>\n<li>不安全\n<ul>\n<li>c++ 来写插件，可以直接获取到电脑上的资源，从而控制电脑，盗窃密码等</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3>多进程浏览器时代</h3>\n<p>早期多进程架构，2008 年 Chrome 发布时的进程架构\n<img src=\"https://static001.geekbang.org/resource/image/cd/60/cdc9215e6c6377fc965b7fac8c3ec960.png?wh=1142*725\" alt=\"Image text\"></p>\n<p>Chrome 的页面是运行在单独的渲染进程中的，同时页面里的插件也是运行在单独的插件进程之中，而进程之间是通过 IPC 机制进行通信（如图中虚线部分）。</p>\n<ul>\n<li>由于进程是相互隔离的，所以当一个页面或者插件崩溃时，影响到的仅仅是当前的页面进程或者插件进程，并不会影响到浏览器和其他页面，这就完美地解决了页面或者插件的崩溃会导致整个浏览器崩溃，也就是不稳定的问题。</li>\n<li>同样，JavaScript 也是运行在渲染进程中的，所以即使 JavaScript 阻塞了渲染进程，影响到的也只是当前的渲染页面，而并不会影响浏览器和其他页面，因为其他页面的脚本是运行在它们自己的渲染进程中的。所以当我们再在 Chrome 中运行上面那个死循环的脚本时，没有响应的仅仅是当前的页面。</li>\n<li>采用多进程架构的额外好处是可以使用安全沙箱，你可以把沙箱看成是操作系统给进程上了一把锁，沙箱里面的程序可以运行，但是不能在你的硬盘上写入任何数据，也不能在敏感位置读取任何数据，例如你的文档和桌面。Chrome 把插件进程和渲染进程锁在沙箱里面，这样即使在渲染进程或者插件进程里面执行了恶意程序，恶意程序也无法突破沙箱去获取系统权限。</li>\n</ul>\n<h3>目前多进程架构</h3>\n<p><img src=\"https://static001.geekbang.org/resource/image/b6/fc/b61cab529fa31301bde290813b4587fc.png?wh=1142*494\" alt=\"Image text\"></p>\n<ul>\n<li>浏览器进程。主要负责界面显示、用户交互、子进程管理，同时提供存储等功能。</li>\n<li>渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页，排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中，默认情况下，Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑，渲染进程都是运行在沙箱模式下。\n<ul>\n<li><strong>注意</strong>: 同一站点会放进一个渲染进程里进行执行，A 页面的 JS 是可以直接在 B 页面里运行的，包括进行通信</li>\n</ul>\n</li>\n<li>GPU 进程。其实，Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果，只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制，这使得 GPU 成为浏览器普遍的需求。最后，Chrome 在其多进程架构上也引入了 GPU 进程。</li>\n<li>网络进程。主要负责页面的网络资源加载，之前是作为一个模块运行在浏览器进程里面的，直至最近才独立出来，成为一个单独的进程。</li>\n<li>插件进程。主要是负责插件的运行，因插件易崩溃，所以需要通过插件进程来隔离，以保证插件进程崩溃不会对浏览器和页面造成影响。</li>\n</ul>\n<p>不过凡事都有两面性，虽然多进程模型提升了浏览器的稳定性、流畅性和安全性，但同样不可避免地带来了一些问题：</p>\n<ul>\n<li>更高的资源占用。因为每个进程都会包含公共基础结构的副本（如 JavaScript 运行环境），这就意味着浏览器会消耗更多的内存资源。</li>\n<li>更复杂的体系架构。浏览器各模块之间耦合性高、扩展性差等问题，会导致现在的架构已经很难适应新的需求了。</li>\n<li></li>\n</ul>\n<h3>面向服务架构</h3>\n<p>为了解决这些问题，在 2016 年，Chrome 官方团队使用“面向服务的架构”（Services Oriented Architecture，简称 SOA）的思想设计了新的 Chrome 架构。也就是说 Chrome 整体架构会朝向现代操作系统所采用的“面向服务的架构” 方向发展，原来的各种模块会被重构成独立的服务（Service），每个服务（Service）都可以在独立的进程中运行，访问服务（Service）必须使用定义好的接口，通过 IPC 来通信，从而构建一个更内聚、松耦合、易于维护和扩展的系统，更好实现 Chrome 简单、稳定、高速、安全的目标。如果你对面向服务的架构感兴趣，你可以去网上搜索下资料，这里就不过多介绍了。</p>\n<p><img src=\"https://static001.geekbang.org/resource/image/32/2a/329658fe821252db47b0964037a1de2a.png?wh=1142*582\" alt=\"Image text\"></p>\n<p>浏览器缓存是怎样的？</p>","timeToRead":4,"frontmatter":{"title":"浏览器原理","date":"March 04, 2024","spoiler":null},"fields":{"slug":"/learn-browser/"}}},"pageContext":{"slug":"/learn-browser/","previous":{"fields":{"slug":"/pnpm/"},"frontmatter":{"title":"Why should we use pnpm?"}},"next":{"fields":{"slug":"/learn-browser/render/"},"frontmatter":{"title":"渲染流程"}}}},"staticQueryHashes":["3649515864","63159454"]}