Ank*_*rma 1 c++ v8 node.js libuv
因此,也许这个问题太过新手了,但是我仍然不知道为什么LIBUV在Node JS Architecture中占有一席之地?所以这是我对NodeJs架构的理解。
现在有疑问了
在此先感谢和快乐编码:)
小智 8
如果有人偶然发现这一点,并且由于它对OP的问题缺乏一个好的答案,我会尝试解决这个问题。
太长了;
让我们一一解答你的疑惑。
1. 由于 V8 支持 EcmaScript Javascript,这意味着它能够运行使用 EcmaScript 标准编写的回调。
回调并不意味着操作是异步的。回调与异步执行无关。回调只是一种搭载函数的方法,以便它在“异步操作”之后执行。
// example of synchronous callback
function main(cb) {
console.log('main code of the function');
cb(); // callback invocation here
}
main(function () {
console.log('in callback');
});
Run Code Online (Sandbox Code Playgroud)
现在是异步回调的示例
function getDataFromNetwork(url, cb) {
ajaxCall(url).then(cb);
}
getDataFromNetwork('http://some-endpoint', function (data) {
console.log(data);
});
Run Code Online (Sandbox Code Playgroud)
这是带有回调的异步调用。这里的 getDataFromNetwork 函数是异步的而不是回调。重点是回调只是一种在某件事之后运行代码的机制。在异步操作中,这是必需的。我们还要怎么做呢?正确的?
不! 如今,我们有 async-await,您可以在异步函数完成后运行代码,而无需使用回调。
所以你明白了吗?回调不是异步的。这并不是 libuv 的意义所在。
2. 因此,我们可以在 C++ 中添加文件系统访问、Http 服务器和数据库访问的代码,因为有库(头文件)提供了该功能,因为 Java 是用 C++ 编写的(如果我错了,请纠正我)并且 Java 具有此功能做同样的事情。
是的,我们可以为文件系统访问、Http 服务器添加大量代码。但为什么?我们确实已经有很多图书馆可以做到这一点。是的,它已经用 C 语言编写了,这就是 NodeJS 执行它们的方式。
Java已经有这个了?是的,但这也是 JVM 的一部分而不是核心 Java 语言,就像 libuv 是 NodeJS 运行时的一部分而不是核心 Javascript 语言一样。在这方面,Java 和 NodeJS 是相似的。只是 Java 有自己的 C++ 层,而 NodeJS 借用了 libuv。顺便说一句,libuv 主要是为 NodeJS 构建的
3. 现在,如果我们可以在 C++ 中添加这些功能,那么 Libuv 将在 NodeJs 架构图中占据什么位置。
我回答了这些功能如何在 C++ 中实现,现在让我们看看 libuv 在整个架构图中的位置。
让我们以 ajax/网络调用为例。你认为这是谁执行的?
NodeJS?不,它只是向其 C++ API(Node API)提供指令。
那么是 Node API 吗?不,它只是向 libuv 提供指令
那么是libuv吗?是的
计时器、文件访问、子进程等也是如此。
还要考虑一下,当 NodeJS 程序中触发大量网络调用、文件访问时,它在哪个进程上运行?谁安排他们?谁通知结果和失败。
这有很多事情要做。Java 有自己的线程池来做到这一点。Java 有自己的调度程序来调度线程。并且由于 Java 也为最终用户(程序员)提供了线程。使用 Java 线程来实现所有这些东西是有意义的。
但 NodeJS 是单线程的。当它可以从另一个库借用而不使它们成为 Javascript 的一部分时,为什么它应该有线程来执行 I/O 操作?毕竟,我们不会向程序员提供线程,所以为什么要麻烦呢?
另外,从历史上看,Javascript 只能在浏览器中运行。浏览器唯一可以访问的异步操作是网络请求、无文件访问、无数据库。所以我们没有太多的基石可供构建。
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()
Run Code Online (Sandbox Code Playgroud)
所以在这种情况下,libuv 看到我们正在尝试发出 HTTP 请求。libuv 和 node 都没有任何代码来处理与网络请求有关的所有这些低级操作。相反,libuv 将请求委托给底层操作系统。所以实际上是我们的操作系统执行真正的 HTTP 请求 Libuv 用于发出请求,然后它只是等待操作系统发出一个信号,表明某些响应已经返回到请求。因此,由于 Libuv 将已完成的工作委托给操作系统,因此操作系统本身决定是否制造新威胁。或者只是一般如何处理提出请求的整个过程。
检查以下文档-
https://nodejs.org/en/docs/meta/topics/dependencies/#libuv
另一个重要的依赖项是libuv,它是一个C库,用于将非阻塞I / O操作抽象为所有受支持平台之间的一致接口。它提供了处理文件系统,DNS,网络,子进程,管道,信号处理,轮询和流传输的机制。它还包括一个线程池,用于分担某些无法在操作系统级别异步完成的工作。
综上所述,V8提供了与运行JS文件有关的功能,但要使用网络,文件等系统资源,则使用libuv。它还提供了用于访问所提及资源的线程模型。