PWA系列 - Web Workers 线程模型

本文涉及的产品
.cn 域名,1个 12个月
简介: 本文是Chromium官方设计文档Blink Workers主旨内容的翻译,介绍ServiceWorker在内核层面的一些基本概念和线程模型。

前言

本文是Chromium官方设计文档Blink Workers主旨内容的翻译,介绍ServiceWorker在内核层面的一些基本概念和线程模型。

一 Worker类型

Web Workers是一个Web平台特性,它提供了后台JS context,和允许任何脚本运行在后台,通常运行在一个独立的线程。Blink实现了几类worker:

  • dedicated worker: 专用worker, 只能被创建它的JS访问。创建它的页面关闭, 它的生命周期就结束了。 一个文档可以有多个dedicated worker。
  • shared worker:共享worker, 可以被同一域名下的JS访问。关联的页面都关闭时, 它的生命周期就结束了。多个文档可以对应同一个shared worker。
  • service worker:事件驱动的worker, 生命周期与页面无关。关联页面未关闭时, 它也可以退出, 没有关联页面时, 它也可以启动。
  • compositor worker:允许JS脚本处理UI的工作,比如,响应输入和更新视觉效果。它运行在非UI线程。

二 基本概念

  • Worker context:worker脚本运行的后台JS上下文。
  • Worker thread:worker context运行的线程,它通常是指blink中的WorkerThread类,对应一个底层平台线程(blink中的WebThread)。
  • Worker object: 通常是指JS的worker对象,关联文档可以通过它与worker交互。它一般在它的parent context进行初始化,它通常运行在parent context的线程中,一般是主线程。
  • Worker global scope:worker JS上下文的global scope(比如, window 是文档JS的global scope)。注意,window scope中APIs与worker global scope的APIs并不是一一对应。

a691b23afee6a731b30ae3ae8158bfda5d7d2bab

它们之间的关系:

Document 可以new一个Worker object,Worker object会去加载worker script,worker script加载完成后, 会new Worker thread,Worker thread会创建Worker global scope,worker context运行在worker thread。

三 进程模型

Workers可以大致分为in-process workers 和 out-of-process workers。

In-process workers: 与它们对应的document(s)运行在同一进程, 因此,它们基本只是对document(s)增加不同的线程。

Out-of-process workers可以运行在与document(s)不同的进程。通常如果worker需要由不同的documents共享,blink/chromium就会实现为out-of-process worker。

具体实现上,in-process workers可以在renderer进程中worker线程和主线程通过post task来实现交互,而out-of-process workers必须通过IPC进行通信,无论worker是否和文档运行在同一进程。

508521477066920bcfd200d52778617a6698ec46

四 线程模型

大部分worker都运行在它们自己的线程(比如,worker context : worker thread = 1:1),而Compositor Worker例外,它是运行在per-process singleton thread(比如,worker context : worker thread = N:1)。

Out-of-process workers需要使用IPCs与关联的文档进行交互,而IPC的基础设施在browser进程实现,所以它们一部分的代码需要在browser进程实现。

 

Process model

Thread model

Dedicated Worker

In-process

Run on its own thread
(Worker context : thread = 1:1)

Shared Worker

Out-of-process

Run on its own thread
(Worker context : thread = 1:1)

Service Worker

Out-of-process

Run on its own thread
(Worker context : thread = 1:1)

Compositor Worker

In-process

Share a per-process single thread within a process
(worker context : thread = N:1)

Isolated Worker

In-process

May run on the same thread as document thread

