1.为什么要开始用nodejs, 而不是php
理由有三点:
因为我是前端程序员出身,nodejs都是用javascript写的,这样相当于前端和后端都使用javascript,开发更加有效率。当然很多网友提到这里有一个悖论,就是虽然是同一个语言写的框架/类库,但不依靠文档还是不会用。然而不可否认的是,相同的语言基础确实降低了理解的难度,这一点不可忽视。
nodejs是现在最流行的短平快web后端开发技术,解决大规模I/O问题及其高效,其社区也非常火。使用sailjs+nodejs可以快速开发原型。举个例子,咱们的服务器后端肯定要定义一个用户对象,并在数据库中存取数据。php+codeigniter只能定义对象后,一个一个写对应的增删改查的rest API。使用sailjs+nodejs方案,只需要在后端定义这么一个用户对象,那么可以自动地生成对这个节点对象的增删改查的rest API,极大提高开发效率。
据说在程序员之间引起战争,最简单的办法就是发个帖子赞美php打压其他后台脚本语言,然后其他语言的爱好者就会一拥而上,帖子点击轻松破万有木有。事实上php经过这么多年的发展,其实能做的比我们想象的要多得多——能做的都做了,不能做的创造条件也做了。例如新浪大部分服务都是php实现的。在计算机界,比起硬件的更新换代,编程语言的变化又慢又不明显。我对php应该是有感情的。但是事实上,后端我通常都是有人帮忙,我专心做前端,所以php我并不是特别熟练。当面临要单干的现状时,我迫切地需要一种可以最大限度扬长避短的方案。何况追求新技术跟研究老技术其实并不矛盾。既然如此,不如直接上nodejs。
2.javascript后台运行效率是否比较低?
nodejs这个服务器端javascript框架出现后,很多人质疑其效率是否比较低。这也很正常,因为javascript本来就是是用C编写的前端脚本语言,本身依赖解释器运行,运行效率当然没有编译运行的C高——但是不要忘记,php, ruby, python,大家都是解释型脚本语言。nodejs在服务器端后台使用的是V8引擎,V8在运行之前将JavaScript编译成了机器码,而非字节码或是解释执行 它,以此提升性能。更进一步,使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript程序与V8引擎的速度媲美二进制编译。现在主流的动态语言里面,执行效率排序大概是 JavaScript > Python > Ruby (假设用常见的解释器:V8、CPython、MRI)。下文还有更深刻的例子,摘自知乎。
总而言之,你可以看到,作为服务器,nodejs是足够快了。其在解决高并发访问方面相对php有相当优势,npm模块化令其安装方便,因而现在已经有很多公司企业采用Nodejs进行开发,github的node项目上详细列举了使用node开发的程序https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node,我认为从09年到现在,node可以说已经是比较成熟的技术方案了。
但是,nodejs主要解决的是并发访问问题,对大规模服务器端计算并没有特别的优化。这里javascript的确有些弱势,
其一:javascript这类弱类型解释型语言,计算效率不高。例如计算最大质数的问题,javascript比java要慢1,2个数量级 ,这还不算浮点数精度差异。(事实上,计算最大质数的问题一般都是都是用C语言+分布式计算来处理。)
其二:nodejs是单线程的,任何 CPU密集型操作会削弱掉 Node通过事件驱动、异步 I/O 模型等等带来的在吞吐量上的优势,因为当线程被非异步的高计算量占用时任何传入的请求将被阻塞。 这意味着丧失了node的高并发优势,同时带来高延时。
对此的解决方法,有两种:
其一:可以对于关键计算的模块,可以采用java甚至C/C++来写。将繁重的计算转移到更合适的语言写的后台进程来处理,同时让他们通过像 RabbitMQ 那样通过消息队列服务器来进行通信,这是最常见的做法。(我坦言C/C++我写不了,没有经验)
其二:涉及到服务器上多核并发处理,Node 的核心团队已经使用 cluster 模块的形式在这一方面做了一些工作 (参考:)。当然,也可以很容易的通过 nginx 的反向代理运行多个 Node.js 的服务器实例来避免单一线程阻塞的问题。这样的设置有很高的可扩展性,例如一开始的时候可以在一台服务器上运行多个实例,等计算量大时就可以分配到多个节点服务器上运行。用 Node.js 你可以得到很高的吞吐量,每个请求都作为一个小任务非常迅速和高效地处理。