日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
好玩的Sendfile---探索Node.Js中更快的數(shù)據(jù)傳輸方式

本文轉(zhuǎn)載自微信公眾號「編程雜技」,作者theanarkh。轉(zhuǎn)載本文請聯(lián)系編程雜技公眾號。

創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供石阡網(wǎng)站建設(shè)、石阡做網(wǎng)站、石阡網(wǎng)站設(shè)計(jì)、石阡網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、石阡企業(yè)網(wǎng)站模板建站服務(wù),10多年石阡做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。

在Node.js中,當(dāng)我們給前端返回一個靜態(tài)文件的時候,我們通常會把文件先讀進(jìn)內(nèi)容,然后通過socket接口寫到底層,從而返回給前端。無論是一次性讀取到內(nèi)存還是使用流式的方式,都不可避免地要把數(shù)據(jù)從內(nèi)核復(fù)制到用戶層,再把數(shù)據(jù)復(fù)制到內(nèi)核,這是一種低效的方式,因?yàn)槎嗔藷o效的復(fù)制。在nginx中,可以通過sendfile指令提供效率。Node.js的copyFile底層使用了sendfile系統(tǒng)調(diào)用,但是網(wǎng)絡(luò)IO的時候,沒有使用該API。因?yàn)镹ode.js通過隊(duì)列的方式,控制數(shù)據(jù)的寫入。那么是否可以實(shí)現(xiàn)sendfile的方式來提供這網(wǎng)絡(luò)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通過把內(nèi)核完成數(shù)據(jù)的傳輸,減少了內(nèi)核和用戶層的數(shù)據(jù)復(fù)制,從而提高了效率。下面我們通過napi寫一個addon來實(shí)現(xiàn)這個功能。

 
 
 
 
  1. #include   
  2. #include   
  3. #include  
  4. #include  
  5. #include  
  6. static napi_value copyFile(napi_env env, napi_callback_info info) { 
  7.   size_t argc = 3; 
  8.   napi_value args[3]; 
  9.   // 拿到j(luò)s層的入?yún)?,這里是三個 
  10.   napi_get_cb_info(env, info, &argc, args, NULL, NULL); 
  11.   int fd1; 
  12.   int fd2; 
  13.   int len; 
  14.   // js傳入的是一個數(shù)字,v8轉(zhuǎn)成了對象,這里再次把入?yún)⑥D(zhuǎn)成int型 
  15.   napi_get_value_int32(env, args[0], &fd1); 
  16.   napi_get_value_int32(env, args[1], &fd2); 
  17.   napi_get_value_int32(env, args[2], &len); 
  18.   int writed = sendfile(fd2, fd1, 0,len); 
  19.   napi_value ret; 
  20.   napi_create_int32(env, writed, &ret); 
  21.   return ret; 
  22.  
  23. napi_value Init(napi_env env, napi_value exports) { 
  24.   napi_value func; 
  25.   // 創(chuàng)建一個函數(shù)并且設(shè)置為exports對象的getArray屬性的值 
  26.   napi_create_function(env, 
  27.                       NULL, 
  28.                       NAPI_AUTO_LENGTH, 
  29.                       copyFile, 
  30.                       NULL, 
  31.                       &func); 
  32.   napi_set_named_property(env, exports, "copyFile", func); 
  33.   return exports; 
  34. NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

下面我們看看怎么使用。首先用這個addon來復(fù)制文件,類似Node.js的copyyFile

 
 
 
 
  1. const fs= require('fs'); 
  2. const { copyFile } = require('./build/Release/sendfile.node'); 
  3. const { 
  4.   O_WRONLY, 
  5.   O_CREAT, 
  6. } = fs.constants; 
  7. async function test() { 
  8.   const [fd1, fd2] = await Promise.all([openFile('1.txt', 'r'), openFile('2.txt', O_WRONLY | O_CREAT)]); 
  9.   const { size } = await getFileInfo(fd1); 
  10.   console.log(copyFile(fd1, fd2, size)); 
  11.   fs.close(fd1, () => {}); 
  12.   fs.close(fd2, () => {}); 
  13. function openFile(filename, mode) { 
  14.   return new Promise((resolve, reject) => { 
  15.     fs.open(filename, mode, (err, fd) => { 
  16.       if (err) { 
  17.         reject(err); 
  18.       } else { 
  19.         resolve(fd); 
  20.       } 
  21.     }); 
  22.   })} 
  23.  
  24. function getFileInfo(fd) { 
  25.   return new Promise((resolve, reject) => { 
  26.     fs.fstat(fd, (err, stat) => { 
  27.       if (err) { 
  28.         reject(err) 
  29.       }else { 
  30.         resolve(stat); 
  31.       } 
  32.     }); 
  33.   }) 
  34. test(); 

執(zhí)行上面代碼,我們可以看到文件會成功復(fù)制2.txt。接著我們再來試一下網(wǎng)絡(luò)IO的場景。

 
 
 
 
  1. const fs= require('fs'); 
  2. const http = require('http'); 
  3. const { copyFile } = require('./build/Release/sendfile.node'); 
  4. const server = http.createServer(async (req, res) => { 
  5.   const fd = await openFile('1.txt', 'r'); 
  6.   const { size } = await getFileInfo(fd); 
  7.   const ret = copyFile(fd, res.socket._handle.fd, size); 
  8.   res.socket.end(); 
  9. }).listen(8002); 
  10.  
  11. const { 
  12.   O_WRONLY, 
  13.   O_CREAT, 
  14. } = fs.constants; 
  15.  
  16. function openFile(filename, mode) { 
  17.   return new Promise((resolve, reject) => { 
  18.     fs.open(filename, mode, (err, fd) => { 
  19.       if (err) { 
  20.         reject(err); 
  21.       } else { 
  22.         resolve(fd); 
  23.       } 
  24.     }); 
  25.   })} 
  26.  
  27. function getFileInfo(fd) { 
  28.   return new Promise((resolve, reject) => { 
  29.     fs.fstat(fd, (err, stat) => { 
  30.       if (err) { 
  31.         reject(err) 
  32.       }else { 
  33.         resolve(stat); 
  34.       } 
  35.     }); 
  36.   })} 

以上代碼首先啟動一個http服務(wù)器,然后收到請求的時候,通過addon調(diào)用sendfile給前端返回對應(yīng)的內(nèi)容,最后關(guān)閉連接。結(jié)果如下。

sendfile似乎在網(wǎng)絡(luò)IO中可以應(yīng)用了,但只是一個demo的思路,后續(xù)有時間繼續(xù)研究分析。


本文題目:好玩的Sendfile---探索Node.Js中更快的數(shù)據(jù)傳輸方式
文章分享:http://www.dlmjj.cn/article/dhichoj.html