在Node.js中扮演V8引擎的角色是什么?

时间:2016-01-23 22:39:43

标签: node.js multithreading concurrency v8 libuv

在过去的几天里,我一直在研究如何理解Node.js基于事件的样式如何处理比经典多线程方法更多的并发请求。最后是关于内存占用和上下文切换的问题,因为Node.js只使用几个线程(V8单线程和一堆C ++工作线程以及libuv的主线程)。

但是如何处理大量的线程请求,因为最后必须阻塞一些线程等待,例如,数据库读取操作。 我认为这个想法是:不是阻止客户端线程和数据库线程,而是只阻塞数据库线程,并在客户端线程结束时提醒它。

这就是我理解Node.js的工作原理。

我一直想知道Node.js能够处理HTTP请求的能力。 根据我到目前为止阅读的内容,我了解libuv是谁做的工作:

  

句柄代表能够执行某些操作的长寿命对象   活动时的操作。一些例子:一个准备句柄得到它   每个循环迭代在活动时调用一次回调,并且一个TCP   服务器句柄每次有一个调用时都会调用它的连接回调   新的联系。

enter image description here

因此,正在等待传入的http请求的线程是执行libuv事件循环的libuv的主线程。

所以当我们写

const http = require('http');

const hostname = '127.0.0.1';
const port = 1337;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

...我在libuv中放入一个回调,当请求进来时,它将在V8引擎中执行?

事件的顺序将是

  1. TCP数据包到达
  2. 操作系统创建一个事件并发送到事件循环
  3. 事件循环处理事件并创建V8事件
  4. 如果我在处理请求的匿名函数中执行阻塞代码,我将阻止V8线程。

    为了避免这种情况,我需要执行将在另一个线程中执行的非阻塞代码。我想这个“另一个线程”是libuv的主线程,其中

      

    网络I / O总是在一个线程中执行,每个循环的线程

    此线程不会阻止,因为使用异步操作系统调用。

      

    Linux上的epoll,OSX和其他BSD上的kqueue,SunOS上的事件端口   和Windows上的IOCP

    我还假设http.request正在使用libuv来实现这个目标。

    类似的,如果我需要做一些文件I / O而不阻塞V8线程
    我将使用Node的FileSystem模块。这次libuv主线程无法以非阻塞方式处理此问题,因为操作系统不提供此功能。

      

    与网络I / O不同,没有特定于平台的文件I / O原语   libuv可以依赖,所以目前的方法是运行阻塞文件   线程池中的I / O操作。

    在这种情况下,需要一个经典的线程池,以便不阻止libuv事件循环。

    现在,如果我需要查询数据库的所有责任,请不要阻止V8线程和libuv线程在驱动程序开发人员手中。 如果驱动程序不使用libuv,它将阻止V8引擎。

    相反,如果它使用libuv但底层数据库没有异步功能,那么它将block a worker thread

    最后,如果数据库提供异步功能,它将只阻止数据库线程。 (在这种情况下,我可以完全避免使用libuv并直接从V8线程调用驱动程序)

    如果这个结论正确描述,虽然以简单的方式,libuv和V8在Node.js中一起工作的方式,我看不到使用V8的好处,因为我们可以直接在libuv中完成所有工作(除非目标是给开发人员一种允许以更简单的方式编写基于事件的代码的语言。)

3 个答案:

答案 0 :(得分:0)

据我所知,差异主要是异步I / O.在传统的每请求进程或每请求线程数的服务器中,I / O,尤其是网络I / O,是传统的同步I / O. Node.js使用的线程少于Apache或其他什么,并且它可以处理流量主要是因为它使用异步网络I / O.

Node.js需要V8来实际解释JS代码并将其转换为机器代码。 Libuv需要做真正的I / O.我不仅仅知道:)

答案 1 :(得分:0)

有一篇关于node.js V8引擎的优秀帖子:How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code。它解释了引擎的许多深入细节方面以及使用它时的一些很好的建议。

简而言之,V8 engine(和其他javascript engines)的作用是执行javascript代码。但是,与其他人相比,V8 engine获得了高性能执行。

  

V8将JavaScript代码转换为更高效的机器代码   使用口译员。它将JavaScript代码编译为机器代码   通过实现JIT(即时)编译器执行...

答案 2 :(得分:0)

I / O是非阻塞的,并且通过libuv异步,底层使用像epoll或类似的操作系统原语,具体取决于平台,使i / o非阻塞。当fd上的事件(例如tcp套接字)发生时,Nodejs事件循环获取一个排队的事件