新知一下
海量新知
5 9 9 1 3 7 0

Electron 架构揭秘

前端食堂 | 你的前端食堂,记得按时吃饭。 2020/10/29 15:09

彩蛋

昨晚搬砖回家看到 Peter 发了条朋友圈,腾讯云游戏平台 START 公测发布,他在用 MAC 打 LOL。我紧随其后体验了一波,毕竟 LOL 是我们这代人的青春,工作后很少有时间玩,用上 MAC 后,之前的游戏本也放在箱底很久了。

选个 EZ 浪一浪~(天赋都没来得及换)

新知达人, Electron 架构揭秘

20 分钟轻松拿下首胜(毕竟 s2 老玩家了,匹配局常规操作),综合体验还是很不错的,家用网速下基本感觉不到延迟,除了窗口模式下调整视角时鼠标有点难受之外。(想要体验的同学记得先把触发角关了)

云游戏平台这种“云”模式彻底解放了“跨平台”的想象力,随着 5G 的到来,它有没有可能是未来解决跨平台的最佳方案呢?对我们前端工程师来说,等待我们的又会是什么新的挑战呢?欢迎同学们留言一起探讨~

书归正传,最近手头在做 Electron 的项目,Electron 为了实现跨平台做了很多努力。(刚好可以与云游戏平台这种模式形成对比。)下面我们来一起看一看。

浏览器架构演进

新知达人, Electron 架构揭秘

我们先从浏览器架构演进开始说起,日益复杂的业务需求不断 push 着浏览器架构不断的演进和迭代。

拿我们最喜欢的

Chrome

举例,从 2007 年以前的单进程架构到现在的多进程架构,浏览器因为架构的调整, 变得更加稳定、更加流畅、更加安全。目前你能看到的最新的

Chrome

浏览器应该包括如下进程:

  • 1 个浏览器(Browser)主进程

  • 1 个 GPU 进程

  • 1 个网络(NetWork)进程

  • 多个渲染进程 (运行在沙箱模式下)

  • 多个插件进程

新知达人, Electron 架构揭秘

不过,软件工程没有银弹。浏览器的架构体系也随着调整变得更加复杂, 也会有更高的资源占用。

如何寻求一种在资源占用和复杂架构体系之间的平衡便成为了一个难题。

「小孩子才做选择,鱼和熊掌我都要!」

Chrome 团队在 2016 年使用“面向服务的架构”(Services Oriented Architecture,简称 SOA)的思想设计了新的 Chrome 架构。

Chrome

团队将模块重构成独立的服务 (

Service

),服务运行在独立的进程中,想要访问的话必须使用定义好的接口,通过

IPC

来进行通信。这样的架构无疑更加内聚、松耦合、易于维护和扩展。

Chromium 架构

新知达人, Electron 架构揭秘

Chromium 是

Chrome

的开源版,也是一个浏览器。

  • 主进程的

    RenderProcessHost

    和 渲染进程的

    RenderProcess

    专门处理

    IPC

    事件。

  • 渲染进程的

    RenderView

    :我们的页面就是在这里基于

    Webkit

    排版展示出来的。

  • ResourceDispatcher

    处理资源请求,当页面需要请求资源时,通过

    ResourceDispatcher

    ,创建一个请求

    ID

    转发到

    IPC

    ,在

    Browser

    进程中处理然后返回。

Electron 架构

新知达人, Electron 架构揭秘

  • 在各个进程中暴露了

    Native API (Main Native API、Renderer Native API)

  • 引入

    Node.js

这样,在

Electron

中就可以使用

Chromium

Node.js

做好玩的事情了!

不过在此之前,还有一个难点需要解决:如何将

Node.js

Chromiums

整合?

Node.js

事件循环基于 libuv,但

Chromium

基于 message_pump。

解决这个问题的的主要思路有两种:

  • 1.将

    Chromium

    集成到

    Node.js

    :用

    libuv

    实现

    message_pump

  • 2.将

    Node.js

    集成到

    Chromium

第一种方案,NW.js 就是这么做的。

Electron

前期也是这样尝试的,结果发现在渲染进程里实现比较容易,但是在主进程里却很麻烦,因为各个系统的

GUI

实现都不同,

Mac

NSRunLoop

Linux

glib

,不仅工程量十分浩大,而且一些边界情况处理起来也十分棘手。

后来作者另辟蹊径,再次进行尝试,用一个小间隔的定时器轮询

GUI

事件,发现

GUI

响应的非常慢,

CPU

也爆表。

直到后来

libuv

引入了

backend_fd

的概念,相当于

libuv

轮询事件的文件描述符,这样就可以通过轮询

backend_fd

来得到

libuv

的一个新事件了。也就是第二种思路,将

Node.js

集成到

Chromium

如果你想了解更多,也可以去看看下面作者的这个知乎回答~

  • 维护一个大型开源项目是怎样的体验?

    https://www.zhihu.com/question/36292298/answer/102418523

新知达人, Electron 架构揭秘

小结

Node.js

集成到

Chromium

中的原理:

Electron

起了一个新的安全线程去轮询

backend_fd

,当

Node.js

有一个新的事件后,通过

PostTask

转发到

Chromium

的事件循环中,这样就实现了

Electron

的事件融合。




更多“架构”相关内容

更多“架构”相关内容

新知精选

更多新知精选