【问题标题】:What role plays the V8 engine in Node.js?V8 引擎在 Node.js 中扮演什么角色?
【发布时间】:2016-01-23 22:39:43
【问题描述】:

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

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

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

我一直想知道是什么赋予了 Node.js 处理 HTTP 请求的能力。 根据我到目前为止所读到的内容,我知道libuv 是谁做的:

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

所以,等待传入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 事件

如果我在处理请求的匿名函数中执行阻塞代码,我将阻塞 V8 线程。

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

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

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

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

我还假设http.request 正在使用 libuv 来实现这一点。

类似地,如果我需要在不阻塞 V8 线程的情况下进行文件 I/O
我将使用 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 中完成所有工作(除非目标是为开发人员提供一种允许以更简单的方式编写基于事件的代码的语言。

【问题讨论】:

    标签: node.js multithreading concurrency v8 libuv


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      有一篇关于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 (Just-In-Time) 编译器 ...

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-25
          • 2020-12-24
          • 1970-01-01
          • 2010-10-18
          • 2023-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多