用了4年多的node.js,再去阅读《深入浅出Node.js》这本书,发现别有一番滋味。接下来我将用几小篇文章重新带大家领略Node.js的风采。
故事要追溯到2009年3月,28岁的美国程序猿Ryan Dahl宣布要基于V8创建一个轻量级的Web服务器并提供一套utils,之后他仅仅花了两个月时间,也就是当年5月份就发布了第一个版本。
2010年年底,就拿到了硅谷云服务商Joyent的赞助,他也加入了Joyent并全职负责Node的发展。可以看得出,他是一个能力很强并且很有天赋的程序猿,通过查看Wiki发现,他6岁的时候他妈妈就给了一台苹果电脑(Apple IIc,如下图)给他,拿到电脑他不是第一时间拿来打游戏,而是拿来研究技术。因为他对技术的热爱,后面他进入了罗切斯特大学(University of Rochester)学习数学专业。
这东西为啥叫Node呢?为啥不叫什么D语言、E语言呢?起初,这个项目是叫web.js,也就是一个Web服务器,但项目的发展很给力,渐渐变成了基础框架,大家可以在它的基础上构建更多的东西,例如服务器、客户端、命令行等工具。它自身非常简单,而且易扩展,大家可以通过统一的规范来构建大型网络应用。每一个Node进程都构成这个网络应用中的一个节点,这就是为什么它叫Node.js。
那Node.js有哪些特点呢?总结下来有4点,异步I/O、事件与回调函数、单线程、跨平台。
一、异步I/O
我们知道对于Java语言,程序语句是一行行执行的,但是对于node.js来说,底层有很多异步I/O的API,包含文件读取(https://nodejs.org/dist/latest-v12.x/docs/api/fs.html)、网络请求(https://nodejs.org/dist/latest-v12.x/docs/api/http.html)等等,每个调用之间无需等之前I/O调用结束,这样的意义在于,我们可以从语言层面很自然地进行并行I/O操作
二、事件与回调函数
对于Node.js来说,我们处理请求,只需要关注成功和失败的时候的业务逻辑即可,在多个异步任务的场景下,事件与事件之间各自独立,具有轻量级、松耦合的特点。但这样的设计对于如何协助是一个问题,它和常规的同步方法相比,变得不是那么一目了然。后期我们可以通过一些方法可以解决这个问题,比如promise、async/await。
三、单线程
Node.js保持了Javascript在浏览器中单线程的特点,它最大的好处是不用像多线程编程那样处处在意状态的同步问题,没有死锁的存在,也没有线程上下文交换带来的性能上的开销。但它也存在一些缺点,比如无法利用多核的CPU,错误会引起整个应用退出、对于CPU密集型的事件需要等待计算任务完成才能重新到事件循环取事件。
四、跨平台
起初,Node.js只能在Linux平台上运行,后面随着Node.js的发展,微软帮助了它实现了Windows平台的兼容,在v0.6.0的时候已经可以在Windows上运行了。这得益于中间的这层libuv,它是一个可以在许多平台上实现跨平台的基础组件,Node的第三方C++模块也可以通过libuv实现跨平台。
由于Node.js具有以上四个特点,那么它的应用场景有哪些呢?第一个当然是需要高性能I/O的实时应用,比如聊天工具,花瓣网、蘑菇街的实时通知功能就是通过socket.io来实现的;第二个是利用并行I/O高效利用分布式环境,比如eBay的ql.io就是借用Node并行I/O的能力,高效地利用已有的数据。第三个是利用稳定接口提升Web渲染能力,例如LinkedIn的移动版网站就摒弃了同步的方式,利用并行I/O加速数据的获取,提升Web渲染速度。
参考文献:
1.Ryan Dahl介绍:https://en.wikipedia.org/wiki/Ryan_Dahl
2. ql.io的代码仓库和发布会:
https://github.com/ql-io/ql.io
https://tech.ebayinc.com/engineering/announcing-ql-io/
3.Event Loop +V8 Engine + libuv threadpool
https://medium.com/@chaudharypulkit93/how-does-nodejs-work-beginner-to-advanced-event-loop-v8-engine-libuv-threadpool-bbe9b41b5bdd