您好,登錄后才能下訂單哦!
這篇文章主要介紹“Node.Js中怎么實現更快的數據傳輸”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Node.Js中怎么實現更快的數據傳輸”文章能幫助大家解決問題。
在Node.js中,當我們給前端返回一個靜態文件的時候,我們通常會把文件先讀進內容,然后通過socket接口寫到底層,從而返回給前端。無論是一次性讀取到內存還是使用流式的方式,都不可避免地要把數據從內核復制到用戶層,再把數據復制到內核,這是一種低效的方式,因為多了無效的復制。在nginx中,可以通過sendfile指令提供效率。Node.js的copyFile底層使用了sendfile系統調用,但是網絡IO的時候,沒有使用該API。因為Node.js通過隊列的方式,控制數據的寫入。那么是否可以實現sendfile的方式來提供這網絡IO的效率。首先我們看一下sendfile的好處是什么。
sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.
我們看到sendfile通過把內核完成數據的傳輸,減少了內核和用戶層的數據復制,從而提高了效率。下面我們通過napi寫一個addon來實現這個功能。
#include <sys/sendfile.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <node_api.h> static napi_value copyFile(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args[3]; // 拿到js層的入參,這里是三個 napi_get_cb_info(env, info, &argc, args, NULL, NULL); int fd1; int fd2; int len; // js傳入的是一個數字,v8轉成了對象,這里再次把入參轉成int型 napi_get_value_int32(env, args[0], &fd1); napi_get_value_int32(env, args[1], &fd2); napi_get_value_int32(env, args[2], &len); int writed = sendfile(fd2, fd1, 0,len); napi_value ret; napi_create_int32(env, writed, &ret); return ret; } napi_value Init(napi_env env, napi_value exports) { napi_value func; // 創建一個函數并且設置為exports對象的getArray屬性的值 napi_create_function(env, NULL, NAPI_AUTO_LENGTH, copyFile, NULL, &func); napi_set_named_property(env, exports, "copyFile", func); return exports; } NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
下面我們看看怎么使用。首先用這個addon來復制文件,類似Node.js的copyyFile
const fs= require('fs'); const { copyFile } = require('./build/Release/sendfile.node'); const { O_WRONLY, O_CREAT, } = fs.constants; async function test() { const [fd1, fd2] = await Promise.all([openFile('1.txt', 'r'), openFile('2.txt', O_WRONLY | O_CREAT)]); const { size } = await getFileInfo(fd1); console.log(copyFile(fd1, fd2, size)); fs.close(fd1, () => {}); fs.close(fd2, () => {}); } function openFile(filename, mode) { return new Promise((resolve, reject) => { fs.open(filename, mode, (err, fd) => { if (err) { reject(err); } else { resolve(fd); } }); })} function getFileInfo(fd) { return new Promise((resolve, reject) => { fs.fstat(fd, (err, stat) => { if (err) { reject(err) }else { resolve(stat); } }); }) } test();
執行上面代碼,我們可以看到文件會成功復制2.txt。接著我們再來試一下網絡IO的場景。
const fs= require('fs'); const http = require('http'); const { copyFile } = require('./build/Release/sendfile.node'); const server = http.createServer(async (req, res) => { const fd = await openFile('1.txt', 'r'); const { size } = await getFileInfo(fd); const ret = copyFile(fd, res.socket._handle.fd, size); res.socket.end(); }).listen(8002); const { O_WRONLY, O_CREAT, } = fs.constants; function openFile(filename, mode) { return new Promise((resolve, reject) => { fs.open(filename, mode, (err, fd) => { if (err) { reject(err); } else { resolve(fd); } }); })} function getFileInfo(fd) { return new Promise((resolve, reject) => { fs.fstat(fd, (err, stat) => { if (err) { reject(err) }else { resolve(stat); } }); })}
以上代碼首先啟動一個http服務器,然后收到請求的時候,通過addon調用sendfile給前端返回對應的內容,最后關閉連接。結果如下。
關于“Node.Js中怎么實現更快的數據傳輸”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。