我对Node js的架构和性能有疑问.
我已经完成了一些关于这个主题的阅读(包括Stack Overflow),我还有几个问题.我想做两件事:
Node具有单线程,异步事件处理架构
单线程 - 有一个事件线程可以调度异步工作(结果通常是I/O但可以是计算)并执行回调执行(即处理异步工作结果).
事件线程在无限的"事件循环"中运行,执行上述2个作业; a)通过调度异步工作来处理请求,以及b)注意先前的异步工作结果已准备好并执行回调以处理结果.
这里的常见类比是餐厅订单接收者:活动线程是一个超级快速的服务员,从餐厅接受订单(服务请求)并将订单发送到厨房准备(发送异步工作),但也注意到当食物准备就绪(异步结果)并将其送回表格(回调执行).
服务员不做任何食物; 他的工作是尽快从餐厅到厨房来回走动.如果他陷入餐厅的订单陷入困境,或者如果他被迫回到厨房准备其中一餐,系统就变得效率低下并且系统吞吐量受损.
异步 由请求(例如Web请求)产生的异步工作流在逻辑上是一个链:例如
FIRST [ASYNC: read a file, figure out what to get from the database] THEN
[ASYNC: query the database] THEN
[format and return the result].
Run Code Online (Sandbox Code Playgroud)
上面标有"ASYNC"的作品是"厨房工作","FIRST []"和"THEN []"代表服务员开始回调的参与.
像这样的链以3种常见方式以编程方式表示:
嵌套函数/回调
用.then()链接的承诺
async()异步结果的异步方法.
所有这些编码方法都非常相同,尽管asynch/await似乎是最干净的,并且使得异步编码的推理更容易.
问题
我的问题涉及使用OS支持的异步操作,实际执行异步工作的人,以及这种体系结构比"按每个请求生成一个线程"(即多个cooks)体系结构更高效的方式:
通过使用跨平台异步库libuv设计节点库是异步的,对吗?这里的想法是libuv为节点(在所有平台上)提供一致的异步I/O接口,但随后使用平台相关的异步I/O操作吗?在I/O请求"一直向下"到OS支持的异步操作的情况下,谁正在"做工作"等待I/O返回并触发节点?它是内核,使用内核线程吗?如果不是,谁?无论如何,这个实体可以处理多少个请求?
我已经读过libuv也在内部使用了一个线程池(通常是pthreads,每个核心一个?).这是为了"包装"不像"async"那样"完全向下"的操作,这样一个线程就可以用来等待同步操作了,所以libuv可以提供一个异步API吗?
关于性能,用于解释类似节点的体系结构可以提供的性能提升的通常说明是:画出(可能更慢和更胖)线程每请求方法 - 产生的延迟,CPU和内存开销一堆线程只是坐在等待I/O完成(即使他们没有忙碌等待)然后将它们拆除,节点很大程度上让它消失了,因为它使用了一个长期存在的事件线程来将异步I/O发送到OS /内核,对吗?但是在一天结束的时候,SOMETHING正在睡眠互联网并在I/O准备就绪时被唤醒...是否认为内核比用户线程更有效?最后,请问由libuv的线程池处理的情况怎么样...这似乎与每个请求线程的方法类似,除了使用池的效率(避免启动和拆除),但是在这种情况下,当有很多请求并且池有积压时会发生什么?...延迟增加,现在你做的比每个请求的线程更糟,对吧?