node.js成也异步,败也异步,评node.js的异步特性

node.js最大的卖点就是异步,声称以此获得更高的性能,而我认为,node之所以快并不是因为异步而快,而是因为V8而快。异步仅在资源占有明显优势,而引入异步却大大增加了编程的复杂度,且异步在http服务上并没有或者无法用在刀刃上。

以目前node来看,其作为单独http服务器的实现远远不如nginx,若以node建站,更普遍的选择是nginx 反向代理 node,一则由于node作为http服务器功能简单,实现更是差nginx几个台阶,其次因node单线程特性,若要发挥多核的优势,也必然会开2个以上的node进程,由此nginx + node几乎是首选模式,如果使用cluster,可以达到不错的性能,但也是因为简单而快,非异步的优势。相对于nginx + n * php-cgi模式,其工作模式近似看成 nginx + n*65535*node,n*65535*node为假想的大量worker,n为node进程数。

首先看传统的 nginx + 50*php-cgi 工作模式。
如果使用php-fpm进行fastcgi spawn,那么平每个空php-fpm基础占用物理内存6.4M,50个php-cgi则占用了 320M + 每个请求占用的内存。
而nginx + 4*node,占用的内存仅为 52M + 每个请求占用的内存 。

同样100个worker会有100个不同的持久化连接,而node可以通过各种connections pool,使其共享持久化连接,大大减少其总连接数,node可以在任意时刻把一个连接取出或放回连接池而几乎没有性能上的损失。

这也是node异步资源上的优势。而除此之外,异步并没有想像中的这么美。

一、 异步在http服务器上表现

1. 充分利用等待时间的谎言

先看完整一次http请求,花费的时间可能是
40ms 服务器从客户端连接并接收数据
5ms 各类数据传输与接收
2ms 数据处理
1ms rendering
10ms 服务器向客户端发送数据

由此可以近似看成 55ms等待时间 + 3ms 数据实际处理时间。
但由于nginx fastcgi buffer,upload等的存在,对于php-cgi实际等待时间仅为 5ms,如果数据库处理的很糟糕,等待时间则延长为 50ms,由于存在50个worker,那么相当于每个worker延长了1ms,所以node的充分利用等待时间本身就形成了一个伪命题。由于1ms的等待那么php-cgi将占用的cpu最大为75%,等待中的25%,正好可以给系统其它进程所利用,似乎也物尽其用。且若是CPU真得持续跑在50%以上了,那也到了不得不升级硬件的时候了。

2. 无法出众的http性能

node作为独立服务器,可以达到不俗的性能,而由若与nginx配合,对比nginx + php-cgi中并没有占到太多优势。在不同机器上快约-10%~25%不等,差距并不明显。若是完整用例的快,是因为V8的出色表现,和异步与否并没有太大的关系。

3. 艰难的异步之路

并不是说异步难写,而是相对于同步来讲,如今有各种异步实现模型,其跟本的目的也是简化异步实现。而异步再简化,再优雅都还是异步,易用性比起同步来讲仍然是天地之别。用繁复的异步换取不多的性能提升,实在是得不尝失。

二、 node异步的用武之地

批判了node的异步,但异步也并非一无是处,worker无法很好胜任的场合是异步的舞台。

各种需要要持久化连接的非http连接的服务器,如网游服务器。

大量远程api调用,假设每次请求都会有2~3次通过服务器的远程api调用,那么每个请求会有400ms以上的等待时间。而这类请求数量过多,会导致阻塞了普通动态页面请求。需要增大的worker数量,或者使用不同通道的worker。但显然没有异步来得实惠,而且这类请求逻辑通常不会复杂。

简言之,如果传统的线程池或者多进程worker,数量不得不达到100以上,那么就是异步的用武之地了。

三、 一组hello world的测试

在四核 AMD Phenom 9650 下的一组最简单的hello world的测试结果
nginx + node sock

var http   = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen("/tmp/node-"+process.argv[2]+".sock");

node + cluster

var http    = require('http');
var cluster = require('cluster')
var server  = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
});
cluster(server).listen(1337);

及php

<?php
echo 'hello world';

测试结果如下,单位(rps)
20并发与100并发

siege -c 20 ab -c 100
node + cluster 12548 19194
nginx + 5*node sock 7260 12803
nginx + php-fpm 8400 11242

无并发

siege -c 1 ab -c 1
node + cluster 6019 6535
nginx + 5*node sock 3024 3830
nginx + php-fpm 3839 4297

从测试结果可以发现,node + cluster 最快,nginx + php-fpm 次之,而nginx + node sock最慢。
也意味着 php-fpm 甚至快于 node sock,而cluster因其功能简单,node又没有php般完整http请求初始化,综合评价,node的底层实现不出众,异步优势更是无法得到充份的体现,

有人会说,hello world没用到异步,只是对入口的测试,对于单连接,同步在性能上并不会弱于异步,异步的优势只能在大规模持久连接或大延迟中才能得到体现。正如我上文充分利用等待时间的谎言所述,我对node与php下PostgreSQL查询性能比较,两者性能是几乎一致的。而php下memcache的实现就很不如意,比起异步还是同步更多取决于语言本身,不过这些不在本文讨论范围之内。本文主要讨论node的异步在http服务下情况,而非node vs php或者v8 vs php,

四、 小结

本文不否认node快,但快与异步与否并没有太大关系,只因node简单,更重要的是其背后的v8引擎。对于逻辑复杂的网站,抛开异步是更佳的选择。

共2条Pingback
共42条评论
  1. heywap @ 2011-11-23 10:40:11 回复

    据我所知,异步根本不能减少程序的运行时间
    不会因为你启动了一个异步,查询数据库的时间就会从10ms减少到5ms
    无论是同步还是异步,执行的时间依然是10ms
    异步的作用仅仅是提升了应用程序的吞吐量。这才是关键

    你的观点我基本上同意,但是这句话应该修改一下
    node之所以快并不是因为异步而快
    我认为说到node“快”的命题不是成立的

    如果说sqlserver2005以后的产品是“默认安全”的
    那么可以这样描述node

    默认低复杂度(征对线程开发来说)
    默认高吞吐量(线程池、异步)

    • JiangMiao @ 2011-11-23 13:14:42

      只要是非可持续连接,即非websocket,非网游tcp服务器等的传统的http连接,高吞吐量上node不占优势,前端nginx同样可以很好的吃下任何数量的并发连接,并合理分配到数十至数百个工作进程进行处理。

      由于系统到一定时候,数据库多数会采用独立服务器,而node众对异步上的支持在于查询数据库到得到结果中会有10ms的等待时间。而这10ms异步的话可以干些另的而非傻等着。

      node快肯定能成立,任何使用node与php的开发过完整应用都可以得到此结论,也正因为如此大家若受官方的文档所介绍影响而把功劳归结于异步,也是本文所要反驳的。因为除了异步部份没有明显优势外,由于v8引擎是php的数倍性能,比如node使用js渲染页面,只需0.1ms,10倍于纯php脚本的执行。页面达到一定复杂度,语言上的性能优势会逐渐突显。不接任何前端的node虽与nginx差据甚远但还是可以发挥出1倍以上之于的nginx+php-fpm的性能。反之,只要接任何前端,就只剩下语言优势了。

      关于复杂度,我一点不觉得node低复杂度,我们对复杂度的理解可能不一样。我认为异步开发是复杂的,异步流程,异常处理,资源释放等都需要特别对待。
      node是单线程,没有线程池,在cluster等帮助下可以多进程,但无论未来node怎么进化,只要v8不变,linux下只能是多进程协作,比如在现有node外加上一个壳作主控制进程,原node fork多份作工作进行以利用多核特性。

  2. heywap @ 2011-11-23 15:07:13 回复

    我们对复杂度的理解可能不一样
    是的,我很认同这样的话。

    对于一般的前端开发人员来说,可以使用相同的语法可以开发后端应用,应该来说是个很大的跨越。
    我同样认同异步开发是复杂的,线程,线程池,资源争用等等问题,正是因为这些我才说一个前端开发人员可以很快的开发一个后端应用,我所以说是低复杂度的。

    您可能有一些误区,因为js只能运行在单线程下,所以node执行js也是单线程的,这不是node的错
    虽然node是单线程执行,但是v8中可以使用多线程,所以node执行js是单线程,但是io操作是多线程的。据我所知,事实上就是是使用线程池。

    • JiangMiao @ 2011-11-23 17:23:04

      相同的语法开发后端本也是我想驳的一条,因为后端和前端区别不仅仅是语法,语法比起后端的知识体系根本是微不足道。但考虑到这的确是优势,一者两者用的库都相同,比如underscore前后端通用,再者不需要深入学习后端就可以用一些如socket.io之类的进行前后端交互,的确有可取之处,也是一大跨越。但是我还是想说句,后端没有捷近,对于js熟手,php语法只要30分钟内就可以掌握,可这又有何用,一切只是开始。

      同步会遇到各种资源争用的冲突这只是前端开发人员对后端恐惧的说词或环境搭设不利所至,在现在温室环境,不到大规模应用后端很难会遇到上述情况。况且进程同步手段繁多,而且IPC,mutex等进程,线程间调度是必备技能,虽然在传统网站开发基本上用不到,比如wordpress全代码都不见有进程控制相关的代码。

      V8不可能多线程,是由V8自身架构所决定的,Context与Handle堆都是全局变量,多线程调用V8函数,必然会使其冲突,虽然用isolate可以进入临界域避免冲突,但从外围来看将与同步单线程无异,多线程应用V8是非常不明智的,频繁进isolate只会降低性能。由于Linux中AIO实现不理想在文件IO中采用线程池,这是无奈之举。而Socket IO使用epoll或kqueue,根本不需要用到多线程,异步本身的设定就是用于取代多线程,最主要归根到最后node对于event的处理需要调用v8函数,那将仍然是单线程。并不是有多个线程在运行就是多线程。拿v8举例,单线程是共识,而实际上v8也有2个线程,一个工作线程,另一个线程进行gc等处理。

  3. heywap @ 2011-11-23 21:56:36 回复

    听您一席话很受教。。
    这里有一篇文档http://cnodejs.org/cman/addons.html这里有说到线程池的使用。
    希望有机会可向您多请教一些问题。

    • JiangMiao @ 2011-11-24 14:44:54

      文档中的libeio使用线程池进行IO处理实际上是aio的实现或许叫模拟更合适,主要用于解决异步文件IO问题。libev IO事件通知机制的跨平台库,一般单线程使用,各个平台有各自实现,比如Linux可以使用epoll,BSD使用kqueue等封装,可以支持Socket IO,inotify,计时器等,也是node的核心。那个文档已经有点老了,新技术就是变化快,现在joyent把eio和ev封装改进成libuv了。
      请教不敢当,技术方面问题我还是乐于探讨。

  4. Heron Huang @ 2012-01-08 16:25:09 回复

    没看到正确的技术论点,看到更多的是两个人相互吹捧。
    不过可惜了,Node不是单线程的. Javascipt是单线程的没错,但是Node.JS的avaScipt实现的只是回调模块,不是执行主线,所有的回调是底层的多线程C模块发起的,这才是Node异步的精髓。

    • JiangMiao @ 2012-01-08 18:40:05

      Node是否多线程参见上面对于libuv的描述。
      实际上不需要任何异步理论知识,也可从种种迹象看出Node的单线程特性。
      1. Node中没有thread相关的API。
      2. 没有Cluster的Node即单进程的Node只能利用到一个CPU,这也是为什么会有Cluster的原因。

    • JiangMiao @ 2012-01-08 18:43:42

      现在cluster并到Node中,从文档中也可以读到对Node单线程的描述
      http://nodejs.org/docs/v0.6.7/api/cluster.html
      ‘A single instance of Node runs in a single thread. To take advantage of multi-core systems the user will sometimes want to launch a cluster of Node processes to handle the load.’

    • Leric @ 2012-02-14 11:23:37

      Node是单进程单线程的,这个没什么疑问。所以程序里任何变量都不需要考虑锁的问题,因为不会被打断。

  5. Leric @ 2012-02-14 11:20:32 回复

    在我的测试里,Hello World程序Node比Nginx+PHP-FPM快3倍,用上Express加Jade的速度也是PHP裸奔的150%,这部分是V8的作用。
    1000并发下Node最慢的相应速度是3s,PHP大量出错
    100并发下Node最慢相应不到1s,PHP10s
    这部分是异步的作用。

  6. my @ 2012-03-07 19:05:37 回复

    你好,我想为移动项目(社交类应用)后端选择一种语言,不知道Node.js合适吗?不合适的话,请问你有没有什么推荐的呀

    • JiangMiao @ 2012-03-08 03:03:57

      关于node可以参考 https://github.com/muyuan/nodeclub ,如果使用node开发出来的代码将会是类似这样。nodeclub使用的是express + mongoose + eventproxy,如果可以接受controllers中的代码,则用node也无妨,在异步处理上还有Jscex,TameJs等辅助工具。
      前段时间又听闻了一个叫opa的语言http://opalang.org/,用于web开发,看上去挺美,不过没有去多去研究。
      我现在转回了PHP,因为PHP没有花枝招展的特性,虽说开发效率不及ruby与node,但成熟的环境下用给人非常稳健,踏实的感觉。

  7. yangzhu6263736 @ 2012-04-02 12:41:01 回复

    最近有一个LBS的项目要实现socket聊天。开始用php长驻实现php+libevent 。php是单进程单线程的。不能利用多核。单进程同一时间只能处理一个请求,于是只好开很多进程,于是又涉及到进程间通信, php不是很适合干这样的事情,libevent用上之后要加个定时器都没办法。 所以考虑用别的语言重写。 node.js看了一下下午就写出了demo. socket.io封装了很多底层实现,心跳,拆包等等,让IM的开发异常方便。这样的便捷让我觉得舒心多了。

    关于node.js,我知道node.js是单线程的。但是IO是放在其它线程中处理的。用node.js编程我们只能控制主线程。但这样的模型让node.js开发异常的方便。而语言实现本身的多线程(处理IO的线程)应该也能用光多核CPU的性能。 实际上很多时候语言的快慢不是很紧要。PHP很快,但加上数据库查徇之后就快不了了。

    我感觉PHP可以简单快速的开发WEB。不用考虑异步。node.js本身强项还是在socket这类IO操作更多的地方。node.js做WEB一定不如php方便快捷。php去做socket server本身也是强人所难。

    至于node.js的单进程 不能有效利用CPU的特点(这个只是我的猜测)。我也想到一个多进程的方式来处理。 在一台服务器上开多个进程监听多个socket端口。进程间的通信可以借用redis的pub/sub模式。也可以用zeromq之类的第三方工具。这样的模型很容易扩展。理论上一个进程可以很容易的移到另一台服务器。通信用的中间信 redis也是很高效和很容易扩展的。

    个人见解,希望跟博主探讨下。我本人没有C的开发经验。因为赶进度也没有时间去重新把C拿起来。所以也只能在能用最快时间捡起来的语言来实现。

    • ddouble @ 2012-05-28 06:48:08

      php libevent的定时器功能未写入php文档,亲自测试发现完全可以使用,请见 http://cn.php.net/manual/en/book.libevent.php 这页下方的注释。

      There are undocumented functions:
      event_timer_new() alias of event_new()
      event_timer_set(event, callback, args)
      event_timer_pending(event, timeout)
      event_timer_add() alias of event_add()
      event_timer_del() alias of event_del()

      注意 event_timer_add(ev, time) 函数的第二个参数单位不是秒
      // add a timer which will be timeout after 5 second.
      event_timer_add(ev, 5000000);

  8. Thynson @ 2012-04-19 18:58:04 回复

    你的例子仅仅是一个hello world级别的东西,没有考虑过数据库操作,文件I/O,服务器间通信等复杂的情形,对于一个复杂的业务逻辑,I/O才是制约因素,绝不是CPU。
    nodejs不光在http上异步执行,从数据库到文件读写,所有的I/O全部异步,
    遇到I/O稍多一些的业务逻辑时,nodejs的优势就体现出来了。
    比如写一个代理,请求目标页面需要100ms,那么一个线程就要阻塞100ms,对于同步逻辑来说想要高并发就必须多线程,多进程。而相比与多进程多线程方案,异步方案的阻塞最小,I/O调度开销最小,这就是nodejs快的原因,不是v8,而是异步。

    • Fay @ 2012-06-27 11:09:31

      你说的非常的对.

    • qiw209 @ 2012-08-25 23:33:26

      同意你的观点; 但是硬币的另外一面就是程序的复杂性会增加。

    • dfa @ 2013-06-04 15:09:39

  9. ddouble @ 2012-05-28 07:09:45 回复

    1.对于计算密集型的,比如字符处理,数学计算,这全得靠v8当家,并且这类运算也会阻塞node,和并发无关。
    2.对于io密集型的,比如网络,文件,数据库,这得靠异步,如果一次请求中可并行处理的io任务比较多,那么node应该是快的;如果一次请求中的io操作有前后关系,不能颠倒顺序,必须串行执行,则异步并不会提高这类请求的执行速度。

    *注意对于计算密集型的:除非你用另一个程序专门处理此类运算,则负责客户请求的node程序不会被阻塞,这实际上是把阻塞的运算转化为io等待。这么做似乎多此一举,但对于负责客户请求的node程序来说是有益的,他的阻塞减少了,可处理更多并发连接。

  10. 凋零 @ 2012-06-12 17:22:12 回复

    博主你似乎没明白NodeJS的异步是用来干嘛的.
    任何一种事物的出现都不可能达到一种十全十美的境界.用合适的语言和方法做合适的事情才是正道.
    用NODEJS并不擅长的领域去说他如何如何不好真的有意义么?

    像你说的.一次请求中的IO操作有前后关系.不能颠倒顺序.必须串行执行.这只是异步内的操作
    而请求的异步对于全并发而且还有操作前后关系的IO操作来说.这已经是优势了.

    举个现实的例子:
    这就像安检一样.我先要检查你是否有票(请求处理).才允许你做安检.安检的步骤1234是有顺序的(IO操作).
    如果一个请求处理需要1ms.一个IO操作需要20ms.
    那么我完成整个步骤需要21ms.
    NODEJS只开放了一个检票窗口和50个安检窗口
    如果是并发操作.理解为开了50个安检窗口(同时负责检票)

    那么在1000个人同时进行的时候.
    NODEJS: 1秒种可以进行1000次检票.和50次安检
    同步并发: 1秒种可以进行约50次检票+安检(因为同步阻塞关系.检票受安检速度制约)

    这时候来一个政界要员.说我只需要检票.不需要进行安检了
    NODEJS则直接帮他检票通过
    而同步并发则需要再等20秒(因为你必须将前边的1000人全部处理完才可以空出窗口)

    • JiangMiao @ 2012-06-12 17:51:00

      如果你说的“不擅长”是指逻辑复杂的网站,那么我么的观点是一致的。node的应用场景我在第二节也有述。关于安检例子同步的解决方法也有很多,最常用的方法是检票前端,或者设5个VIP通道+45个普通通道。

  11. ChironChan @ 2012-07-13 11:09:36 回复

    膜拜一下。另外说说个人观点,只有足够合适得解决方案,没有最优解决方案和放之四海皆准得方案。每个系统得成长都是不断的瓶颈点优化迭代,迭代的结果通常都是各方面都较优。所以我也支持博主的观点node快不是因为异步,同理,我也不认同node快是因为v8快。我们可以先把思考前提限定在单核cpu,node 和 php分别是单线程异步实现和多进程同步实现,我没有数据支撑,我只想说,这个情况下php需要大量进程切换,这是消耗cpu但没有落到业务处理实体的纯成本。回到多核CPU,为每个核分配一个node进程,这个时候的node的满负荷比 php的满负荷实际上CPU时间更多了。另外我们实际上不需要太考虑单机性能,更多应该考虑分布式性能吧?单纯疑问,单机性能再怎么提高都是有限的。我觉得选择php还是node,跟团队成员对技术熟悉程度关系比较大。

    • JiangMiao @ 2012-07-19 21:40:09

      我也同意不需要“太”考虑单机性能这点。现在对性能的提升还是以各种cache,架构为主,毕竟在数据库和磁盘上IO的压力远高于语言的压力。PHP这么多年在分布式上显然要比新秀node成熟很多。但同时我更支持在同等硬件下支持更多的请求或事务,还是一个平衡上的问题,选择合适的武器才是最重要的。

  12. Tiger @ 2012-08-22 15:27:34 回复

    异步就是为了解决高并发的问题,如果在并发量不大的情况下,和多线程模型比较性能没有明显提升。
    并发规模超大时(例如10000以上),worker的模型几乎就不能工作。

    >>如果数据库处理的很糟糕,等待时间则延长为 50ms,由于存在50个worker,那么相当于每个worker延长了1ms。
    这个没明白“相当于每个worker延长了1ms”。
    设想这时候有5000个并发,50个worker的模型会应为一个数据库的延迟而无法及时处理后面的请求,而异步模型可以。这就体现了充分利用等待时间。

  13. qiw209 @ 2012-08-25 23:32:20 回复

    充分利用时间的假设是一个应用里面有很多逻辑; 如果你在等待服务器响应的时候可以处理别的事情; 但是这个必然增加程序的复杂性,特别是异常处理的复杂性。

  14. jimthunderbird @ 2012-09-23 13:49:59 回复

    看一下这个有趣的项目https://github.com/phastlight/phastlight

    • JiangMiao @ 2012-09-25 01:53:42

      是满有趣,可惜这个项目受众目前看只能是一小撮爱折腾的GEEK。主要是PHP的根基不倾向大量的回调函数,闭包在PHP中也是5.3后的事。但多一个选择,作为PHP在异步处理上的补充探索肯定是要支持的。

  15. jimthunderbird @ 2012-09-25 13:20:36 回复

    个人认为现在最新版php已是5.4.7, php 5.3应渐渐成为主流,闭包应该成为一个常用的工具。希望能有更多的附加模块和类库建立在phastlight上,使其成为php的新应用领域。

    • JiangMiao @ 2012-09-25 21:40:27

      PHP 5.3成为主流那是肯定的,只是过程比较缓慢,基本不只望现在还在使用PHP 5.2的老旧系统会有大的变动,新系统的话PHP 5.3会更多些。这对Phastlight不是问题,Phastlight的受众群体肯定是新潮的。希望这个项目能走得更远更高吧。

    • snow @ 2012-10-09 17:47:31

      闭包的确是一个很重要的东西,但是否应该常用,持保留态度。
      某些地方用到能使代码清晰不少,但是大量使用,像nodejs一样,我就觉得过了,至少我是不太喜欢那种风格的,尤其逻辑复杂的时候,流程会变得很晦涩。
      一个语言有一个语言的风格,lisp之类你不用闭包就很难写代码。但是php就不至于了。喜欢nodejs的同学也没必要一定把大量闭包回调加到php上,难道想用php再造一个node?异步和事件也并非一定需要大量回调和闭包。比如,python的gevent就不错。

    • 崔钢 @ 2013-09-13 13:58:25

      我认为闭包很好,对于逻辑的影响的确是存在的。但是它可以有效的降低代码量,因此可以大大的消减维护的成本。

  16. zack @ 2012-10-10 18:09:50 回复

    首先我就不赞成用HTTP来展开论述,NODE.JS的官方从来没有说它就是WEB服务器.原文:
    for easily building fast, scalable network applications.
    总所周知的一个问题是,传统WEB SERVER依然瓶颈在数据库IO,语言的选择只有最合适的,所谓合适就是天时、地利、人和。PHP,NODE,PYTHON,RUBY什么的都不重要。
    NODE的特点是什么?
    event-driven, non-blocking I/O model
    事件驱动,非阻塞是关键,这是特性。讨论一个特性怎么怎么样,好不好还不如讨论自己喜欢哪类美女。“node.js成也异步,败也异步”可以修改为“茱莉亚罗伯茨成也大嘴美女,败也大嘴美女”
    把砖头砌在墙上,瓷砖铺到地上。

    • JiangMiao @ 2012-10-11 10:48:31

      写这篇文章时正是node.js在已经初有发展,也有express,backbone等框架。部份开发者也以异步为卖点布道node在网站开发的前途。而本文就其在开发具有复杂逻辑网站中的看法,同时与网站开发语言PHP进行比较。“把砖头砌在墙上,瓷砖铺到地上。”也正是本文的观点。

  17. zack @ 2012-10-10 18:19:39 回复

    补充一下,我是Ruby程序员,不喜欢PHP,但PHP好不好我不作评价,但Node.js的回调机制作为常写block的ruby程序员来说是非常优雅的写法,Node.js的那帮子推手很多都有Ruby背景,而Ruby社区里面很看不起PHP(原因的话知道了Rails的诞生就知为何了),coffeescript的语法完全就是ruby+python。所以我才说了以上那句语言的选择只有最合适的,你要是习惯了就是合适的,不习惯请自己编写Node.php。

    • JiangMiao @ 2012-10-11 11:18:15

      我从08年底起开始接触Ruby开发,现在还在使用Ruby写脚本,但没作为网站的开发语言,当年的放弃rails原因是语言慢,并写了文章从rails回到了php,经过这些年的发展,Ruby性能上也应有提升,只是惭愧3年了也并没有从php回到ruby。

      CoffeeScript的确是好语言,我非常喜欢甚至在其原基础上加入了简单异步语法支持建了分支ToffeeScript,也强烈推荐任何人js开发者学习CoffeeScript

  18. wenlin @ 2012-11-27 16:26:45 回复

    啊,Node.js 的异步、并发是 I/O 的异步和并行化吧,本身的程序执行仍是单核单线,计算总量不变。当然说它性能好,V8 肯定功不可没。

    就总体性能而言,不只是请求处理时间,还包括 QPS 等的度量。PHP 的同步开发模型在 I/O 时只能阻塞等待——当 Worker 被用满时就只能 502 了…,所以 QPS 有个并发限度。另一方面,开太多的 Worker,在进程间切换也会开销很大。。

    Node.js 相比 PHP,能更好地榨干 服务器 能力——,能同时处理更多的连接——,更大限度发挥各 I/O 子系统、I/O 硬件处理器的使用率…

  19. 彼岸 @ 2013-01-05 20:59:26 回复

    node.js 主要是吞吐量吧,就是1ms处理1000000个连接,是指这个快吧。另外标题党。。。。

  20. 海默 @ 2013-02-08 01:02:36 回复

    从程序猿的角度上来看:异步不能带来任何实质上的性能提升。
    从用户的角度上来看:异步处理能得到更快的响应(特别在并发量大的情况下)。
    大多数情况下,更快的响应就已经是先声夺人了。

  21. leizi @ 2013-04-04 09:48:44 回复

    小伙不要不懂装懂,快不是单个请求快,要勇于接受新知识。不要抓着php不放。

  22. zhang @ 2013-04-04 19:36:10 回复

    nodejs最大特点 用最简单的方式来进行异步io编程, 不说语言, 就异步io在编程来说仁者见仁智者见智,可用可不用, 从学习成本来说我给nodejs满分。什么语言技术都有优点和缺陷, 如果你的程序很少用到异步io, nodejs对你来说完全毫无意义。 也有很多技术可以规避io操作比如memcache, 如何权衡他们这才是重点,楼主做的测试根本没有体现nodejs的价值, 观点侧重同步编程,所以讨论意义不大。

  23. Fuzhou @ 2014-01-06 00:46:30 回复

    我的感觉是异步最大的问题在于难以控制执行流程。

    最近我的部门在使用 Node.js 写一些内部的测试服务器。其中有这个一个场景:第一个操作通过公有 API post 一个数据,然后通过一组内部的 API 直连那个服务器的后台检查数据是不是已经正确更新。内部的 API 实际上是需要查询外部的数据源。前后两组 API 是有依赖关系的:我们必须等前面的公有 API 调用结束之后才能做查询。

    我们第一版的服务器是通过 edge 调的 C# 接口。写这个服务器的哥们直接用了 edge 的同步调用。功能实现得倒是很快,但有一个问题:一是 edge 只能用在 Windows 上。我尝试着把它移植到 Linux 上时,用了 child_process,于是发现了一个问题:当 child process 执行外部命令时,它没有同步操作,于是我不得不把操作改成异步。但接下来的问题就是一个随机的错误。当收到请求时我建了一个子进程处理外部命令,但接下来这个子进程的回调有时候会在内部 API 做状态查询之后才被调用。结果状态查询就开始随机地失败。

    最后我找到的解决方案是 exec-sync,但这个方案在部署上多少也有问题:exec-sync 是 C++ 的模块,安装的机器上要有编译器。这其实是个安全隐患,不能在生产环境里用。幸亏只是个测试的服务器,也就由他去了。

    从这个意义上说,其实我不是很喜欢 node 的设计。它强调异步我不反对,但它应该提供某种同步的机制。Larry Wall 当年说,复杂的事情必须可能,简单的事情必须容易,而 Node 服从的实际上是另一个设计:复杂的事情必须容易,简单的事情我就不管。就我个人口味来说,这不是一个好的设计策略。

发表评论

电子邮件地址不会被公开。 必填项已用*标注