V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiao00000000
V2EX  ›  Node.js

在node.js中顺序流程驱动的模块应该如何优化?

  •  
  •   xiao00000000 · 2012-10-08 13:14:56 +08:00 · 3627 次点击
    这是一个创建于 4434 天前的主题,其中的信息可能已经有所发展或是发生改变。
    正在做一个APP的服务器端,外围的组建都是事件驱动的,只有内核还是顺序流程驱动。在内核里,要在每一次外围请求后遍历所有连接上的session的状态并做出相应处理,比如更改状态,分发通知。这样在连接数或业务逻辑增加后,内核在每一个请求周期所消耗的时间也就不断增加。由于node.js单线程的运行机制,内核就会成为瓶颈。考虑过用Cluster做负载均衡,但是由于请求后的业务逻辑流程比较碎片化,不容易移植到Cluster。且请求比较密集,担心“Experimental”状态中的Cluster会不稳定。

    个人感觉在这种情况下使用其他的开发工具,使用传统的线程由操作系统进行任务分派或者使用协程自行协调任务会比较好。不过在node.js下没有这方面的经验,不知道是否合适。

    请教各位,有没有比较好的方法解决这个问题?
    18 条回复    1970-01-01 08:00:00 +08:00
    phuslu
        1
    phuslu  
       2012-10-08 13:27:12 +08:00
    试下 async 或者 step
    hewigovens
        2
    hewigovens  
       2012-10-08 13:31:59 +08:00
    @phuslu 哇,你什么时候精通nodejs了
    phuslu
        3
    phuslu  
       2012-10-08 13:44:47 +08:00
    @hewigovens 汗, 比你差远啦.
    xiao00000000
        4
    xiao00000000  
    OP
       2012-10-08 14:50:57 +08:00
    @phuslu 我需要的不是control-flow类型的功能,而是不阻塞node.js的主线程,另起线程执行,完成后通知主线程的功能。
    step的源码我看了一下,是使用“process.nextTick”进行的处理,这样依然会在每一次耗时的callback的时候阻塞消息。
    Cluster是可以满足这个需求的,但是由于启动进程的开销、“Experimental”的状态、还有碎片化的业务逻辑没有选择这个功能。
    reus
        5
    reus  
       2012-10-08 15:43:28 +08:00
    虽然不懂nodejs,不过感觉可以把处理请求和“更改状态,分发通知”这些工作分开。用个任务队列,处理请求时只向队列里加任务,具体的执行由另外的进程/程序完成,这样就算逻辑再复杂也不会阻塞住处理请求的线程了
    xiao00000000
        6
    xiao00000000  
    OP
       2012-10-08 17:20:12 +08:00
    @reus node.js的Cluster模块就是实现这种功能的,不过没有采用的原因我上面也提到了。
    reus
        7
    reus  
       2012-10-08 17:49:29 +08:00
    @xiao00000000 看了下cluster的文档(http://nodejs.org/api/cluster.html#cluster_cluster),它只是多开启了几个node进程,并不是将请求处理和后台处理分开吧
    我说的是这类:https://github.com/LearnBoost/kue,在处理请求的时候只是jobs.create,然后另外跑一个程序执行jobs.progress。
    也就是处理请求和”更改状态,分发通知“在不同的进程/程序执行,这样就不会互相阻塞了。cluster也还是在同一个进程处理的
    xiao00000000
        8
    xiao00000000  
    OP
       2012-10-08 18:03:50 +08:00
    @reus 如果用Cluster来解决这个问题,那就是fork出多个node进程,由Master进程监听连接和请求分派,由多个Worker进程负责业务逻辑的负载均衡,然后当每次操作完成后通过message通知Master进程处理结果。这个应该和你说的是一样的。
    phuslu
        9
    phuslu  
       2012-10-08 18:04:19 +08:00
    @reus 从回帖来看楼主所说的"内核"操作估计是由一系列的的 CPU 密集型操作组成的, 这种硬碰硬的操作, nodejs/gevent 本身基本没啥好办法. 楼主不要 process.nextTick(callback), 那么觉得 SetTimeout(callback, 1) 如何呢, 呵呵.

    最后, 楼主需要的可能是 golang
    reus
        10
    reus  
       2012-10-08 18:27:16 +08:00
    @xiao00000000 原来如此
    xiao00000000
        11
    xiao00000000  
    OP
       2012-10-08 22:25:33 +08:00
    @phuslu 我觉得不能算是CPU密集型的操作,毕竟对每个session的操作并不是很费时,只是有可能会有大量的session需要遍历。
    如果用coroutine的话,类似下面的代码:
    for i in xrang(0, session_num):
    process_session(i)
    stackless.schedule()
    xiao00000000
        12
    xiao00000000  
    OP
       2012-10-08 22:28:03 +08:00
    @phuslu 我觉得我需要的其实是erlang。。。
    meteor
        13
    meteor  
       2012-10-22 10:44:14 +08:00
    Node.js底层是V8,主线程一个就够了.
    其他的交给Google的V8引擎.
    除非你的被把多线程管理的比Google好,一般不建议去碰底层的东西.
    JavaScript不是C/C++.
    aa88kk
        14
    aa88kk  
       2012-10-22 11:03:18 +08:00
    你说的这种应用类似聊天室, 这正是nodejs擅长的. 连接多少不重要, 反正延迟主要都是在io上, 可以先测试下实际的响应速度是否能达到要求. 业务逻辑慢的话,可以试试用c++写nodejs模块.
    clowwindy
        15
    clowwindy  
       2012-10-22 11:52:35 +08:00
    CPU 密集型任务可以放在另外的进程里,用 redis 做任务队列。
    xiao00000000
        16
    xiao00000000  
    OP
       2012-10-22 14:12:20 +08:00
    @clowwindy 如果要另起进程的话,就考虑Cluster了。其实node-fibers已经在考虑之列了。
    xiao00000000
        17
    xiao00000000  
    OP
       2012-10-22 14:15:36 +08:00
    @meteor 线程对于node.js确实不是好方案,所以我在考虑用coroutine处理。
    xiao00000000
        18
    xiao00000000  
    OP
       2012-10-22 14:16:53 +08:00
    @aa88kk 如果可以的话,我还是尽量不去写native-code的模块
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3390 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:38 · PVG 19:38 · LAX 03:38 · JFK 06:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.