五 代码目录说明

  • third_party/WebKit/Source/core/workers/*

    • Common worker code (e.g. WorkerThread.*, WorkerGlobalScope.*)

    • Dedicated worker code (e.g. DedicatedWorker*)

    • Shared worker code (e.g. SharedWorker*)

  • third_party/WebKit/Source/modules/serviceworkers/*

    • Service worker blink端的代码

  • third_party/WebKit/Source/modules/compositorworker/*

    • Compositor worker bink端的代码

  • third_party/WebKit/Source/web/*Worker*

    • 实现public/web/的类,browser端使用/交互的类 (e.g. ServiceWorkerGlobalScopeProxy, WebEmbeddedWorkerImpl, WebSharedWorkerImpl)

    • 通过public/web/* 与browser端交互的类 (e.g. WorkerGlobalScopeProxyProviderImpl, ServiceWorkerGlobalScopeClientImpl)

  • third_party/WebKit/public/web/*Worker*

    • 头文件的类,由Blink实现,给browser端使用 (e.g. WebEmbeddedWorker, WebSharedWorker, WebServiceWorkerContextProxy)

    • 头文件的类,由browser端实现,给blink使用 (e.g. WebServiceWorkerContextClient)

  • content/{browser,child,common,renderer}/service_worker/*

    • service worker browser端的代码

  • content/{browser,renderer}/shared_worker/*

    • shared worker browser端的代码

  • content/child/worker_*

    • 处理worker thread的browser端的代码。主要是从worker thread收发IPCs。比如,Worker context中的storage API需要和browser进程进行交互时通常使用这些类。

六 重要类说明

(1)Worker object classes

所有Worker object类都从AbstractWorker类派生,AbstractWorker接口定义为H5 workers的通用基础接口。

dc571824cca871b953a309122aebcd65080df4e8

(2)Worker thread classes

WorkerThread: 代表一个worker线程,WorkerThread的实例一般会持有一个platform thread(通过WebThreadSupportingGC类持有WebThread,通过WorkerThread::backingThread访问)。

每个 WorkerThread 会使用一个v8::Isolate来完全隔离running worker script和main thread scripts。

WorkerBackingThread:代表workers的一个线程,它持有一个WebThreadSupportingGC和一个v8::Isolate。多个workers可以关联到一个WorkerBackingThread(比如,CompositorWorkers)。

b6c3e1d38e4c4ca0fe86f5f4f16e3b5cee6e5e51

注意:大部分WorkerThread的子类,仅仅重写了createWorkerGlobalScope方法,而CompositorWorkerThread还重写了线程和v8::Isolate相关的一系列方法,从而可以做到多个CompositorWorkerThread共享一个per-process platform thread 和 v8::Isolate。

(3)Worker global scope classes

WorkerGlobalScope:通用的基础类,代码一个worker global scope。

95c924e380f39dc8ab67d17a958431fbd702047d

注:前面章节为Blink Workers主旨内容的翻译

七 ServiceWorker进程模型

在多进程模型下, ServiceWorker会同时运行在renderrer进程和browser进程,其中ServiceWorkerThread运行在renderer进程,其他如ServiceWorkerVersion等则运行在browser进程。

打开两个相同域名的ServiceWorker页面,页面里的ServiceWorker会运行在同一renderrer进程中。

打开两个不同域名的ServiceWorker页面,页面里的ServiceWorker会运行在不同renderrer进程中。

如果浏览器已有同一域名的renderrer进程,新建一个ServiceWorker一般不会创建一个新的renderrer进程,而只会使用已有的renderrer进程。

我们看看,ServiceWorker创建renderrer进程的过程:

ServiceWorkerVersion::StartWorker
--> EmbeddedWorkerInstance::Start
--> ServiceWorkerProcessManager::AllocateWorkerProcess(bool can_use_existing_process) 
// 如果ServiceWorkerVersion失败次数超过2,那么EmbeddedWorkerInstance会强制新建一个renderrer进程。
// 这里的失败一般是指ServiceWorker注册过程的失败。
     --> ServiceWorkerProcessManager::FindAvailableProcess // 查找可用的进程
     --> ServiceWorkerProcessManager::SortProcessesForPattern(const GURL& pattern) 
     // 按域名查找是否存在合适的renderrer进程
     --> pattern_processes_.find(pattern) // ServiceWorker注册的流程会将pattern加入pattern_processes_
--> SiteInstance::GetProcess // 如果上面没有找到合适的renderrer进程, 就新建一个renderrer进程

从上面流程可以看到, ServiceWorker会根据一定的算法去决定是否使用新的renderrer进程。其中两个较重要的因素是,按域名分派进程,同一version失败次数不能太多,比如,不超过2(kMaxSameProcessFailureCount)。

参考文档

Blink Workers - Current architecture, implementation and future project ideas for Blink Workers

目录
相关文章
|
14天前
|
并行计算 JavaScript 前端开发
单线程模型
【10月更文挑战第15天】
|
15天前
|
JavaScript API 开发工具
(H5-Web3D-ThreeJS)在网页三维CAD中绘制窗户模型
本文介绍了如何使用mxcad3d在网页中创建一个简单的三维窗户模型。通过官方教程搭建环境,编写绘制窗户模型的代码,并在点击按钮后展示模型效果。最终模型包括窗框和玻璃部分,具备丰富的三维建模功能和便捷的API支持。
|
19天前
|
缓存 API UED
通过渐进式Web应用(PWA)提升用户体验
【10月更文挑战第15天】渐进式Web应用(PWA)结合了传统Web应用和移动应用的优点,提供更快、更可靠和更吸引人的用户体验。本文介绍PWA的核心特性、优势及构建方法,包括服务工作线程、响应式设计和现代Web API的应用,帮助开发者提升用户体验。
|
16天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
13 1
|
29天前
|
机器学习/深度学习 监控 数据挖掘
基于Django和百度飞桨模型的情感识别Web系统
基于Django和百度飞桨模型的情感识别Web系统
33 5
|
2月前
|
消息中间件 存储 NoSQL
剖析 Redis List 消息队列的三种消费线程模型
Redis 列表(List)是一种简单的字符串列表,它的底层实现是一个双向链表。 生产环境,很多公司都将 Redis 列表应用于轻量级消息队列 。这篇文章,我们聊聊如何使用 List 命令实现消息队列的功能以及剖析消费者线程模型 。
90 20
剖析 Redis List 消息队列的三种消费线程模型
|
1月前
|
移动开发 JavaScript 前端开发
HTML5 Web Workers详解
HTML5 Web Workers 允许在后台线程中运行 JavaScript,实现复杂计算而不影响用户界面,提升应用性能。其主要特性包括并行处理、异步通信、独立作用域及多数据类型支持。通过创建和使用 Worker 文件,如 `worker.js`,可执行后台任务,并与主线程通过消息传递机制通信。适用于数据处理、图像处理、复杂计算及网络请求并行等场景。需要注意的是,Web Workers 在浏览器兼容性、安全性限制、调试及资源消耗方面需特别关注。合理利用 Web Workers 可显著增强 Web 应用的流畅度和响应速度。
|
1月前
|
NoSQL Redis 数据库
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
本文解释了Redis为什么采用单线程模型,以及为什么Redis单线程模型的效率和速度依然可以非常高,主要原因包括Redis操作主要访问内存、核心操作简单、单线程避免了线程竞争开销,以及使用了IO多路复用机制epoll。
41 0
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
|
23天前
|
JavaScript 前端开发 安全
轻松上手Web Worker:多线程解决方案的使用方法与实战指南
轻松上手Web Worker:多线程解决方案的使用方法与实战指南
36 0
|
2月前
|
缓存 前端开发 API
探索PWA(Progressive Web Apps)的无限可能
探索PWA(Progressive Web Apps)的无限可能
109 7
下一篇
无影云桌面