簡體   English   中英

為什么 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. 因此,如果您想提供任何新功能,我們可以在我們的 C++ 項目中嵌入 V8,並在 C++ 中使用新的 Embedded V8 附加新代碼。

現在有疑問了,

  1. 由於V8支持EcmaScript Javascript ,這意味着它能夠運行使用 EcmaScript 標准編寫的回調
  2. 所以我們可以在 C++ 中添加文件系統訪問、HTTP 服務器和數據庫訪問的代碼,因為有庫(頭文件)提供了該功能,因為 Java 是用 C++ 編寫的(如果我錯了,請糾正我)並且 Java 有能力做相同。
  3. 現在,如果我們可以在 C++ 中添加此功能,那么 Libuv 的位置會在 NodeJs 架構的圖片中出現嗎?

在此先感謝並祝您編碼愉快 :)

檢查以下文檔-

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

另一個重要的依賴項是libuv,它是一個C庫,用於將非阻塞I / O操作抽象為所有受支持平台之間的一致接口。 它提供了處理文件系統,DNS,網絡,子進程,管道,信號處理,輪詢和流傳輸的機制。 它還包括一個線程池,用於分擔某些無法在操作系統級別異步完成的工作。

綜上所述,V8提供了與運行JS文件有關的功能,但要使用網絡,文件等系統資源,則使用libuv。 它還提供了用於訪問所提及資源的線程模型。

如果有人偶然發現這一點,並且由於它對 OP 的問題沒有很好的答案,我會嘗試解決這個問題。

TLDR;

  • Javascript 語言不是異步的
  • Javascript 語言不是多線程的
  • 回調本身不是異步的,它們只是將您的代碼搭載到異步操作中。

讓我們一一解決您的疑問。

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'); 
});

現在一個異步回調的例子

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

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

這是一個帶有回調的異步調用。 這里的 getDataFromNetwork 函數是異步的而不是回調。 關鍵是回調只是在某事之后運行代碼的一種機制。 在異步操作中,這成為必需品。 我們還要怎么做呢? 對?

不! 現在我們有 async-await,你可以在異步函數完成后運行代碼而不使用回調。

所以你明白了嗎? 回調不是異步的。 這不是擁有 libuv 的重點。

2. 所以我們可以在 C++ 中添加用於文件系統訪問、Http 服務器和 DB 訪問的代碼,因為有庫(頭文件)提供了該功能,因為 Java 是用 C++ 編寫的(如果我錯了,請糾正我)並且 Java 有能力做同樣的事情。

是的,我們可以為文件系統訪問、Http 服務器添加大量代碼。 但為什么? 我們確實已經有很多圖書館可以做到這一點。 是的,它已經用 C 語言編寫了,這就是 NodeJS 執行它們的方式。

Java已經有了? 沒錯,但這也是 JVM 的一部分,而不是核心 Java 語言,就像 libuv 是 NodeJS 運行時的一部分,而不是核心 Javascript 語言一樣。 在這方面,Java 和 NodeJS 是相似的。 只是 Java 有自己的 C++ 層,而 NodeJS 為此借用了 libuv。 BTW libuv 主要是為 NodeJS 構建的

3. 現在,如果我們可以在 C++ 中添加這些功能,那么 Libuv 的位置在 NodeJs 架構圖上的位置是什么?

我回答了這些功能是如何在 C++ 中已經存在的,現在讓我們看看 libuv 在整個架構的這張圖片中的位置。

讓我們以 ajax/網絡調用為例。 你認為這是誰執行的?

節點JS? 不,它只是向其 C++ API(Node API)提供指令。

那么它是Node API嗎? 不,它只是給 libuv 提供指令

那么它是libuv嗎? 是的

計時器、文件訪問、子進程等也是如此。

還想一想當在 NodeJS 程序中觸發大量網絡調用、文件訪問時,它在哪個進程上運行? 誰安排他們? 誰通知結果和失敗。

這是很多事情要做。 Java 有自己的線程池來做到這一點。 Java 有自己的調度程序來調度線程。 並且因為 Java 也為最終用戶(程序員)提供線程。 使用 Java 線程實現所有這些東西是有意義的。

但是 NodeJS 是單線程的。 當它可以從另一個庫中借用它而不使它們成為 Javascript 的一部分時,為什么它應該有線程來執行 I/O 操作? 畢竟,我們不會為程序員提供線程,那何必呢?

同樣從歷史上看,Javascript 僅用於在瀏覽器中運行。 瀏覽器唯一可以訪問的異步操作是網絡請求,沒有文件訪問,沒有數據庫。 所以我們已經沒有很多基礎可以建立。

libuv模塊的職責與標准庫中的某些特定功能有關。 對於某些標准庫函數調用,節點C ++端和libuv決定完全在事件循環之外進行昂貴的計算,它們創建了一個稱為線程池的東西,該線程池是一系列四個線程,可用於運行計算密集型任務例如哈希函數。

默認情況下,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將工作委托給操作系統,因此操作系統本身將決定是否提出新的威脅。 或者只是通常如何處理發出請求的整個過程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM