乐趣区

Deno源码简析一架构

开始

感觉又很久很久没写东西了,心里有点忐忑不安:一直埋头工作而不去学习新知识可是程序员的大忌,刚好 Deno 又正式发布 1.0,所以忙里偷闲也要学习一下,那么今天就是带来一波简单的 Deno 源码分析。

Deno vs Node.js

有人说 Deno 就是 Destroy Node 的缩写就是为了替代 Node.js 而生,也有人说 Deno 目前不成熟并不能替代现在的 Node.js 等等;自从 Ryan 指出 Node.js 的十大问题并且公开了新的项目 Deno,在某乎上立马就展开各种(友好)讨论。不过无论怎么样,有竞争才有进步,Deno 已经作为一个挑战者走进我们的视野,我们只需客观正视它的优缺点就好了。
不过个人的一些看法,Deno 的出现基本意味着这是一场死斗,因为彼此基本特性实在太相似了:v8 引擎,单线程异步,背靠着 js 的生态圈 …,基本意味着开发者选择两者其一就永远不需要考虑其二,长远来看用户群可能会分裂吧;而 Deno 目前在这个基础上主打的是稳定性和安全性,这是服务端开发所必须的,只有满足这两个要求基础上才能去追求更高的性能,所以现在 Deno 的性能从官方的测试来看跟 Node.js 比还是有一段距离,但是个人并不太担心这一块性能差距,迟早也是会慢慢赶上来的,毕竟才 1.0 嘛。

前置知识

准备深入 Deno 部分知识还是要提前准备一下的:

  • Typescript(对于前端开发大多没啥压力)
  • Rust(主打安全和高性能的语言,学习曲线奇高,长期被编译器教做人)
  • V8 引擎(Isolate,Context,Handle 等等概念常记心里)

不得不说,其实 rust 就是 Deno 和 Node.js 分界点,感觉 Deno 的一个潜在目标就是把 Deno 的生态与 rust 的生态捆绑在一起,这样 Deno 一开始的生态比较弱的问题也可以得到一些缓解吧,另外对于前端来说迟早也是需要学习一门静态语言的,rust 也是一个不错的选择(rust 可是 StackOverflow 最受欢迎的语言)。

Deno 的架构

直接贴上官网的架构图:

这里官方的架构图还没来得及更新,libdeno 已经替换成 rusty_v8,这样意味着我们开发 native 插件的时候可以完全绕过了 c /c++,直接使用 rust 就可以完成功能开发(加上 rust 本身自带一个可靠强大的标准库更加得心应手),当然开发者还是需要了解 V8 引擎相关的知识了。
再回到架构图上,我们知道 Node.js 是由 libuv 提供调度和 io 的能力,那么在 Deno 上这个角色就由 rust 的 Tokio 库提供相似的能力,而一开始 Deno 还是想使用 go 语言来提供这样的能力(Ryan 果然是 go 语言的真粉),但是毕竟 go 语言也是带 gc 的(一个应用上同时跑两个 gc,稳定性实在很难想象)而且性能上也是差 rust 一截,后面替换成 rust 也是相当明智的,另外 Tokio 其实对比 libuv 也是毫不逊色的(任务调度算法也是参考了 go 语言的实现)
另外在 Deno 里面 js 与 rust 的交互都会通过 Deno.core.send 和 Deno.core.recv 这两个方法,这样做对于应用做审计和权限控制是非常有好处,后面再会分析 js 和 rust 是如何交互的。最后例如 js 异步读取文件这些操作都会扔到 Tokio 线程池中执行,这也是 Deno 实现非阻塞的关键点。
然后 Deno 为了安全的原因,对资源都做了一层映射,原本系统的文件描述符或者其他资源都映射成了一个 rid(非零整数),对资源的操作都需要通过 rid 进行。

|                       **Linux** | **Deno**                         |
| ------------------------------: | :------------------------------- |
|                       Processes | Web Workers                      |
|                        Syscalls | Ops                              |
|           File descriptors (fd) | [Resource ids (rid)](#resources) |
|                       Scheduler | Tokio                            |
| Userland: libc++ / glib / boost | https://deno.land/std/           |
|                 /proc/\$\$/stat | [Deno.metrics()](#metrics)       |
|                       man pages | deno types                       |

好吧,把所有的概念汇集在一起,跟 Linux 一对比,就会发现 Deno 真的很有意思了,难道是想要变成一个轻量级 js 应用平台吗?官方文档透露的信息实在太少了,感觉一些设计意图也没有表达出来,希望文档能够再详细一点就好了。

项目结构

.
├── cli // 负责实现各种接口,包括兼容浏览器的和 Deno.xxx
├── core // 负责实例化和执行模块代码,处理 js 与 rust 之间交互还有实现 event-loop
├── deno_typescript // 负责编译打包 typescript 文件和生成 v8 的 snapshot
├── docs // 文档
├── std //std 标准库
├── target
├── test_plugin
├── third_party
└── tools

自己再整理里面各个模块的依赖关系,大致如下:

当然发现更有趣的是 std 目录下还有有一个 node 的模块:

.
├── README.md
├── _fs
├── _utils.ts
├── events.ts
├── events_test.ts
├── fs.ts
├── global.ts
├── module.ts
├── module_test.ts
├── os.ts
├── os_test.ts
├── path.ts
├── process.ts
├── process_test.ts
├── querystring.ts
├── querystring_test.ts
├── tests
├── timers.ts
├── util.ts
└── util_test.ts

是不是看到这些文件名称就有一种相当熟悉的感觉,嗯,这就是 deno 为了兼容 node 模块所做的一个兼容层,虽然还没有完成,不过至少也知道 deno 也是有这个意愿去兼容 node 的模块,或许在下一个版本我们就能看到 deno 能够直接使用 node 的模块去开发应用了。

结束

暂时先介绍到这里,好像一点也没有深入到代码,真的是标题党,哈哈,下一篇文章再来深入代码分析。

退出移动版