为什么在 Node JS 中需要 LIBUV?

Why is LIBUV needed in Node JS?

所以,也许这个问题太菜鸟和新手了,但我仍然不知道为什么 LIBUV 在 Node JS 架构中占有一席之地?所以这里是我对NodeJs架构的理解。

  1. Node Js 基于 V8
  2. V8 能够运行使用EcmaScript 标准编写的代码
  3. V8 是用 C++ 编写的。
  4. 因此,如果您想提供任何新功能,我们可以将 V8 嵌入到我们的 C++ 项目中,并在 C++ 中使用新的嵌入式 V8 附加新代码。

现在疑惑来了,

  1. 因为 V8 支持 EcmaScript Javascript 这意味着它有能力 运行 使用 EcmaScript.
  2. 标准编写的回调
  3. 所以我们可以在 C++ 中添加用于文件系统访问、HTTP 服务器和数据库访问的代码,因为有库(头文件)提供了该功能,因为 Java 是用 C++ 编写的(如果我是,请纠正我错误)并且 Java 有能力做同样的事情。
  4. 现在,如果我们可以在 C++ 中添加此功能,那么 Libuv 在 NodeJs 体系结构中的地位是什么。

提前致谢 快乐编码:)

查看下面的文档 -

https://nodejs.org/en/docs/meta/topics/dependencies/#libuv

Another important dependency is libuv, a C library that is used to abstract non-blocking I/O operations to a consistent interface across all supported platforms. It provides mechanisms to handle file system, DNS, network, child processes, pipes, signal handling, polling and streaming. It also includes a thread pool for offloading work for some things that can't be done asynchronously at the operating system level.

所以综上所述,V8提供了运行JS文件相关的功能,但是要使用网络,文件等系统资源,则需要使用libuv。它还提供了一个线程模型来访问提到的资源。

libuv 模块的职责与标准库中的某些特定函数相关。对于一些标准库函数调用,节点 C++ 端和 libuv 决定在事件循环之外进行昂贵的计算 entirely.They 制作一个叫做 线程池的东西 线程池是一个系列可用于 运行 计算密集型任务(例如哈希函数)的四个线程。

默认情况下,libuv 在此线程池中创建四个线程。因此,这意味着除了用于事件循环的那个线程之外,还有四个其他线程可用于卸载需要在我们的应用程序内部发生的昂贵计算。节点标准库中包含的许多函数将自动使用此线程池。

现在这个线程池的存在意义重大。很明显 Node.js 不是真正的单线程


Libuv 还允许节点访问操作系统的底层文件系统,例如网络。因此,正如节点标准库具有一些使用 libuv 线程池的函数一样,它也具有一些使用通过 libuv 内置到底层操作系统中的代码的函数。

简单的 Http 请求

const https=require(“https”)
const start=Date.now()
https.request(“https://www.google.com”,res=>{
res.on(“data”,()=>{} ) 
res.on(“end”,()=>{console.log(Date.now()-start)  }) }).end()

所以在这种情况下,libuv 看到我们正在尝试发出 HTTP 请求。 libuv 和 node 都没有任何代码来处理所有这些与网络请求相关的低级操作。相反,libuv 将请求委托给底层操作系统。所以实际上是我们的操作系统执行真正的 HTTP 请求 Libuv 用于发出请求,然后它只是等待操作系统发出一个信号,表明一些响应已经返回到请求。因此,由于 Libuv 将完成的工作委托给操作系统,操作系统本身决定是否制造新威胁。或者只是一般如何处理发出请求的整个过程。

如果有人偶然发现这个问题,并且由于它对 OP 的问题没有很好的回答,我会尝试解决这个问题。

TLDR;

  • Java脚本语言不是异步的
  • Java脚本语言不是多线程的
  • 回调本身不是异步的,它们只是将您的代码搭载到异步操作中。

让我们一一解答你的疑惑

1.由于 V8 支持 EcmaScript Javascript,这意味着它有能力 运行 使用 EcmaScript 标准编写的回调。

回调并不意味着操作是异步的。回调与异步执行无关。回调只是一种搭载函数的方式,以便它在 'something asynchronous'.

之后执行
// example of synchronous callback

function main(cb) {
  console.log('main code of the function');
  cb(); // callback invocation here
}

main(function () { 
  console.log('in callback'); 
});

现在一个异步回调的例子

function getDataFromNetwork(url, cb) {
  ajaxCall(url).then(cb);
}

getDataFromNetwork('http://some-endpoint', function (data) {
  console.log(data);
});

这是一个带回调的异步调用。这里的 getDataFromNetwork 函数是异步的,不是回调。关键是回调只是 运行 在某事之后编写代码的一种机制。在异步操作中,这成为必需。我们还能怎么做?对吗?

没有! 现在我们有了 async-await,您可以在其中 运行 异步函数完成后不使用回调的代码。

你明白了吗?回调不是异步的。这不是拥有 libuv 的重点。

2。所以我们可以在 C++ 中添加用于文件系统访问、Http 服务器和数据库访问的代码,因为有库(头文件)提供了该功能,因为 Java 是用 C++ 编写的(如果我错了请纠正我)和 Java 有能力做同样的事情。

是的,我们可以为文件系统访问、Http 服务器添加大量代码。 但是为什么呢? 我们已经有很多图书馆可以做到这一点。是的,它已经用 C 语言编写,这就是 NodeJS 执行它们的方式。

Java 已经有了吗? 是的,但这也是 JVM 的一部分而不是核心 Java 语言,就像 libuv 是 NodeJS 运行time 的一部分而不是核心 Javascript 语言一样。在这方面 Java 和 NodeJS 是相似的。只是 Java 有自己的 C++ 层,而 NodeJS 为此借用了 libuv。顺便说一句,libuv 主要是为 NodeJS 构建的

3。现在,如果我们可以在 C++ 中添加这些功能,那么 Libuv 在 NodeJs 体系结构中的位置是什么。

我回答了这些功能是如何在 C++ 中实现的,现在让我们看看 libuv 在这张整个架构图中的位置。

让我们以 ajax/network 调用为例。你认为是谁执行的?

节点?不,它只是向其 C++ API(节点 API)提供指令。

那么是节点API吗?不,它只是给 libuv

指令

那是libuv吗?是的,就是

计时器、文件访问、子进程等也是如此

还想当在 NodeJS 程序中触发大量网络调用、文件访问时,它在什么进程上 运行s?谁安排他们?谁通知结果和失败。

这有很多事情要做。 Java 有自己的线程池来执行此操作。 Java 有自己的调度程序来调度线程。并且由于 Java 也为最终用户(程序员)提供了线程。使用 Java 个线程来实现所有这些东西是有意义的。

但是 NodeJS 是单线程的。当它可以从另一个库借用它而不使它们成为 Java 脚本的一部分时,为什么它应该有线程来执行 I/O 操作?毕竟,我们不会为程序员提供线程,所以何必呢?

此外,从历史上看,Java脚本仅适用于 运行 在浏览器中。浏览器唯一可以访问的异步操作是网络请求,没有文件访问,没有数据库。所以我们没有很多基石可以建立。