Node.js仅仅是个过渡方案?

文章翻译自:http://www.philipotoole.com/is-node-js-just-a-stopgap/?utm_source=nodeweekly&utm_medium=email


Node.js总有些不太对劲的地方。我编写Node.js程序至今已经有一年时间,总体感觉编写Node.js程序是很有趣的,但我认为Node.js只是个过渡性方案,在需求出现而没有更好的解决方案时的权宜之计。


利用Node.js编写网络程序?so easy!

毫无疑问,Node.js在某些方面还是很值得赞赏的。不久前,我用Node.js写了一个高性能的系统日志收集器(Syslog Collector),该程序1秒能处理和解析25万条日志记录。这个日志收集器利用了数千个同时发起的TCP连接来实现功能,同时也支持UDP,HTTP和SSL。该收集器由C++写成,且使用了Boost库里面的ASIO框架。这个收集器从没崩溃过,也不存在内存泄漏的问题。但从程序编写(包括重写),测试到部署,我花了整整5个月的时间!所以要讲开发的速率的话,掌握如何编写相似的Node程序是个很核心的技能。

想搭建HTTP服务器?调用http模块即可。同样地,调用net模块,你就可以使用socket server了。加之Node.js天然的以事件驱动为框架的特点,相比传统的线程—每次—连接的模式,在性能上也高出来不少。Node.js以与Twisted等网络框架全然不同的方式流行了起来。


那么,Node.js到底哪里不对劲呢?

JavaScript

首先,让我们从JavaScript说起吧——我很喜欢它的闭包特性,但不得不承认,这门语言还是有挺多坑的。甚至很多核心的JavaScript程序员也经常拿它来开玩笑。有这样的段子,如下图所示,看图即可明白笑点所在。



图1.Javascript VS Javascript:The Good Parts

并且更让人费解的是,在Node终端(REPL,Read-Eval-Print Loop)里,像如下的输入是合法的:

undefined=42

像下面这样,会输出啥呢?

> []+[]
' '

为什么一个空的数组加上另一个空的数组不等于一个空的数组,正如Python中所做的那样呢?

还有这个:

>[]+[]*5
'0'


很难理解为什么JavaScript会设计的这样不统一(译者注:作者这里的意思是:[]+[]结果为‘ ’,而[]+[]*5结果为‘0’,基本同样的操作得出迥然不同的结果,表现出设计的不一致性)。看起来JavaScript像是给1千亿只猴子设计的语言。Node终端可以接受这么多的输入,以至于输入任何的内容,你可能得到真的可以运行的程序!

很显然,JavaScript不像Java那样要敲很多代码才能实现一个功能,但至少Java让你知道两个月后你在哪。

Debugging

在我见过的所有Node.js开发人员里,无一例外都是用最原始的方法来调试程序。没有太多可以利用的调试工具让开发者感到很沮丧。在像MochaChai这些单元测试框架下,追踪回调函数的整个调用过程简直就是一场噩梦,为了找出错误所在,开发者通常需要花费好几个小时。debug时唯一的所有人可以使用的开发工具,估计只有console.log()了。

Callback Hell

大多数程序员,在开始编写Node.js的36个小时内,就会发现所谓的“Callback Hell”。甚至有一个完整的网站来教程序员们如何来避免这个问题。而出人意料的是,像异步性、事件驱动这些让Node.js实现了高性能的部分,也是大多数Callback Hell的栖身场所。

但是我们有Promises,你这样反驳我的观点。这一点我同意。如果不是其在像Bluebird这些模块中的不可或缺的地位的话,我想大多数开发者早已经抛弃它了。我非常喜欢Promises——欣赏其实现回调的优雅代码。将一列promises链接起来 是一种精巧的实现方案,也是富有启迪性的。事实上,Promises是如此的优秀,以致于你都忘了它们是为了解决callback hell 而存在的。而我认为,callback hell是影响Node.js在关键性生产环境中使用情况的重要因素。


我会挑我喜欢的Node.js的核心特点,但只会挑一个

Node.js总是以单线程运行。这使得其在不同函数和不同模块之间交换和共享数据变得异常容易。这并不意味着各个模块之间没有了对CPU资源的竞争,而是意味着当修改了任意一个模块后,你的代码执行不会被打断。但如果你的Node程序运行内存超出了单个CPU核的最大内存,你该怎么办?即使你的机器是多核的,你也没法使用该线程所在CPU核以外的其他核,这时候就杯具了。当然,这里有基于集群的Node.js,但当下还处于试验阶段,而且如果要使用它的话,你得修改很多的代码。而且更根本的问题是:由于Node.js的单线程性,你的程序从始至终都没有考虑过如何通过多核来实现,即使一台机器上有多个CPU核。


那么,Node.js的替代者会是谁呢?

在现代编程中,编写针对网络和分布式系统的高性能的程序已经显得异常重要,而且最小化内容交换的编程框架——比如,Node.js——的兴起也让我们搭建高性能服务器变得异常简单。但是比Node.js更好的可选方案肯定存在。

一个可能的替代方案是Go,其强大的标准库,对网络编程的天然支持,使得搭建服务器像Node.js一样简单。Goroutines让程序员摆脱了Callback的困扰,用一种更加符合程序员的直观想法的方法——线性方法——来实现。而且在底层,Goroutines是如此的轻量级,以致于其交换内容甚至比系统线程都少。而Node.js设计时就没有考虑使用系统线程级别的内容交换。

Go 还可以很容易就使用多核处理器的优势,这是Go设计语言的集成部分。我用Go语言写了一些重要的程序,整个编程体验就比Node.js爽多了。


一家之言,难除谬误,还请参照其他内容

说实话,我在Node.js和在JavaScript上的编程经验都没有在C,C++和Python上那样多,但我的直观感受——还有其他人的(和其他人的,和其他其他人的)——告诉我Node.js不过是在网络编程方面向更好的实现方案的一个过渡性作品。Node.js做了很多出色的工作——而且我很自豪我掌握了Node.js这门技能——但应该还有比其更好的方案。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值