1

为什么要读Nodejs源码?

 3 years ago
source link: http://developer.51cto.com/art/202102/645543.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

6vYje2M.jpg!mobile

本文转载自微信公众号「编程杂技」,作者theanarkh。转载本文请联系编程杂技公众号。

前几天有个同学和我说,他在看nodejs源码,但是不知道为什么需要看,也不知道从中可以学到什么。所以今天想聊一下关于阅读nodejs源码的意义。阅读其他源码也类似。

首先,阅读源码的目的无非两个

  • 1 深入了解和理解他或一些底层的原理
  • 2 从中学到一些优秀的设计思想和实践。

如果你没有两个目的,那其实就没有必要去看源码了。那接下来聊一下从阅读nodejs源码中,可以得到什么。

首先我们要深刻理解到nodejs是什么?大家都知道nodejs是一个js的运行时。那么到底nodejs里面有什么呢?每一部分的意义是什么呢?首先nodejs的组成是libuv、v8、第三方库。nodejs的定位首先是一个服务器,所以其实有libuv就可以了。那么剩余的组成部分有什么用?第三方库的作用很明显,就是复用了业界已有的解决方案去拓展了nodejs的一些功能,并不是nodejs的核心。v8的意义是因为nodejs选用了js这个语言,所以就需要一个js的引擎。否则v8也是不需要的,直接把libuv和第三方库编译成二进制就行,类似nginx,redis一样。这个是高层的视图。从底层来看,libuv是对操作系统功能的封装,v8是一个js解释器。那么看nodejs源码的意义就很明显了。nodejs的源码从垂直分为以下三个部分

  • 1 js层
  • 2 c++层(使用v8桥接js和libuv和一些自定义的c++逻辑)
  • 3 c层

读js层,你可以了解到nodejs实现的一些上层的逻辑,虽然js层最后还是依赖底层,但是js层也有很多逻辑,看懂了js层,在使用nodejs的时候,也就能更加深刻地了解到你在做什么,nodejs在做什么。但是js层是远远不够的。因为他只是个壳子。

那么接下来,你就要去读c++层,读c++层的代码,更多的是在了解如何去使用v8。假设你以后想在你的其他项目中单独使用v8,那么nodejs的代码就是一个参考。那么我们了解v8的使用有什么意义呢?这个问题相当于我们使用一个语言,然后了解他的编译器/解释器有什么意义。很多时候,我们都不需要这样做,这完全取决于你的兴趣。如果你以后想使用v8,或者你想了解js实现的底层原理,又或者你想了解一个编译器/解释器是如何实现的。那么你就可以去学习v8。v8首先作为一个js引擎,他里面有一个编译器/解释器的通用逻辑,词法解析,语法解析,代码生成,代码优化等等。然后还包含了js语言本身的实现细节,比如一个js数组,一个js对象,在v8里是怎么实现的。最后,了解v8为我们暴露了什么接口,我们可以使用v8做什么。

最后就是读libuv,nodejs的重点是作为服务器,所以相对来说,读libuv的才是重点,我们都知道v8只是一个js引擎,他没有网络,dns、文件等能力。在前端,js的文件,网络等能力来源于宿主浏览器。在nodejs,这些能力就来源于libuv。这是nodejs为什么叫nodejs,而不叫v8。因为他不只是v8。他还实现了自己的一些功能。所以你也可以实现自己的功能,加上v8的能力,创造出一个新的服务器。言归正传,那么读libuv可以学到什么东西呢?libuv是实现服务器的核心。所以我们可以从libuv中学习到实现一个服务器用到的技术。从libuv官网中我们也可以知道,libuv包括了进程、线程、定时器、文件、tcp、udp、unix域、线程池、dns等等能力,使用到操作系统能力包括进程间通信(管道、unix域、eventfd)、线程池、事件驱动(epoll、select、poll、kqueue等)、inotify机制、文件操作等等,使用数据结构和算法有二叉堆、红黑树、队列等。

总的来说,阅读nodejs源码最直接的是理解nodejs的工作原理和nodejs的本质。如果你是一个nodejs的开发者,这无疑是一个很好的收获。其次,如果你有兴趣,你还可以了解到编译器,操作系统的知识。额外地,你也可以学习到nodejs中的一些设计思想,比如定时器的设计,从早期版本到后来的重构背景。又或者如果你来设计一个服务器,你怎么设计。

从理论上聊了一下阅读nodejs源码的一些看法,下面顺便聊一下我自己的看法和体会。我阅读nodejs源码的原因是非常直接的,因为我希望我成为一个优秀的nodejs工程师。我对v8和libuv本身并没有太大兴趣。虽然我一直是一个前端工程师,但是我也不会去读js引擎的源码。至于libuv,相关的异步io库非常多,而且说到服务器的设计,nginx、redis无疑是更值得读的。但是成为一个优秀的nodejs工程师,深入了解和深刻理解nodejs本身是非常必要的。相对来说,nodejs是非常原生的。很多时候我们觉得读nodejs源码没有意义是因为没有深度或广度地去使用nodejs,可能只是停留到框架层面,复制着业务的最佳实践,成功地避开了一些坑。当你遇到一些难题,却又难以解决,甚至业界也没有解决方案的时候,你就会深刻理解到阅读源码的意义。当然,这种时候可能不会很多(比如https://cnodejs.org/topic/600b9de15d04ac76cf2181a7和https://cnodejs.org/topic/6018f1b103d797fb8e66e71c#6019f31903d7976d1066e9d2等)。

从开始读nodejs源码到现在,我觉得这是一段非常艰难、快乐、深刻的经历。他让我不仅更了解和理解nodejs,也在更高层面地提高了我。虽然我一直在推广阅读nodejs源码、写了很多文章、也和其他同学进行了很多交流。但是并不说明非读源码不可,个人觉得,读源码是一种好的习惯,也是让你变得优秀的方式,但是因为读哪些源码,这个完全取决于个人的兴趣和选择。不要盲目地去读,要带有目的。对个人而言,我是非常感谢nodejs,也非常敬佩nodejs作者和贡献者,但是我觉得我在阅读nodejs源码中,更多的是了解了nodejs的原理,并没有学到太多我想学的东西,v8算一方面,而libuv的内容,我觉得看nginx和操作系统内核可能是更好的选择,但是libuv相比来说可能更轻量,更快了解一个异步框架的设计。

这里顺便提一下nodejs源码分享的事情,有些同学希望我讲得通俗一点,或者结合应用来讲。这里说一下我做分享的一些想法。首先,我是一个在nodejs源码中学习的人,而不是站在nodejs之上的人,这意味着我也在慢慢学习,并且因为时间关系,我没有办法像图解系列,码农翻身一样讲得那么好那么易懂。因为我的初衷其实是做个笔记,然后分享给有兴趣的人,然后大家一起来做这个事情。我不是大家的老师,这也不是我的初衷和目的。我几乎都是免费分享内容、免费答疑。但是却很少碰到真正的志同道合者,大家还希望我讲得通俗易懂这对我来说就未免太难了。我承认如何讲好技术,做一个好的分享是一个值得学习的事情,但是我觉得这不是我现阶段的目的。而且我觉得一个有上进心的程序员,自己多动一下手和大脑,这个要求并不过分。一人之力有限,希望大家明白。

最后,提前祝大家新年快乐!对nodejs感兴趣的同学也可以找我一起交流学习!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK