浏览器基本原理

浏览器简介

目前的主流浏览器有五个:IE、Firefox、Safari、Chrome 和 Opera

浏览器的主要功能是向服务器发出请求,然后在浏览器窗口中呈现返回的资源

浏览器的主要组件有:

  • 用户界面
  • 浏览器引擎
  • 渲染引擎
  • 网络
  • UI 后端
  • JavaScript 解释器
  • 数据存储

进程与线程

  • 进程:资源(CPU、内存)分配的最小单位
  • 线程:是在进程内部的程序运行单位

每打开一个新的标签页就新建了一个进程(如果后期标签页过多可能会合并进程)

浏览器中的主要进程

浏览器进程、第三方插件进程、GPU 进程、渲染进程

  • 多进程的优点:某一页面进程出问题不会影响其他页面,避免不同页面的权限问题,以及第三方插件的问题
  • 多进程的缺点:内存消耗大,不同进程中常常包含相同内容

死锁

在多个进程执行过程中因资源争夺而造成的僵持状态,此时若没有干预这些线程就都将无法向前推进。

  • 产生死锁的必要条件

    • 互斥条件:进程要求对所分配的资源进行排它性控制
    • 请求和保持条件:当进程因请求资源而阻塞时,对已经获得的资源保持不放
    • 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放
    • 环路等待条件:在发生死锁时,必然存在一个进程-资源的环形链
  • 解决死锁的方法

    • 预防死锁

      • 一次性分配所有资源,这样就不会再请求资源了
      • 如果某进程获得了部分资源,但得不到剩下的资源,则释放已有资源(超时放弃)
      • 给资源编号,有序分配
    • 避免死锁

      • 在进行资源分配前先计算安全性,若安全才进行分配,否则进程等待
      • 银行家算法
    • 解除死锁

      • 从其他进程中剥夺资源给死锁进程,以解除死锁状态
      • 直接撤销死锁进程,或撤销代价最小的进程直到资源足够接触死锁进程为止

渲染进程(浏览器内核)

渲染进程也就是我们说的浏览器内核

GUI 渲染线程

作用:负责渲染页面

渲染流程

  1. 构建 DOM :根据 HTML 渲染 DOM(同一个 HTML 文件得到的DOM 树并不总是一样,浏览器会按照自己的规范来构建)
  2. 加载次级资源:请求下载图片,CSS,JS 等资源
  3. JS 的下载与执行:<script>
  4. 样式计算:基于 CSS 选择器解析 CSS 计算每个节点的具体样式值
  5. 获取布局:遍历 DOM 以及相关元素的计算样式,构建出布局树
  6. 绘制各元素:遍历布局树,创建绘制记录
  7. 合成帧:遍历布局树,创建层树,合成器将每一层栅格化然后合成帧(合成器是独立工作的,与主线程无关,非常流畅)

JS 引擎线程

作用:负责解析执行 JS 脚本

JS 引擎线程是单线程,容易引发的阻塞问题, HTML5 提出了 Web Worker 解决此问题,允许主线程创建 Worker 线程,将一些任务分配给该线程在后台运行。JS 引擎线程与 Worker 线程之间通过 postMessage API 进行通信

JS 引擎线程与 GUI 渲染线程互斥,无法同时进行,因为 JS 也可以操作 DOM,会影响渲染结果

事件触发线程

作用:控制事件循环

事件循环

同步任务直接放入 JS 引擎线程中的执行栈中处理,异步任务放入事件触发线程中的事件队列中等待。

当 JS 引擎线程上的执行栈为空时,JS 引擎线程会询问事件触发线程,如果事件队列中有异步任务,就会被添加到执行栈中开始执行。

定时触发器线程

作用:执行 setInterval 与 setTimesout,计时完毕后通知事件触发线程

异步http请求线程

作用:在 XMLHttpRequest 连接后通过浏览器新开一个线程请求。当检测到状态变更时,如果设置有回调函数,异步线程就会产生状态变更事件,将回调放入事件队列中,再由 JS 引擎执行。

浏览器缓存

浏览器会把通过 HTTP 获取的所有资源保存到本地

缓存位置

Service Worker:

内存缓存 memory cache 硬盘缓存 disk cache
读取速度快 读取速度慢
退出进程时数据会被清除 退出进程时数据不会被清除

通常 memory cache 保存 JS、字体、图片等文件,disk cache 保存 CSS 文件

访问缓存优先级

  1. 在内存中查找
  2. 在硬盘中查找
  3. 进行网络请求
  4. 把获取的资源缓存到本地

强制缓存 和 协商缓存

浏览器在请求某一资源时,会先获取该资源缓存的 header 信息,判断是否命中强缓存,若命中则直接从缓存中获取资源信息,不会与服务器进行通信。若没有命中强缓存,浏览器会向服务器发送携带之前获取到的有关缓存的 header 信息,服务器对比相关 header 信息看是否命中协商缓存,若命中则服务器返回新的响应 header 信息更新缓存中对应的 header 信息,告知浏览器可以直接从缓存中获取资源信息,若没有命中协商缓存,则会直接返回最新的资源内容

HTTP 报文中的缓存相关字段

  • Cache-Control

    http 1.1 出现的 header 字段,可以定义资源什么时候被缓存、如何被缓存以及缓存多长时间等

  • Last-Modify

    标识资源的最后修改时间,浏览器第一次请求一个资源的时候,服务器返回的 header 中会加上 Last-Modify。当浏览器再次请求该资源时,服务器会根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回 304,并且不会返回资源内容,如果未命中,返回 200 和新的资源,并带上新的修改时间 Last-Modify。

    缺点:短时间内如果资源发生变化,Last-Modified 并不会变化,可以用 Etag 处理

  • Etag

    服务器针对资源计算出一串校验码,通过 Etag 返回给客户端,客户端下次请求时带上该值,服务器对比校验,如果相同则返回 304,不返回资源,不一致则返回 412 和新的资源。

参考资料

浏览器的工作原理:新式网络浏览器幕后揭秘

从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理

图解浏览器的基本工作原理

浏览器原理机制

Web Worker 使用教程

浅谈http中的Cache-Control

实践这一次,彻底搞懂浏览器缓存机制

死锁面试题(什么是死锁,产生死锁的原因及必要条件)


最后修改于 2021-10-02